Skip to content

Persistent state files are the memory that outlives the subprocess — everything needed to resume, compose, and correlate phases lives in adw_state.json, because in-context state dies with the process that owned it.

Principle

State is Workflow Memory

Why it matters

The crash test — what survives the process?

In-memory state

● planok

● buildok

✕ testcrashed

💥 process died — memory gone

Can't resume. adw_id? branch? worktree? → recompute from git log (often impossible)

State on disk

● plan→ saved

● build→ saved

✕ testcrashed

📄 adw_state.json survives

Resumes from last phase. new process reads state → knows adw_id, branch, worktree, where to pick up

If state dies with the subprocess, the workflow can't be resumed, re-run, or composed out of order.

The artifact

What the state file actually holds.

agents/{adw-id}/adw_state.json

{ // identity — who is this workflow"adw_id": "abc-123", "issue_number": 42, "issue_class": "/chore", // branch + paths — where work lives"branch_name": "feat/abc-123", "plan_file": "specs/plan-abc.md", "worktree_path": "trees/abc-123", // resources — allocations held by this workflow"backend_port": 9100, "frontend_port": 5173, "model_set": "base", // history — append-only, enables replay"phase_history": [{"phase": "plan", "status": "ok"},
{"phase": "build", "status": "ok"},
{"phase": "test", "status": "failed"}]}

A Pydantic schema (ADWStateData) is the contract. Every phase reads on start, writes on success, atomic.

The boundary

State holds correlation data, not content.

✓ Belongs in state

adw_id, issue_numberidentity — how phases find each other

branch_name, worktree_pathpaths — where work physically lives

backend_port, model_setresource allocations held by the workflow

phase_historyappend-only — drives replay from failure

✗ Does NOT belong

✗The plan itself lives in specs/plan-*.md — state points to it

✗The codebase lives in the worktree — state points to it

✗The agent's working memory stays in-context; dies with the process (correctly)

✗Logs, transcripts, artifacts written to disk beside state, not inside it

Fatten the state file with content and every phase writes a schema migration. Keep it to correlation.

The failure modes

Four ways to violate the principle — and what breaks.

Pass state only via in-memory variables

First crash loses the workflow. ADW ID, branch, worktree all have to be recomputed from git log. Often impossible.

Force all phases into one process

No resumability. Can't re-run just review. Can't build-only for a hotfix. Can't compose phases out of order.

Let each phase define its own schema

No shared contract. Phase N+1 can't read Phase N's state — fields drift, types shift, handoff silently corrupts.

Embed correlation IDs in prompt text

Parsing by regex. Works until the next model update. Then the regex breaks, and the whole pipeline goes with it.

Every violation dissolves the workflow's identity. Memory that can't be read back isn't memory — it's just exhaust.

The discipline

The subprocesses are interchangeable. The state file is the workflow.

If your workflow's identity lives in a running process, a crash erases it. Write the correlation data — id, branch, paths, history — to disk on every successful phase, atomically, under a typed schema. That file is the workflow's only persistent self.