AGENTIC SYSTEMS
The Case for Planner–Executor Architectures in Agentic Coding
There is a tempting way to build a coding agent. Take the strongest model available, give it access to a repository, a shell, a browser, a test runner, and a long context window, then ask it to behave like a careful engineer. It reads the task, searches the codebase, writes a patch, runs the tests, diagnoses the failures, and keeps going until it has something that appears to work.
The appeal is obvious. There is one model, one transcript, and one apparent centre of intelligence. The system is easy to explain and surprisingly easy to prototype.
I am increasingly unsure that this should be the default architecture for serious coding agents.

A coding agent does not feel to me like a single act of intelligence stretched across many tokens. It feels more like a small organization—or, less generously, a small distributed system. There is planning, retrieval, observation, implementation, verification, and revision. These activities depend on one another, but they are not quite the same kind of work.
Some parts require broad judgment. Others require patience and mechanical discipline. Some require deciding what evidence would be useful; others require turning noisy output into a compact account of what happened. It seems wasteful to assume that the same model should perform all of them simply because it can.
The architecture I currently find most convincing is some version of a planner–executor system. A frontier model handles the parts of the loop where judgment matters most: understanding the task, forming hypotheses, deciding what to inspect, and determining whether the evidence supports the current approach. Smaller or more specialized models handle much of the operational work around it, while tests, linters, browsers, and other tools keep the process tied to reality.
This is partly a cost argument, but I do not think cost is the interesting part. The more important question is where model capability has the highest marginal value.
My intuition is that the strongest model should spend its attention deciding what matters, not reading every line emitted by the terminal.
Consider a bug report: “The checkout button disappears on mobile after applying a coupon.” An agent can begin by searching the repository for the checkout button and gradually collect whatever looks relevant. Sometimes this works. But in a large codebase, search is not a neutral activity. Every file opened and every plausible fragment retrieved changes the context in which the model makes its next decision.
The danger is not only that the agent wastes time. It may begin treating whatever happens to be present in context as evidence that it matters. A few loosely related files become the working theory of the bug simply because they were found first.
A planner can begin at a slightly higher level. Is this likely to be a responsive layout issue? Does applying the coupon change some cart-validity state? Is the frontend rendering stale derived data? Is the apparent UI failure actually downstream of a product-state transition?
The initial theory does not need to be correct. Its value is in determining what evidence to seek next. Good planning is less about predicting the answer immediately and more about choosing investigations that make the space of possible answers smaller.
Once that direction has been set, much of the next work is comparatively routine. Open the relevant files. Reproduce the failure. Run a targeted test. Extract the meaningful part of a trace. Record what changed and what did not.
This is where I think smaller models are underrated. A model does not need to understand the entire repository to report that the coupon request succeeded, a cart-state flag changed, and the button’s visibility depends on that flag. It needs a narrow interface, a clear task, and some discipline about what it returns.
The point is not to replace reasoning with cheap models. It is to protect reasoning from everything that does not deserve to occupy it.
Raw tool output is usually a poor form of memory. Test logs contain repeated stack frames, warnings, timing noise, and environmental debris. Browser traces contain hundreds of events that are technically real but strategically useless. Repository search produces fragments that are individually plausible and collectively confusing.
Giving all of this to the strongest model can feel like the safest option because nothing has been hidden. In practice, though, a large context window is not the same thing as a faithful memory. Information can remain present while its relevance becomes increasingly difficult to judge.
A distillation layer makes that compression explicit. Instead of carrying the entire history of the run forward, the system carries a compact account of what it currently believes, what it has observed, and what remains uncertain. The planner can then reason from a cleaner state rather than repeatedly reconstructing the investigation from terminal exhaust.
There is an engineering benefit here as well. When the system has explicit boundaries, its failures become easier to discuss. Did it inspect the wrong part of the repository? Did it omit an important observation? Did it generate a patch that violated the intended constraint? Did it accept weak verification?
In a monolithic agent, all of these often collapse into the same diagnosis: the model failed. That is not a particularly useful way to improve a system.
I think a similar argument applies to code generation, although less cleanly. There are changes where the architectural reasoning and implementation are too closely connected to separate: subtle concurrency bugs, difficult migrations, or refactors where the shape of the patch is itself the main design decision. In those cases, the frontier model may need to remain deeply involved.
But a large amount of coding work becomes local once the problem has been framed properly. If the relevant files, expected behaviour, constraints, and verification target are known, a capable coding model can often produce the patch. The quality of the result then depends heavily on the quality of the instruction it receives.
“Fix the bug” is not meaningful delegation. “Change this behaviour without altering this interface, avoid a broad refactor, and add a regression test for this case” is much closer.
This resembles, in a loose way, how strong engineering teams already operate. The most experienced engineer is not valuable because they personally type every line. Their value often lies in framing the problem, spotting bad assumptions, preserving conceptual integrity, and deciding whether an implementation actually solves what it claims to solve.
A planner–executor agent gives the frontier model a similar role. It shapes the work, delegates a constrained change, reviews the result, and decides whether the evidence is strong enough to stop.
The obvious weakness is that every handoff can lose information. A smaller model may omit the one important line in a log. An executor may misunderstand the planner. A compressed state may hide a clue that would have changed the investigation.
I do not think this is a minor objection. Poorly designed decomposition can easily perform worse than a coherent single-model loop.
But the alternative is not perfect information. A monolithic agent also compresses its history, only less visibly. It relies on attention to preserve relevance across an expanding transcript and on the model to maintain a stable internal account of what has happened. Compression still occurs; it is simply implicit and difficult to inspect.
Planner–executor systems make the compression boundary part of the design. They force us to decide what counts as evidence, what state should survive, what an executor is allowed to change, and what verification is required before the system can claim success.
Those choices may matter more than the names of the models involved.
I would hesitate to claim that planner–executor systems are the final form of coding agents. Models are improving quickly, and some of the distinctions that seem important today may become unnecessary. For small repositories and short tasks, a single capable model may remain the simplest and best option.
My thesis is narrower. As coding agents take on longer tasks in larger repositories, I expect the separation between judgment and execution to become more useful, not less. The hard part is often not producing code. It is maintaining a coherent view of the problem while deciding what should be done, what should be ignored, and when the available evidence is good enough.
The strongest model is not the agent. The agent is the entire loop: models, tools, memory, tests, constraints, and review.
The goal should not be to keep the largest model busy. It should be to spend intelligence deliberately.