I deleted five AI review agents and the reviews got better

4 min#claude-code#agents#ci

The first version of an automated MR reviewer I built ran five specialist subagents in parallel: security, reliability, performance, testing, impact. An orchestrator fanned out to all five, collected their findings, and wrote a summary. It looked thorough. More agents reading the diff from more angles has to mean better coverage, right up until you look at what that actually costs and what it actually catches.

The session that changed my mind cost $5.88 and ran for 905 seconds. It produced no verdict. One of the specialists had a Bash(grep:*) grant, issued a git show | sed | grep pipeline, and the grep pattern itself matched a denied command name in the tool policy. The call got blocked, but the session didn't error, it parked. From the outside a parked session and a turn-budget exhaustion look identical. They are not the same failure and they don't have the same fix. One means widen a grant or stop shelling out; the other means raise the turn cap. Confusing them wastes another expensive run figuring out which one you're actually looking at.

What actually needed a model

Most of what the five specialists were checking didn't need judgment at all. Security scanning, secret detection, terraform blast-radius, coverage math: these are deterministic. A shell script either finds a hardcoded credential or it doesn't. So the rewrite pulled all of that out into plain detectors, eleven of them, that run before any model is invoked and cost zero tokens. What's left for the model is the part that's genuinely a judgment call: does this change do what the ticket says it does, does it break something a linter can't see, is the architecture sound.

That's one judgment pass, not five. A second pass validates the first one's output against a strict schema, because a model asked to emit structured findings will drift from the schema over a long session and nothing downstream should have to guess whether severity: "pretty bad" means BLOCKER or MAJOR. If the validator finds a broken contract, one repair pass gets the offending finding re-emitted, once. A clean review is exactly two model calls. Not two agents doing two things. Two calls, one flow, in order.

Coded gates decide when the expensive pass runs

The interesting design choice isn't the review agent, it's the gate in front of it. Whether the deepest pass runs (a full architectural read, not just "did the diff look reasonable") is decided by code, not by the model deciding it needs to think harder. The gate looks for concrete signals: infrastructure-as-code in the diff, a new module entry point, a schema or migration touched, a manifest changed beyond its version field, more than 25 files.

That gate used to be the default. It got overridden to run on every single review, and the reason is worth stating plainly because it's a real cost tradeoff, not a compromise dressed up as one: a pure-prose or pure-config change trips none of the coded gate's conditions, so the pass most likely to catch a design-level problem was the one that reliably didn't run on the changes least likely to look risky on paper. Running it every time means paying for the deep pass on every review instead of a subset of them. That's accepted, explicitly, as the right trade.

The verdict is never trusted from the model

The last piece is the one I'd tell anyone building something like this to copy first: the pipeline never trusts the model's own verdict field. Whatever the model says the outcome is, the driver recomputes the actual blocking decision in code from the findings array. This exists because four earlier copies of that same blocking logic, scattered across the pipeline, had already been caught drifting from each other. Now there's a self-test that asserts all the paths agree, and the recomputed verdict, not the model's stated one, is what a downstream approval job reads.

None of this is about distrust of the model doing the reading. It's about not asking a model to also be the arbiter of its own output format, and not asking five agents to do what one detector script already does for free. Fan-out is a cost multiplier that reads as thoroughness. Push everything deterministic out of the loop first. Pay for judgment only on what's actually ambiguous, and check its work in code every time.

More in AI

All in AI