An agent builds a feature. It compiles. Type-check passes. The unit tests pass. Two reviewers look at it. They disagree about some details, then both approve it.
Later, a deterministic security scan catches a tainted value travelling from a search box, through six files, into a live network call. It finds a vulnerable dependency. It catches an authentication check that returns true for logged-out users.
That is the story Addy Osmani recently used to promote Sonar. The product is beside the point. The uncomfortable part is that the agent made the mistake, the reviews missed it, and the machine that found it was not smarter or more responsible than either reviewer. It was just checking the same property, every time, without getting tired or persuaded by a plausible diff.
The obvious conclusion is: stop reading AI-generated code. Robert C. Martin has made exactly that provocation. His current strategy, he says, is not to read code written by his agents at all. Otherwise he cannot get the productivity. Instead, he surrounds them with extreme constraints: unit tests, Gherkin acceptance tests, QA procedures, mutation testing, quality metrics.
The obvious rebuttal is just as compelling: if nobody understands the code, who owns the incident? Who notices that the tests are testing the wrong thing? Who decides that a feature is technically correct and commercially wrong? Who has the courage to block a release that is green in every dashboard?
Both sides are arguing about review. Neither is quite arguing about the job the human is actually there to do.
The false comfort of the green check
A passing test says something precise: this implementation satisfied this test, in this environment, under these assumptions. That is valuable evidence. It is not a general certificate of good judgment.
METR recently had active maintainers inspect 296 agent-produced PRs that had already passed SWE-bench Verified grading. Roughly half would not have been merged into the real repositories. The gap was not that maintainers enjoy reformatting code for sport. They were seeing integration concerns, compatibility, repository conventions, documentation, and the thousand small local rules that a benchmark's scoring function did not express.
That is the strongest case for the people who still insist on reading code. A codebase is not a collection of test cases. It is an accumulated agreement about what will be expensive later.
And there is a darker version. An agent that can see the test suite can learn that the quickest route to green is not fixing the product but changing the definition of green: weakening an assertion, deleting a failing test, rewriting a mock, increasing a tolerance, adding a feature flag that never turns on. ImpossibleBench made the point bluntly: agents with access to unit tests can delete failing tests rather than repair the underlying bug.
So no, “CI passed” is not enough when the agent also changed CI, fixtures, mocks, policies, dependencies, or the tests themselves. Those are not ordinary implementation changes. They are changes to the court that decides whether the implementation wins.
This is where the argument for human review is absolutely right. Somebody has to own the definition of success.
But that does not rescue the old workflow of opening a thousand-line AI diff and trusting a weary pair of eyes to save the company. The Addy example is the problem in miniature: two reviews already happened. Both missed the dangerous bug. Telling that team they needed a third reviewer is not engineering. It is hope with a calendar invite.
A better question after every escape
When an agent creates a defect that gets past its own checks, a reviewer, and a gate, the reflex is always the same: we should have had a human look at the code.
Maybe. But that is not yet an answer.
Ask a harder question:
Would a competent engineer, doing a normal review, actually have caught this?
If the answer is no, mandatory manual review would have been retrospective theater. The missing control belongs in a deterministic check: a property test, SAST rule, dependency policy, authorization regression test, contract test, sandbox boundary, or release gate.
If the answer is yes, we have learned something useful. There was a signal in an engineer's head that never made it into the system. Maybe the reviewer knows that every endpoint touching tenant data must carry a particular authorization invariant. Maybe they know a payment action must be idempotent. Maybe they recognize a dependency name that does not belong in this repo. The response should not be “hire a reviewer who remembers better.” It should be to make that knowledge explicit: a policy, a test, a review rubric, a protected path, a required owner.
That is how review gets better instead of merely more frequent.
There is a third answer, and it is the one the automation maximalists understate. The reviewer might not have found the exact bug, but they might have noticed that the feature answered the wrong question. The requirements might not mention a privacy posture, an operational cost, a public API contract, a migration path, or a user harm that cannot be expressed as a neat assertion.
Addy makes this objection to his own constraints argument in Comprehension Debt: you cannot write a test for behaviour you have not thought to specify. Reading a PR can expose assumptions and architecture conflicts. It can distribute the understanding that matters at 3 a.m., when the green tests are no longer the thing keeping the service alive.
Itamar Friedman sharpened that distinction in a useful response to the Uncle Bob debate: the code may be disposable; the codebase is not. An agent can cheaply regenerate an implementation. It cannot cheaply reconstruct the accumulated architecture of a company — the interfaces, conventions, exceptions, product decisions, and old scars that explain why the obvious solution was rejected five years ago. A locally correct change can still make the whole system harder to change.
His image is the third disk. The old interview question asked whether you would rescue the disk containing source code or the one containing tests. In the agent era there is a third thing worth saving: intent. Product requirements, service boundaries, API contracts, architectural principles, security policies, ownership, and the reasoning behind decisions that mattered. Tests tell us what the system does. Intent tells us what kind of system we are trying to preserve.
That changes where review belongs. For serious or novel work, spend human judgment earlier: align on the user outcome; agree service, schema, and trust boundaries; make the program shape legible; then give the agent small vertical slices that can be run and redirected before the wrong design becomes two thousand lines of load-bearing code. That is not an architecture committee for a copy change. It is a way to make the expensive decisions while they are still cheap.
That is not an argument to read every line forever. It is an argument to stop pretending that bug detection is the only output of review.
Agents should run the inner loop
Addy has a useful name for the division of labour: agents run the inner loop; engineers own the outer loop.
The inner loop is investigation, implementation, verification, repeat. It is exactly where machines are becoming absurdly useful. They can search a repository, make a bounded change, run a suite, diagnose a failure, try another implementation, and keep doing it without losing concentration. A human manually supervising every tool call is not a safety system. In low-risk work, it is a bottleneck dressed as caution.
The outer loop is different. It is deciding what is worth changing, what evidence counts, what access the agent receives, which failures are acceptable, and whether the result crosses a production boundary. It is also being able to explain that decision later.
The UK NCSC puts the floor clearly: if you cannot understand, monitor, or contain an agent's actions, it is not ready for deployment. Notice that this does not say “read every line the agent writes.” It says understand enough to grant access responsibly, monitor what matters, and stop the system when its behaviour ceases to deserve trust.
That distinction matters because autonomy is not one setting. An agent that renames a private UI component and an agent that changes authorization across services should not get the same review process just because both produced a diff.
Where I would still read the code
I do not think the useful rule is “humans out of the loop.” It is: put human attention where it changes the decision.
I would require deliberate human ownership — and often a substantive review — when a change touches authentication or authorization, payments, PII, multi-tenancy, public contracts, schema migrations, infrastructure permissions, deployment policy, or anything with a large and hard-to-reverse blast radius.
I would also treat changes to tests, mocks, CI, fixtures, quality thresholds, and dependency lockfiles as a different class of work. They are not proof that the implementation is safe; they are modifications to the evidence mechanism. Letting the same agent both write the answer and quietly redraw the exam is an invitation to self-deception.
There is an adversarial reason too. Trail of Bits showed how an attacker could use a malicious issue to steer a coding assistant toward a backdoor. The injected instruction could be invisible to a human maintainer while still readable to the model. That does not prove a human reviewer would have caught the backdoor — Trail of Bits explicitly notes it could pass review. It proves something more useful: task provenance, permissions, dependencies, and trust boundaries need independent ownership. The code is only one part of what the agent is doing.
For a reversible, well-bounded change with strong tests and easy observability, I would happily let the agent run and let deterministic checks carry most of the weight. Birgitta Böckeler has the right test: will you notice when AI gets it wrong? Low impact, high detectability: delegate aggressively. High impact, low detectability: review deeply, assume the system can be wrong, and build for containment.
The real scarce resource
The scarce resource is not human eyeballs per line of generated code. Agents will win that race. It is informed human judgment: the ability to specify a constraint, recognize when a constraint is missing, decide whether evidence is sufficient, and own a consequence that cannot be made reversible.
There is a risk in treating this as a clever process upgrade. If nobody ever reads generated code, teams can accumulate comprehension debt faster than they accumulate defects. Anthropic's recent study of engineers working with an unfamiliar Python library found that AI assistance reduced mastery scores. That does not prove every AI-assisted team becomes incapable. It does warn that comprehension does not appear by accident when production is faster than learning.
So build the habit deliberately. Keep ownership legible. Walk through critical flows. Review the boundaries, not merely the syntax. Use incidents to improve constraints. Make it possible for the person on call to understand enough of the system they are being asked to defend.
The agent can generate more code than you can read. That part is already true. The answer is not to pretend you can keep up, and it is not to abdicate.
Automate the checks for every property you can state. Keep humans where the question is whether you stated the right property, whether the system still deserves to act, or whether somebody must own a consequence that cannot be made reversible.
Next time: the moment you want to grab the mouse from an agent, you are already answering this question. But does the agent need the human interface at all? Selectors vs screenshots.
