Defining Intents
Intents are declared under the actions: key in .actions.causet files. Each entry names an intent type your API submits to the runtime.
Full anatomy
actions:
PURCHASE_TICKET:
state: ticket # entity stream this intent operates on
entity_id_expr: intent.ticket_id
input: # validated before rules run
ticket_id: { type: string, required: true }
user_id: { type: string, required: true }
show_id: { type: string, required: true }
quantity: { type: integer, required: true }
preflight:
rules: [ ... ]
core:
rules: [ ... ]
side_effects:
rules: [ ... ]state
The entity stream (state definition) this intent targets. Must match a declared state: block in your app.
state: userThe runtime loads the entity snapshot for (stream, entity_id) before evaluating rules.
entity_id_expr
Expression that resolves which entity instance to load:
entity_id_expr: intent.user_idBoth intent.<field> and event.<field> compile here. Convention is intent.<field> for command submission.
input
Typed schema for the intent payload. The compiler validates types; the runtime rejects missing required fields before preflight runs.
input:
user_id: { type: string, required: true }
artist_id: { type: string, required: true }
limit: { type: integer, required: false }Access input in expressions as intent.user_id, intent.artist_id, etc.
Tip: Avoid naming input fields
type— it collides withevent.typein expressions.
Rule blocks
Every intent has up to three rule sections:
| Block | Purpose | Allowed ops |
|---|---|---|
preflight | Validation before mutation | reject, lookup, if, read-only checks |
core | State mutation | set, add, sub, push, filter, relationships |
side_effects | Fan-out after commit | emit, submit, schedule, decision |
See Rules for phase semantics and Operations for the full op reference.
Minimal example
actions:
FOLLOW_ARTIST:
state: user
entity_id_expr: intent.user_id
input:
user_id: { type: string, required: true }
artist_id: { type: string, required: true }
preflight:
rules:
- name: reject_self_follow
when: { expr: "intent.user_id == intent.artist_id" }
then:
- op: reject
code: CANNOT_FOLLOW_SELF
message: "A user cannot follow themselves"
core:
rules:
- name: record_follow
when: {}
then:
- op: push
path: /following
value: intent.artist_id
side_effects:
rules:
- name: emit_followed
then:
- op: emit
event_type: ARTIST_FOLLOWED
payload:
user_id: intent.user_id
artist_id: intent.artist_idNext steps
- Rules — when clauses, cross-stream validation
- Operations — every op with required fields
- Examples — end-to-end intent patterns