fsm
fsm is a user-defined finite state machine that routes between named agents based on the key they return in finish(key, value).
It’s the escape hatch: when no pre-built pattern fits your workflow, fsm gives you full control.
When to use it
Section titled “When to use it”- Workflows with conditional branching
- Loops with early exit conditions (e.g., critic with a “good enough” shortcut)
- Custom multi-agent pipelines not covered by named patterns
- Nesting pre-built patterns inside a larger workflow
AGENT.md
Section titled “AGENT.md”---name: review-pipelinedescription: Review pipeline with conditional routing.version: "1.0.0"pattern: fsminitial: draftstates: draft: - good-enough: done # skip critique if draft is already good - needs-work: critique critique: refine # unconditional: always go to refine after critique refine: - good-enough: done - needs-work: critique # loop back for another round done: # terminal — no transitionscall: model: role: thinker---No body needed — the FSM itself doesn’t make an LLM call. It routes between the named agents.
Scaffold
Section titled “Scaffold”tama add fsm my-agentTransition types
Section titled “Transition types”Unconditional
Section titled “Unconditional”states: agent-a: agent-b # always goes to agent-b regardless of finish keyConditional
Section titled “Conditional”states: agent-a: - approve: done # key="approve" → done - reject: revision # key="reject" → revision - "*": error # catch-all for unrecognized keysFirst match wins. Use "*" as a catch-all default.
Terminal
Section titled “Terminal”states: done: # no transitions — the FSM ends hereThe output of the last agent (key + value) propagates as the FSM’s output.
Nested FSMs
Section titled “Nested FSMs”A state in an FSM can itself be a complex agent (including another FSM). The key from the inner agent’s final finish propagates to the outer FSM for routing:
# outer FSMstates: editor: # this is a nested FSM agent - publish: approved - escalate: human-review approved: human-review:The inner editor FSM routes to a done terminal internally, but the key that reached that terminal ("publish" or "escalate") propagates to the outer FSM.
System prompts
Section titled “System prompts”The FSM itself has no body. Each state is a separate named agent with its own AGENT.md.
The agents don’t know about the FSM structure — they only know their own system prompt. The prompt should tell the agent which keys to use:
Evaluate the draft. If it meets quality standards, call finish(key="good-enough", value=<draft>).If it needs significant improvement, call finish(key="needs-work", value=<critique>).Example: critic with early exit
Section titled “Example: critic with early exit”The built-in critic pattern always runs all three steps. With fsm, you can add an early exit:
---name: smart-criticdescription: Critic with early exit if draft is already good.version: "1.0.0"pattern: fsminitial: draftstates: draft: - good-enough: done # ← impossible in pattern: critic - needs-work: critique critique: refine refine: - good-enough: done - needs-work: critique # can loop multiple rounds done:---