One loop does everything.
A graph decides who may do what. Graph engineering for coding agents — on any harness you already use.

Three words carry this whole idea.

nodeAn agent CLI as a subprocess.
edgeA file: stdout → prompt.
contractThe exit code.

The loop grades its own homework.

One loop

agentplans, writes, judges
↻ until done

A graph

planread-only
writeworktree
npm testexit code rules

Capability per node is the point, not parallelism.

planread-only
implementworktree
npm testgate
↓   ↓
reviewmodel A
reviewmodel B
[nodes.verify]
needs = ["implement"]
agent = "shell"
gate  = true
prompt = "npm test"

Isolation makes parallel writes safe.

pkg/apibranch geng/api
pkg/webbranch geng/web
pkg/clibranch geng/cli
↓   ↓   ↓
typecheck + testone barrier for all three
[nodes.api]
isolate = true # own worktree
cwd     = "packages/api"

Parallelise reading. Serialise writing.

repro ×200gate: bug is real
↓   ↓   ↓
timingread-only
state
git log
fixonly writer
repro ×200gate: bug is gone
[nodes.fix]
needs = ["timing","state","git"]
prompt = """
Strongest evidence wins:
{timing}
{state}"""

Switching harness is one line.

[agents.dev]
argv = ["claude", "-p"]          # Claude Code
argv = ["codex", "exec"]         # Codex
argv = ["opencode", "run"]       # OpenCode
argv = ["kiro-cli", "chat"]      # Kiro
argv = ["gemini", "-p"]          # Gemini

Three triggers justify a graph. Otherwise, don't.

context rotPast 300k tokens.
independent reviewAuthor must not judge.
wall-clockSerial independent work.

Multi-agent burns 15× the tokens.

A step that can't write
can't break anything. A gate that isn't an agent can't be argued with.
Everything else is a rename.