agent step’s input alike. That is the one spelling to author in, and what everything writing a plan emits: graph plan show (including --json), the authoring commands, and the workbench’s save.
The planner uses camelCase internally (toolName, queryToAnswer) because that is the schema the model is taught. You never see it: a plan it drafts is normalized to snake_case before it reaches disk. The camelCase spellings stay accepted on the way in, so a plan authored before this settled still loads — and rewriting it with any authoring command normalizes it.
Optional fields you never set are omitted rather than written as null/[].
Top level
solver and output are mutually exclusive; declaring neither makes the plan silent (side effects only).
solver
Steps
Control steps
Seven reservedtool_names are executor-intercepted, never dispatched to a registry. Their input is the control grammar — snake_case like everything else, and the only part of a step’s input graph normalizes, since every other tool’s arguments belong to that tool:
exit — end the plan early
decide — fork into one of two branches
filter — partition a list
Legal everywhere, including inside
decide branches and map/reduce bodies — the one nestable control step (it makes no tool call). Inside a body its {{item}}/{{index}} shadow the enclosing body’s within the gate.
map / reduce — run a body per item
agent — delegate an open-ended sub-task
Legal everywhere, including inside
decide branches and map/reduce bodies.
ask — put a question to the user
Legal everywhere, including inside
decide branches and map/reduce bodies. Whether a human is reachable depends on the host, not the plan, so when_unanswered is what keeps one plan runnable both interactively and in CI.
Gate grammar (when / if / where)
A single comparison: { value, op, to }, where value is usually a template (typed splice keeps numbers numeric).
Body grammar (then / else / do)
Either form:
- A single tool call —
{tool_name, input}, no id. Any catalog tool, includingplan__*andplan_and_execute. - An inline step list — normal steps with ids, run in order, with same-branch/same-iteration dataflow. Body ids must not reuse top-level ids and are invisible outside the body.
decide, map, or reduce (branches may contain exit; map/reduce bodies may not). agent, ask, and filter are legal in any body. For other nested control flow, call a plan__* sub-plan — cycles are detected and nesting is capped at 8.