AI agent guide — authoring Event Script flows

At a glance

  • Read this if you are an AI agent asked to write or modify an Event Script flow. It is the context you need — you should not have to read the engine source.
  • Generate from rules. The flow grammar and its machine-readable form event-script-flow.json are the source of truth. Validate against them.
  • A flow is a YAML file compiled and validated by the engine (CompileFlows). Your job is to produce one that passes — the invariants are the contract.

How flows are deployed & triggered

A flow is not called directly:

  1. Write the flow YAML under src/main/resources/flows/.
  2. Register its file in the flows.yaml manifest.
  3. Map an HTTP endpoint to it in rest.yaml (flow: {flow-id}) — or trigger it by event.

The engine compiles every registered flow at startup; a flow that violates the grammar fails to load. So correctness is checkable before runtime.

Generate deterministically

Use event-script-flow.json to look up the exact execution types, task fields, and mapping namespaces; use flow-grammar.md for the rules. Then verify:

Pre-write checklist - [ ] flow.id, flow.description, flow.ttl (≥1s), first.task, and tasks are present. - [ ] Every task has description, input, output, and a valid execution. - [ ] There is ≥1 task with execution: end. - [ ] next matches the execution type: decision ≥2; sequential/response/pipeline exactly 1; end/sink none. - [ ] fork has a join; pipeline has a pipeline list; a decision task's output maps a value into decision. - [ ] If the same process is used twice, each such task has a unique name. - [ ] Every source -> target uses valid namespaces (see the grammar's mapping section); ext: targets require external.state.machine.

Recipe

  1. Header: set flow.id, description, ttl, optional exception; pick first.task.
  2. Tasks: for each, set process (or flow://), description, input, output, execution, and the next/join/pipeline its type requires.
  3. Terminate: ensure at least one end task whose output builds the response.
  4. Wire up: register in flows.yaml; add a rest.yaml mapping if HTTP-facing.

Worked example

A minimal flow: receive a POST, call a greeting function, return its result.

flow:
  id: 'greeting-flow'
  description: 'Greet a caller by name'
  ttl: 10s
first.task: 'greeting.service'
tasks:
  - input:
      - 'input.body.name -> name'
    process: 'greeting.service'
    output:
      - 'result.message -> output.body.message'
    description: 'Build the greeting'
    execution: end

A decision example (branch on a function result):

  - input:
      - 'input.body.amount -> amount'
    process: 'risk.scorer'
    output:
      - 'result.high_risk -> decision'
    description: 'Score and branch'
    execution: decision
    next:
      - 'approve.task'      # decision = false -> next[0]
      - 'review.task'       # decision = true  -> next[1]

See also