State & Variables
The state is how steps communicate. Every step writes its outputs and metrics to a shared key-value store. Other steps read from it via template variables.Basics
After a step executes, its results are available to all subsequent steps:{decompose.output} resolves to the JSON plan produced by the decompose step. No steps. prefix needed — variables use short names.
Fully-qualified keys
The state is a flatmap[string]string with fully-qualified keys:
decompose.output— the JSON planbuild/task-1/converge.output— the diff from task 1build/task-1/converge.diff— the git diffbuild/task-1/converge.agent— the agent that executed (e.g.,claude-opusif escalated)build/task-1/converge.cost— estimated cost USDbuild/task-1/converge.tokens_in— input tokensbuild/task-1/converge.status— pass/fail/fatalbuild/task-1/converge.gate.compile— boolbuild/task-1/converge.gate.review.comments— string
What each step writes
Every completed step writes these keys:Task variables (each block)
Inside aneach block, task-level variables are available:
Retry variables
On retry (attempt > 1), the failed attempt’s context is available:Dynamic agent reference
{<step>.agent} returns the agent that actually executed a previous step. If the step was escalated (agent overridden in retry), the variable returns the final agent, not the declared one. This enables the idiom:
Scope resolution
Variables resolve by strict scope: step local → each scope → workflow scope. If a variable name is ambiguous (same step name in different scopes),--dry-run will reject the workflow with an error listing available paths.
There is no implicit resolution by proximity. For cross-scope references, use the fully-qualified path: {build/task-1/converge.output}.
Run-level metrics
The{run.*} variables from v0.0.3 have been removed. Run-level metrics (total cost, duration, tokens) are in the ledger and accessible via gump report. The global bounds (max_budget, max_timeout, max_tokens) replace {run.*} for control purposes.
If a prompt needs the cost of a specific step, use {<step>.cost}.
State persistence
The state is serialized to.gump/runs/<uuid>/state.json as a flat JSON dictionary. It’s reloaded on --resume and --replay.
At retry, the previous iteration’s keys are copied under the prev namespace. The original keys are overwritten by the current iteration.