One-Shot Coding Is the Wrong Standard

I keep seeing AI coding models evaluated with a one-shot challenge: describe an entire application in one enormous prompt, wait, and see whether the result runs. That can be entertaining, but I do not think it represents a serious software-development workflow.

Production software is not normally created by one person moving directly from an idea to deployment without review. There are product decisions, implementation plans, tests, hooks, code review, and deployment controls. AI does not make those responsibilities disappear. If anything, the unpredictability of a language model makes those boundaries more important.

I already use deterministic checks to keep agents honest. A test failure is evidence an agent cannot explain away. A hook can reject a change regardless of how persuasive the agent’s summary sounds. But checks alone do not answer a second question: who should implement the change, and who should decide whether that implementation actually solved the problem?

My answer is an implement-review-fix loop with separate agents.

The Implementer Should Not Review Its Own Work

I do not want the agent that wrote the code to be the only agent reviewing it. The implementer has the entire history of how it reached its solution. That context is useful while writing the code, but it can also make the result feel inevitable. It knows what it meant to do and may read that intention back into what it actually did.

A fresh reviewer begins from a different position. It can compare the requested outcome with the resulting change without inheriting the implementer’s chain of decisions. The reviewer should look beyond syntax and local correctness. I want it to ask whether the change fixes the original problem, respects the boundaries of the task, and introduces consequences the implementation plan did not anticipate.

This is the same reason independent human review is valuable. The second perspective is not a claim that the reviewer is perfect. It is a way to avoid having one perspective define both the work and the judgment of that work.

I Became the Message Bus

My first version used two separate Codex sessions. One implemented the change, and the other reviewed it. When the implementation finished, I copied the result to the reviewer. When the review finished, I returned the findings to the implementer. Then I repeated the process until the review passed.

The separation was useful, but I had turned myself into the handoff mechanism between two agents. There was almost no judgment in that part of my job:

  1. When implementation finishes, start review.
  2. When review finds a problem, send it back for a fix.
  3. When the fix finishes, review again.

That sequence is mechanical. A human should be involved when product judgment, risk, or approval is required—not because one window needs to tell another window that it is done.

The Polling Experiment

I first tried to remove myself with a shared ledger. Each feature already had a GitHub issue, so the implementer could post its status there while the reviewer polled for a state change. When the issue said implementation was complete, the reviewer would begin. It would then post its findings, and the implementer would pick them up.

The idea resembled a familiar concurrency pattern: independent workers coordinate through shared state. On paper, it was simple. In practice, the agents were not reliable polling processes.

Sometimes an agent stopped polling. Sometimes the underlying command died while the agent behaved as though it were still waiting. Every fix exposed another exception, and the coordination layer became more fragile than the workflow it was supposed to automate.

That failure clarified an important distinction. The workflow can have a defined sequence, but the agents executing it are still probabilistic. Treating a language model like a durable background process does not make it one.

Let One Agent Orchestrate Fresh Subagents

The cleaner solution was already available in the tools I use: subagents. Instead of keeping two long-lived sessions synchronized, I can use one main agent as the orchestrator. It starts a bounded implementation agent, receives the result, then starts a separate review agent with fresh context. If the reviewer requests changes, the orchestrator routes those findings into another bounded implementation pass.

Fresh context is the central benefit. The reviewer can inherit the stable project instructions it needs without inheriting the implementer’s conversation. Implementation, review, and—when appropriate—deployment can remain separate responsibilities without requiring me to shuttle messages between windows.

This does not remove the need for deterministic gates or human approval. Subagents are coordination, not proof. Tests, hooks, scope limits, and explicit approval boundaries still decide what is acceptable and what is allowed to happen.

Match the Model to the Responsibility

Orchestration also lets me choose a model for the responsibility instead of using the most capable model for every step.

In my current workflow, product design needs the strongest judgment. Turning an incomplete idea into a coherent feature means understanding intent, identifying tradeoffs, and refining the result through discussion. Review also needs strong judgment because it must compare the implementation with the real goal and decide whether an apparent coding problem is actually a planning problem.

The gaps between those stages can be narrower. Once the product decision is settled, translating it into an implementation plan is more constrained. Once the plan is precise, much of the initial implementation can be more constrained still. The current OpenAI model family gives me Sol, Terra, and Luna as different capability and efficiency points, and I can assign them according to the work.

My current preference is roughly:

  • Use a high-capability model for product decisions and holistic review.
  • Use a balanced model to translate an accepted design into an implementation plan.
  • Start implementation with a fast, efficient model when the plan is already specific.
  • Escalate implementation when the reviewer finds that the task is more complex than the plan suggested.

That last point matters. I do not have to predict the perfect model before any code is written. A less expensive first pass can handle straightforward work, while the reviewer acts as an escalation point when the remaining problems require more judgment. This is a routing strategy based on my own experience, not a universal ranking. The right assignments depend on the codebase, the task, and the evidence produced by the workflow.

Codify the Loop

The practical setup is mostly instruction design. I define the roles, handoffs, model choices, review criteria, and approval boundaries in my project instructions. The orchestrator then knows when to start an implementer, what context to give it, when to request an independent review, and what must happen when the review finds a problem.

I also configured an explicit local workflow called $reviewed-change. When I invoke $reviewed-change full, my instructions tell the agent to run that particular sequence without first deciding whether delegation would be useful. That name is not a built-in universal Codex command; it is my own trigger for a workflow I defined.

The sequence is explicit, but the work inside it is not magically deterministic. The value comes from putting probabilistic agents inside a structure with clear responsibilities, fresh review context, deterministic checks, and known escalation points.

The Point Is Better Judgment, Not More Agents

Subagents are useful because they remove mechanical handoffs while preserving separation of responsibility. They let me stop babysitting two windows, reserve stronger models for the stages where judgment matters most, and give every review a cleaner starting point.

If you are still asking one agent to design, implement, review, and declare its own work complete, I think the first improvement is simply to separate implementation from review. Do it manually at first. Observe where the handoffs become repetitive and where human judgment is still necessary. Then automate the repetitive part with an orchestrator and bounded subagents.

The goal is not an elaborate swarm. It is a small, legible workflow in which no single agent gets to write the code, grade the code, and wave it into production by itself.