5 min read
I made an AI argue with another AI before it wrote any code. It's the best process I've used.
I use two models to argue over a plan before either writes code, and the work that disappears is the work I used to fix afterward.

I make an AI argue with another AI before it writes any code. One investigates and plans, the other questions the plan, and they keep going until they agree. I use this at work, where I run engineering teams, and on Shapio, my open-source headless CMS side project; it's the best process I've used in twenty years of shipping software.
The loop
Claude Fable is the architect and orchestrator. It investigates the request and the codebase, then writes a plan. That investigation matters because a plan has to fit the code that exists, and a plausible description of a feature is not enough.
Claude Opus reviews the plan, asking questions and raising objections. Fable answers, Opus pushes back, and they go back and forth until they agree. There is no code to defend yet.
Then Opus implements the agreed plan, and Fable reviews the diff and tests the result, sends its findings back, and Opus fixes them. The same Opus agent keeps its context through plan review, implementation, and fixes, so nobody has to explain the argument to a fresh agent that missed it. The implementer has already questioned the decisions it is about to turn into code.
Why it uses fewer tokens
This saves a massive amount of tokens because bugs die in plan review before any code is written. An objection can change a plan without requiring an implementation to be pulled apart. Once the code exists, the same objection brings more work with it.
The model split helps too. The expensive model plans and tests, while the cheaper model writes the volume of code. Those are different jobs, and I want the effort spent where it helps: producing more code is not the same as deciding what code should exist.
There are also fewer interruptions for me because the two models answer each other's questions instead of handing every question back to me. I still have decisions to make, but I do not need to be the transport layer for their technical discussion. Running engineering teams gives me enough reasons to be interrupted already.
I have a process that avoids rework and keeps the reasoning with the agent doing the implementation. I would rather pay for the objection while it is still an objection.
Drafts mode
This week, I used the process for drafts mode in Shapio. The feature lets a site's development server render saved drafts instead of published content. Access is gated by a new Read drafts permission on delivery tokens, which Fable's initial plan proposed granting per content model.
Opus found four problems before any code existed, starting with a permission leak through relations. When a draft entry was read, the related entries it pulled in were checked only for the plain read permission. A token allowed to read drafts on one model could therefore see drafts from another model through a relation.
The fix changed the scope of the permission. Read drafts would apply to the whole token, across all models, with one check per request. That decision had to be settled before implementation because it changed what the permission meant; getting the feature working would not, by itself, have made the original permission boundary sound.
The second problem was in the admin. There was no per-model editor for delivery roles to extend, since the existing editor handled only all-models grants. The proposed plan depended on an editing surface that was not there.
The third problem was the shared list of content actions. Adding Read drafts to that list would have spread it into admin roles at startup, where it means nothing. The new action got its own list because a shared list can make an addition look small while carrying it somewhere it does not belong.
The fourth problem was in the Astro starter site. One of its list queries was built by hand, bypassing the client library, so a client-level option would never have reached that query. The plan had to account for the actual query path, not just the library it expected the site to use.
Fable accepted all four objections and answered seven questions. Opus built the agreed feature, which shipped in seven commits, in one pass. It went out as release 0.5.1 the same day: plan, argue, build, test, done, with no rework.
The argument still needs supervision
The models still get facts wrong, confidently, with arguments that sound well considered. Giving a wrong answer a second model to talk to does not automatically make it correct. I still need evidence from the code, the tests, and the review.
The reviewer also over-agrees sometimes, and a plan that sounds good can get less resistance than it deserves. Agreement is only useful after the objections have had a chance to surface. Two models approving the same mistake still leaves me with the mistake.
The process is slow: the back-and-forth takes real wall-clock time, even when it saves implementation work. I cannot count the time spent arguing as free just because I am not typing. It is part of the cost of getting to an agreed plan.
Code is the one domain where this is safe, because tests and a reviewer can catch what the models miss. The argument before the code is the product. I want decisions challenged while there is still room to change them.
Two models that disagree are worth more than one that agrees with you.
I still have to referee when they disagree on a product call. That happens a lot. They can argue over the plan, but the product decision is still mine.