AIExample

Example — Support Copilot

A complete multi-file Causet application demonstrating AI decisions, vector memory, and the full write path from ticket creation through triage to queryable agent dashboards.

Source: the Support Copilot example application (maintained internally alongside the platform).


What it demonstrates

FeatureFile
AI providersproviders/ai.providers.causet
Prompt templatesprompts/triage.prompts.causet
Decision definitiondecisions/triage.decisions.causet
Vector memorymemories/customer.memories.causet
op: decisionactions/support.actions.causet
Apply AI outputlisteners/triage.listeners.causet
Read modelsprojections/support.projections.causet
Agent queriesqueries/support.queries.causet

Architecture


App layout

# app.causet
dsl_version: 1
app: support_copilot
 
includes:
  states:       [./states/**/*.state.causet]
  events:       [./events/**/*.events.causet]
  actions:      [./actions/**/*.actions.causet]
  providers:    [./providers/**/*.providers.causet]
  prompts:      [./prompts/**/*.prompts.causet]
  decisions:    [./decisions/**/*.decisions.causet]
  memories:     [./memories/**/*.memories.causet]
  listeners:    [./listeners/**/*.listeners.causet]
  projections:  [./projections/**/*.projections.causet]
  queries:      [./queries/**/*.queries.causet]

Key actions

Seed customer memory

RECORD_CUSTOMER_NOTE and SIMULATE_ORDER emit events listed in customer_history.source_events. With memory ingestion enabled, these are embedded for later retrieval.

actions:
  RECORD_CUSTOMER_NOTE:
    state: customer
    entity_id_expr: intent.customer_id
    core:
      rules:
        - name: record_note
          then:
            - op: emit
              event_type: CUSTOMER_NOTE_RECORDED
              payload:
                customer_id: intent.customer_id
                note: intent.note
                author: intent.author

Create ticket + AI triage

Core persists the ticket and emits TICKET_CREATED. Side effects run op: decisionafter core commits.

  CREATE_TICKET:
    state: ticket
    entity_id_expr: intent.ticket_id
    core:
      rules:
        - name: persist_ticket_fields
          then:
            - op: set
              path: /status
              value: open
            - op: emit
              event_type: TICKET_CREATED
              payload:
                ticket_id: intent.ticket_id
                customer_id: intent.customer_id
                subject: intent.subject
                body: intent.body
    side_effects:
      rules:
        - name: ai_triage
          then:
            - op: decision
              ref: triage_ticket
              input:
                ticket_id: intent.ticket_id
                customer_id: intent.customer_id
                subject: intent.subject
                body: intent.body

Decision + memory + prompt

Decision — references reasoning provider, triage prompt, and customer memory:

decisions:
  triage_ticket:
    provider: reasoning
    prompt: triage_v1
    emits: TICKET_AI_TRIAGED
    memories:
      - customer_history
    input:
      ticket_id:   { type: string, required: true }
      customer_id: { type: string, required: true }
      subject:     { type: string, required: true }
      body:        { type: string, required: true }
    output:
      priority:    { type: string, required: true }
      category:    { type: string, required: true }
      summary:     { type: string, required: true }
      confidence:  { type: number, required: true }

Memory — ingests notes and orders, partitioned by customer:

memories:
  customer_history:
    source_events:
      - CUSTOMER_NOTE_RECORDED
      - ORDER_PLACED
    partition_by: customer_id
    embedding:
      provider: embeddings
    content: |
      [{{ event.type }}] customer={{ event.customer_id }}
      note={{ event.note }} author={{ event.author }}
      order={{ event.order_id }} total={{ event.total }} items={{ event.item_summary }}

Listener — applies AI fields when TICKET_AI_TRIAGED fires:

listeners:
  - on: TICKET_AI_TRIAGED
    mutate:
      - op: set
        field: priority
        value: event.payload.priority
      - op: set
        field: category
        value: event.payload.category
      - op: set
        field: ai_summary
        value: event.payload.summary
      - op: set
        field: ai_confidence
        value: event.payload.confidence

Compile and deploy

causet build compile --runtime path/to/support-copilot --out build/tmp-support-copilot-out

Outputs include causet.decisions.json plus runtime and projections IR. Deploy and activate on your fork with projections enabled.


Cloud configuration

  1. Deploy and activate the spec on your fork (include causet.decisions.json).
  2. In Causet Cloud → AI Providers, add BYOK keys for reasoning and embeddings.
  3. Enable memory ingestion for the fork if using vector memory.

For offline testing, set providers to executor: mock in your .causet files, or use the mock mode toggle in the Causet Cloud support-demo app for this walkthrough.


Example intents

1. Seed memory

{ "intent_type": "RECORD_CUSTOMER_NOTE", "customer_id": "cust_1", "note": "Prefers email contact", "author": "agent_7" }
{ "intent_type": "SIMULATE_ORDER", "customer_id": "cust_1", "order_id": "ord_99", "total": 149.99, "item_summary": "Pro plan annual" }

2. Create and triage

{
  "intent_type": "CREATE_TICKET",
  "ticket_id": "tkt_100",
  "customer_id": "cust_1",
  "subject": "Billing question on ord_99",
  "body": "I was charged twice for my Pro plan renewal."
}

3. Query results

After triage completes, named queries such as urgent_tickets, tickets_for_customer, and triage_dashboard read from materialized projection tables.


Interactive demo

Causet Cloud includes a live demo in-app: /platform/{platform}/app/{application}/support-demo.

The demo executes intents via the control-plane proxy and refreshes query results after CREATE_TICKET.

The demo uses @causet/sdk via the control-plane proxy. Configure platform, application, fork, and API key in the demo UI — see Install Causet.


Design notes

  1. Core before AI — ticket state and TICKET_CREATED commit even if the LLM fails. Triage is best-effort in side effects.
  2. Memory is async — allow a beat between seed intents and triage in demos so embeddings are available.
  3. Listeners for AI fields — keeps core deterministic; AI output arrives as an event like any other domain fact.
  4. Structured output — the decision schema forces JSON fields the listener and projections can rely on.

See also