actions — Commands + Rules
Intents define commands and the rules that execute when they are submitted. In the DSL they are declared under the actions: key. Rules execute in three phases: preflight → core → side_effects.
actions:
CHECK_IN_TO_SHOW:
state: user
entity_id_expr: intent.user_id # optional; defaults to entity_key
description: "Record a concert check-in"
input:
user_id: { type: string, required: true }
show_id: { type: string, required: true }
venue_id: { type: string, required: true }
preflight:
rules:
- name: reject_duplicate_checkin
when:
expr: "contains(entity.checkins, event.show_id)"
then:
- op: reject
code: ALREADY_CHECKED_IN
message: "Already checked in to this show"
core:
rules:
- name: record_checkin
when: {}
then:
- op: push
path: /checkins
value: event.show_id
- op: add
path: /shows_attended
value: 1
- op: emit
event_type: SHOW_CHECK_IN_CREATED
payload:
user_id: event.user_id
show_id: event.show_id
venue_id: event.venue_id
side_effects:
rules:
- name: notify_friends
when: {}
then:
- op: submit
intent_type: DELIVER_CHECKIN_NOTIFICATION
payload:
user_id: event.user_id
show_id: event.show_idPhases
| Phase | Purpose | Allowed ops |
|---|---|---|
preflight | Validation; abort with reject | reject, read-only checks, LOOKUP_FIELD |
core | Primary state mutations + emit events | All mutation ops, emit, emit_each, relationship_create, relationship_remove |
side_effects | External I/O after core commits; failures do not roll back core | emit, emit_each, submit, schedule, decision |
Rule structure
- name: my_rule_name # snake_case; required
priority: 100 # lower = runs first; default 100
when:
expr: "entity.count > 0" # optional condition
then:
- op: ...when: {} (empty object) means the rule always runs when the action is triggered.
⚠️
when.expr vs filter.where — different shapes
| Clause | Expected shape |
|---|---|
Rule when: expr: | Object: when: { expr: "condition" } |
filter / remove / find where: | Plain string: where: "it.qty > 0" |
Using where: { expr: "..." } under filter causes ClassCastException: LinkedHashMap cannot be cast to String at compile time.
Next steps
- Operations — surgical reference for every
op: - Rule Execution — phase order and modes
- Expressions — scopes and functions