Skip to main content
This walkthrough builds project_status — a real plan — from scratch. The workflow generalizes: probe the tools, chain the steps, shape the finish.

1. Probe the tools you’ll use

Before writing any step, learn each tool’s input schema and actual output shape:
Probing pays twice: you author correct {{Ex.path}} references, and every probe feeds the shape cache.
Prefer tool parameters that accept names over ids when available — linear__list_issues takes project by name, which means fewer fragile deep references between steps.

2. Header and inputs

Missing required inputs are handled for you: plan run exits with code 3 and prints the schema; in chat, the agent receives the error, asks the user, and re-calls with complete inputs.

3. Steps

Steps run sequentially; each input may reference plan inputs and any earlier step. Tool names are namespaced catalog names, plus the bare control steps — exit, decide, map/reduce, agent, and ask — and plan_and_execute, the reserved planner tool. Step ids are identifiers — letters, digits, and _, not starting with a digit — unique across the plan (body sub-steps included). The planner’s E0, E1, … convention and descriptive names like fetch_project are equally valid. Ids may not shadow the reserved template roots input, item, index, accumulator, or length.
Design notes worth stealing:
  • One deep reference, reused. Only {{E0.projects.0.name}} reaches into a result; if the project isn’t found, that produces one clean “empty data” outcome instead of four different failures.
  • Types survive templating. limit: 5 stays an integer; a string that is exactly one tag splices the raw JSON value. See Template language.
  • Steps are LLM-free. However many steps you add, execution costs zero inference.

4. The finish

Choose how the plan ends — a solver report, structured output, or silence (details):
  • data is what the solver sees — whole results spliced by template. Oversized payloads are automatically truncated/sampled.
  • query_to_answer is itself a template: conditional sections (like the milestones block above) adapt the instructions to the data.
  • The tighter the output spec, the more consistent the report run-over-run. For strict formats, write the structure as a grammar — see sprint_analysis in the cookbook.

5. Validate and run

Validation is layered: structural checks (templates, references, ids) run at every load, and plan validate / plan run additionally resolve every step tool against what is actually loadable, refusing to start before any step executes when a tool can’t resolve. What no static layer can catch — a path that doesn’t exist in a tool’s real output — surfaces at run time as a typed error with the available keys listed. The full layering, including how requires_servers declarations behave, is in where validation happens. For interactive authoring, the plan workbench wraps this whole loop in a TUI: the chat agent drafts into a side pane, validation runs on every change, and a gated run pauses before each tool call so you can test a plan before its writes are trustworthy.
The authoring loop in one screen: the draft's step tree, its validation verdict, and the agent that edits it.

The authoring loop in one screen: the draft's step tree, its validation verdict, and the agent that edits it.

Authoring from the command line

The same loop runs as individual commands — useful in scripts, and the surface a plan-managing agent drives. Each command applies one edit to the file and writes it back; there is no session to hold open.
Note what this walkthrough does not do: call the planner. graph plan draft "<goal>" is available and mirrors the workbench’s drafting (per-step validation, salvage on exhaustion), but it is the only authoring command that costs inference. When you already know the steps — or an agent does — building them directly is free, deterministic, and reviewable as a diff. Two properties make this safe to script against:
  • Edits can only improve things. An edit is rejected if it introduces a validation problem, and a rejected edit leaves the file untouched — so step rm fails when a later step still references the step, naming the template that would dangle. Problems that were already there never block an edit, which is what keeps a half-built plan (a fresh plan new has no steps yet) editable.
  • Nothing is clobbered silently. A write refuses a file that holds a different plan, and changing identifier writes a new file rather than overwriting the old one.
Add --json to any of these for a machine-readable envelope — including on rejection, where the problem list is what you want most. See the scripting contract.
To have your coding agent drive this loop, install the skill:
This installs /graph-plan-authoring (Claude Code, Cursor, Codex, and most other agents). It teaches the loop the way it is meant to run — draft first, then repair — including the fixes a fresh draft usually needs and how to read a rejection envelope as a repair list.