AI Best Practices
Keep AI in side_effects
The compiler rejects op: decision in preflight and core. LLM calls are external I/O — they appear in timeline but are not replayed when rebuilding state from the ledger.
Pattern: persist entity state and emit the primary domain event in core; run AI in side_effects afterward.
Design strict input and output schemas
The runtime validates LLM JSON against your output: schema before emitting. Tight schemas prevent silent drift:
- Use
required: trueon every field you depend on - Prefer enums in the prompt (“priority: low|normal|high|urgent”) and validate with
type: string - Include a
confidencenumber when downstream logic needs a threshold
Ask for JSON explicitly in the prompt template. See Providers & Prompts.
Apply output via listeners, not inline
Decisions emit events — they do not mutate entity fields directly. Use a listener to apply structured output to entity state, then projections for dashboards.
This keeps AI output on the same audit path as every other domain event.
Use logical provider names
Reference provider: reasoning, not provider: gpt-4o-mini. Swap models in one place when you change providers or upgrade models without touching actions.
Mock executor for CI and tutorials
Set executor: mock on providers for playground tutorials, integration tests, and local dev without API keys. Mock returns schema-valid placeholder JSON.
Configure real keys in Causet Cloud AI Providers for production forks. See Secrets & Keys.
Vector memory: partition correctly
Memory retrieval scopes by the partition field from decision input (e.g. customer_id). Always pass the partition key in op: decision input: bindings — not only in entity state.
Ingestion is async. Seed memory with earlier intents (notes, orders) before running a decision that depends on history. See Vector Memory.
Control CU cost
AI operations consume compute units:
| Operation | When charged |
|---|---|
| Memory embedding | Each source event ingested |
| Memory retrieval | Each memory ref on a decision |
| AI decision call | Each op: decision execution + tokens |
Keep memory source_events focused. Avoid attaching large memories to high-volume intents without need.
Common mistakes
Running AI in core. Compiler error — move to side_effects.
Skipping the emitted event schema. Define the event in events: to match input + output fields merged in the payload.
Expecting synchronous memory after write. A note recorded in the same intent may not be embedded before triage completes — design ordering or accept slightly stale context.
Mutating state inside the decision. Use listeners; decisions only emit.
Unbounded prompt context. Limit memory retrieval (default 10 snippets) and keep content templates concise.
Next steps
- Examples — reference patterns
- Defining Decisions — full DSL reference
- Support Copilot — end-to-end walkthrough