Intent Expressions
Expressions are strings evaluated by the rules engine at runtime. They must be deterministic — no external I/O, no wall-clock time, no randomness.
Context accessors
| Context | Accessor |
|---|---|
| Intent input | intent.field_name |
| Event payload | event.field_name |
| Entity state | entity.field_name (dot notation) |
| Iterator | it.field (filter/find/remove), item.field (emit_each/for_each) |
| Variable | var_name.field (from find...as or clone...as) |
| Cross-stream | LOOKUP_FIELD('stream_name', id_expr, '/path') |
Examples
when: { expr: "entity.status == 'active' && intent.quantity > 0" }
- op: set
path: /display_name
value: "concat(intent.first_name, ' ', intent.last_name)"
- op: emit
event_type: ORDER_PLACED
payload:
order_id: "concat('ord_', intent.user_id, '_', event.ts)"
total: entity.cart.total_centsString helpers like concat() are available. See DSL Expressions for the full function list.
Forbidden in expressions
| Forbidden | Use instead |
|---|---|
now() | event.ts (event timestamp) |
random(), uuid() | Deterministic IDs: concat('prefix_', intent.id) |
| HTTP / JDBC / external APIs | emit + external consumer, or decision in side_effects |
| JVM reflection | Not supported |
Rules that call forbidden functions fail at compile time or produce non-replayable behavior.
{expr: "..."} vs plain strings
| Location | Syntax |
|---|---|
Rule when: | { expr: "entity.active == true" } |
if.expr | Plain string: "entity.active == true" |
filter.where, remove.where, find.where | Plain string: "it.active == true" |
Using {expr: ...} under filter.where causes a compile-time error.
Next steps
- Rules — where expressions appear in each phase
- Best Practices — expression pitfalls
- Operations — ops that take expression fields