> ## Documentation Index
> Fetch the complete documentation index at: https://gump.build/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# State & Variables

> The state is how steps communicate.

# 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:

```yaml theme={null}
steps:
  - name: decompose
    type: split
    get:
      prompt: "Decompose {spec} into tasks."
    run:
      agent: claude-opus
    gate: [schema]

  - name: review
    type: validate
    get:
      prompt: |
        Review the plan:
        {decompose.output}
    run:
      agent: claude-opus
```

`{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 flat `map[string]string` with fully-qualified keys:

```
<step_path>.<field>
```

Examples:

* `decompose.output` — the JSON plan
* `build/task-1/converge.output` — the diff from task 1
* `build/task-1/converge.diff` — the git diff
* `build/task-1/converge.agent` — the agent that executed (e.g., `claude-opus` if escalated)
* `build/task-1/converge.cost` — estimated cost USD
* `build/task-1/converge.tokens_in` — input tokens
* `build/task-1/converge.status` — pass/fail/fatal
* `build/task-1/converge.gate.compile` — bool
* `build/task-1/converge.gate.review.comments` — string

## What each step writes

Every completed step writes these keys:

| Key                             | Description                                                   |
| ------------------------------- | ------------------------------------------------------------- |
| `{<step>.output}`               | Main output: diff (code), tasks JSON (split), bool (validate) |
| `{<step>.diff}`                 | Git diff (code steps)                                         |
| `{<step>.agent}`                | Agent that actually ran (reflects escalation)                 |
| `{<step>.session_id}`           | Agent session ID                                              |
| `{<step>.status}`               | `pass`, `fail`, or `fatal`                                    |
| `{<step>.attempt}`              | Final attempt number                                          |
| `{<step>.duration}`             | Duration in milliseconds                                      |
| `{<step>.cost}`                 | Estimated cost in USD                                         |
| `{<step>.turns}`                | Number of cognitive turns                                     |
| `{<step>.tokens_in}`            | Input tokens consumed                                         |
| `{<step>.tokens_out}`           | Output tokens produced                                        |
| `{<step>.gate.<name>}`          | Bool result of a specific gate                                |
| `{<step>.gate.<name>.comments}` | Validator comments                                            |

## Task variables (each block)

Inside an `each` block, task-level variables are available:

| Variable             | Description                             |
| -------------------- | --------------------------------------- |
| `{task.name}`        | Current task name (from the split JSON) |
| `{task.description}` | Current task description                |
| `{task.files}`       | Current task blast radius (file list)   |

## Retry variables

On retry (attempt > 1), the failed attempt's context is available:

| Variable                      | Description                                                 |
| ----------------------------- | ----------------------------------------------------------- |
| `{error}`                     | Error output from the failed gate (truncated to 2000 chars) |
| `{diff}`                      | Diff from the failed attempt (truncated to 3000 chars)      |
| `{attempt}`                   | Current attempt number                                      |
| `{gate.<name>}`               | Bool result of a specific gate                              |
| `{gate.<name>.comments}`      | Comments from a workflow validator                          |
| `{gate.<name>.error}`         | Stderr from a deterministic gate                            |
| `{prev.output}`               | Output from the previous retry iteration                    |
| `{prev.gate.<name>.comments}` | Validator comments from previous iteration                  |

## 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:

```yaml theme={null}
- name: smoke
  type: code
  run:
    agent: {converge.agent}
  get:
    session: from: converge
```

## 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.
