The simplest improvement you can make to your agentic programming workflow is to run two agents instead of one. One writes code in its own worktree; the other, in a parallel worktree, reviews it. They share a task list and talk after every TDD cycle. The reviewer is the holder of the lamp: it keeps the end goal fresh in context across the whole task, catching drift before it accumulates.
I wrote previously that the bottleneck in AI-assisted programming is shifting from individual productivity to coordination. The two-agent pair is the simplest possible coordination, and the most useful next step for anyone who has gotten comfortable running one agent and is ready for more.
One Agent Works, but It Drifts
A single coding agent gets a lot done. It picks up a task, writes the test, writes the implementation, runs code-reviewer subagents, runs the test suite, fixes what’s broken, commits.
However, when a task is longer than its working context can hold cleanly, the agent tends to lose sight of the original brief. It makes locally-correct decisions that drift from the overall goal.
Two Agents: Writer and Reviewer
The pattern is simple: two shells, each with its own worktree of the same repo, each with an aweb identity. Run a coding agent in each.
One agent writes code, the other agent reviews. They share tasks, because they are in the same aweb team. When the coding agent finishes a task, it sends mail to the reviewing agent requesting feedback. The reviewing agent does a thorough code review, and then chats with the coding agent. They discuss the findings, and either move on to the next task or agree to have the coding agent go back and fix the implementation.
The cycle, per task:
- The writer picks up the next task.
- Writes the test first (TDD: red, then green).
- Implements until the test passes.
- Asks the reviewer for a review on the diff.
- Waits for the review to come back.
- Discusses anything unclear with the reviewer.
- Applies the changes the review asked for.
- Marks the task done; moves to the next.
The Reviewer Holds the Lamp
A coding agent that has been writing for an hour has its working context filled with implementation details: the function it just refactored, the test it just made green, the import it just moved. The original goal — the why of the task — has been crowded out by the how.
The reviewer agent has a different job. It reads the original brief, the task list, the architectural constraints. When the diff arrives, the reviewer asks the question the writer can no longer ask: does this still solve the original problem? Does it move us toward the end state we agreed on?
I think of the reviewer as the holder of the lamp — the one who keeps the destination visible while the writer is heads-down in the trench. Without the lamp, the writer eventually walks in a circle and convinces itself the new spot is the destination.
The reviewer also catches a class of error that is invisible to the writer: implementations that are correct but make the next task harder. The writer is optimizing the current diff. The reviewer is optimizing the trajectory.
On Top of Subagents
Both Claude Code and Codex have strong code-reviewer subagents built in. The writer agent can spawn a code-reviewer subagent mid-task to catch local issues — bugs, missing edge cases, style violations. These work well and you should keep using them.
A dedicated reviewer agent is a different layer. The code-reviewer subagent runs once inside the writer’s session and forgets when it returns. It sees the diff but not the trajectory. The dedicated reviewer is a separate, persistent session whose context is kept fresh on the end goal across the whole task list.
The two complement cleanly. Subagents catch local issues at the diff level. The dedicated reviewer catches drift at the trajectory level. Use both; they do not compete for context, and they catch different classes of mistake.
Scaling Up: A Product / Engineering Owner Agent
Once the writer/reviewer pair works for one task list, the next step is adding a third agent: a product / engineering owner. This one is not in the loop on every diff. It scopes work, breaks larger goals into the task list each pair consumes, and reviews the result before it ships.
In our team, this agent is named Athena. She owns engineering direction for the aweb codebase: architecture, invariants, review of every diff that lands on main. She does not write code on most tasks; she scopes, dispatches, reviews. When a substantial feature needs authoring, Athena asks for a writer/reviewer pair as a worktree-scoped task, then reviews the gate-input commit before it goes to ship.
Athena pairs with another agent, Hestia, who handles operations. Hestia runs the gate chain (full end-to-end tests, release-ready checks) then tags releases, deploys, and verifies that the new version is live. Athena hands off the reviewed code to Hestia, and Hestia ships releases. Neither is the other’s manager; they are peers in different roles.
This is the working pattern across our codebase today. Two-agent pairs implement; Athena scopes and reviews; Hestia runs gates and deploys. Even multi-day shipping efforts, like a customer-blocking bug we recently worked through across several back-to-back releases, fit this shape without any extra orchestration layer.
I believe that the lesson generalizes. Most agentic-programming bottlenecks are no longer capability problems. They are coordination problems. The simplest form of coordination is a peer that holds context the working agent has lost. Two agents can do this for each other with no infrastructure beyond the conventions of how they talk.
Our team behind aweb uses this pattern daily. aweb is an open-source coordination layer for AI coding agents — identity, task claims, messaging across worktrees and machines. MIT-licensed.