IntentBest Practices

Intent Best Practices


Design intents as your API contract

Intents are the boundary between callers and Causet. Changing input schema is a breaking change for every client. Version carefully and document rejection codes.

Prefer many small, focused intents over one mega-intent with optional fields.


Put all validation in preflight

Don’t skip preflight for performance — it runs before any state change. Business rules that reject invalid commands belong here, not in application middleware.


Keep core focused on the target entity

Cross-stream state writes in core are not allowed. Use op: submit in side_effects to trigger an action on another stream.


Side effects run after commit

If a side effect fails, the ledger write is not rolled back. Design idempotent consumers for emitted events. Use submit for work that must survive parent failures.


Common mistakes

Putting HTTP calls in rules. Rules must be deterministic. Call external APIs from a service that consumes Kafka events, or use op: decision for AI providers.

Using now() or random(). Forbidden. Build IDs with concat(). Use event.ts for timestamps.

Mixing {expr: ...} and plain string syntax. Rule when: takes {expr: "..."}. filter.where takes plain strings.

Naming input fields type. Makes event.type ambiguous in expressions.

Emitting unregistered events. Every event_type in emit must exist in your events: registry before compile.


Next steps