The numbers looked like a success story. A team of six merged more code in one month than in the previous quarter. Cycle time collapsed. The engineering manager put it in a board update. Then the incident rate went up — not dramatically, not catastrophically, just steadily — and the on-call rotation started finding failures in code that nobody on the call could explain, because nobody had written it and, it turned out, nobody had really read it either.
The agents hadn't written bad code. Most of it was fine. The problem was arithmetic: the team had multiplied its ability to produce changes and left its ability to verify them exactly where it was. Everything downstream of that imbalance — review, testing, ownership, metrics, on-call — was still calibrated for a world where writing code was the slow part.
That's the subject here. Not which tools to use, but which practices break when you adopt them, and what has to replace those practices. I've written about specifying work so the agent builds the right thing; this is about everything that happens after it builds it.
What the research actually says, before the opinions
Two findings should anchor any conversation about this, and they're both uncomfortable.
METR's randomized controlled trial (mid-2025) took experienced open-source developers working on real tasks in codebases they knew well, and found they were roughly 19% slower when allowed to use AI tools. The finding that matters more: the same developers estimated afterwards that AI had made them about 20% faster. A ~39-point gap between perception and measurement, in the direction that flatters the tool.
DORA's 2025 report on AI-assisted development, built from thousands of practitioner responses, found near-universal adoption and characterized AI as an amplifier: it magnifies the strengths of organizations with good practices and the dysfunctions of organizations without them.
Put together they produce the operating assumption I'd start from: your team's confidence that this is going well is not evidence, and whatever your delivery system was good and bad at before, it is now more so. That's not an argument against AI-driven development — the teams I see doing it well are genuinely faster. It's an argument for measuring outcomes rather than sensations, and for fixing the practice before scaling the tooling.
The bottleneck moved. Here's where.
graph LR
subgraph BEFORE["Before — writing is the constraint"]
B1["Design
hours"] --> B2["Write code
DAYS"] --> B3["Review
hours"] --> B4["Test + ship
hours"]
end
subgraph AFTER["After — verification is the constraint"]
A1["Specify intent
HOURS — now the leverage"] --> A2["Generate
minutes"]
A2 --> A3["Review + verify
DAYS — the new constraint"]
A3 --> A4["Own + operate
ongoing, and unstaffed"]
end
BEFORE -.->|"same team,
new tools"| AFTER
A3 -.->|"if you don't invest here"| RISK["Rubber-stamped merges
· unexplainable incidents
· change failure rate climbing
while throughput looks great"]
The failure isn't that agents write bad code — it's that the constraint moved and the staffing didn't. Note the last box on the right: own and operate is the stage that grows most and gets budgeted least, because merged code that nobody understands is a liability that only presents itself at 3am, months later, when the person who accepted the diff has moved on.
Review: the practice that has to change most
Cap the size of a reviewable change, and enforce it. An agent will happily produce a two-thousand-line pull request, and there is good evidence from long before AI that review quality falls off a cliff past a few hundred lines. If the agent can generate more than you can review, the constraint is review, and the answer is smaller units — which is exactly what a task breakdown gives you.
Review against intent, not just against style. The questions worth asking changed. Not "is this good code" — it usually is, superficially — but: does this do what the spec said? Is this the smallest change that does it? What did it touch that it didn't need to? What did it delete? That last one catches a specific and nasty class of agent behaviour: a test that was failing gets "fixed" by weakening its assertion.
The author must be able to explain every line. The rule I'd write into a team's working agreement, phrased exactly like that. Whoever opens the pull request owns it, whether or not they typed it. If they can't explain a block, it doesn't ship — not because agent-written code is suspect, but because the alternative is code with no human who understands it, which is a maintenance liability with a delayed fuse.
Make provenance explicit. Not to shame anyone — to route review attention. A one-line note about what generated a change, and what the author verified themselves, tells a reviewer where to look.
# .github/pull_request_template.md
## What & why
## How this was built
- [ ] Hand-written
- [ ] Agent-assisted (I reviewed every line)
- [ ] Agent-authored from a spec (link: ______ )
## Verification — what *I* did, not what the agent claims
- [ ] I ran it. Here is what I observed: ______
- [ ] Tests: I wrote / reviewed the assertions and they would FAIL without this change
- [ ] I checked what this deleted or weakened (assertions, validations, error paths)
- [ ] Dependencies added: ______ (none is the expected answer)
- [ ] I can explain every line in review
## Blast radius
The checklist item that earns its place is the third one. Agents are good at making tests pass, and one legitimate way to make a test pass is to make it assert less. A reviewer who looks specifically at what was removed catches that; a reviewer scrolling a large diff does not.
Tests: now the specification, and now co-authored
When an agent optimizes toward "the tests pass," your test suite stops being a safety net and becomes the specification the system is fitted to. That's a genuine upgrade in leverage and it comes with a trap: if the same agent writes the code and the tests in the same pass, the tests encode the same misunderstanding as the code. They will pass, and they will prove nothing.
Three practices that address it, in order of value:
- Write the acceptance tests from the spec, before implementation — by a human, or by an agent working only from the spec with no sight of the implementation. This is the single most effective control, because it makes the test an independent statement of intent.
- Insist on tests that fail without the change. Trivial to check, easy to skip, and it catches the whole family of tests that assert something already true.
- Prefer properties and contracts at boundaries. Invariants and interface contracts are harder to satisfy accidentally than example-based tests, and they're where agent-generated code most often goes subtly wrong.
And the ordinary discipline that matters more now than it did: coverage is not the metric. An agent can produce 95% coverage of code nobody needs, asserting things nobody cares about. Look at whether the failure modes you're afraid of have tests, which is a conversation, not a number.
Context as a first-class artifact
The highest-leverage thing most teams aren't doing: putting their engineering standards where the agent reads them. An AGENTS.md at the repository root — now read natively by most coding agents and via import by the rest — carrying build and test commands, conventions, architectural boundaries, and the directories nobody should touch, improves every generated change from that point on.
Three rules for it, learned by getting them wrong. Keep it short and true, because a stale instruction is worse than a missing one — an agent will follow it confidently. Review it like code, in pull requests, because it's now part of your build. And prefer executable rules over described ones: a linter, a formatter, a scaffold and a failing test enforce a convention on every change, while a paragraph describing the convention is advice that gets followed most of the time. This is the paved-road principle, and agents make it more valuable rather than less.
Ownership, metrics and the signature to watch for
Ownership. The uncomfortable question for any agent-authored system is: who is on call for this, and can they debug it under pressure? "The team owns it" is the answer that means nobody does. Keep named ownership per service, and treat "the owner has never read this subsystem" as a risk to schedule work against, not a fact of life.
Metrics. DORA's four still apply and they still tell the truth; what changes is which of them you watch. Throughput metrics — deployment frequency, lead time — will improve almost automatically and will flatter you. The honest signal is in the stability pair: change failure rate and time to restore. The signature of a team that has scaled generation without scaling verification is unmistakable once you know it: throughput up and to the right, change failure rate creeping, and time-to-restore worsening because the person debugging didn't write the code. Add two of your own — review latency (which reveals the new bottleneck directly) and rework rate (changes to code merged in the last thirty days). I've written about instrumenting these in DORA metrics for data and AI teams.
Supply chain and safety. Two specific behaviours to watch. Agents add dependencies with a cheerfulness that no human reviewer would show — every added package is a supply-chain decision, and "none" should be the expected answer in your PR template. And an agent that executes code needs a boundary appropriate to what it's running, which is its own subject: sandboxing and tool isolation.
The people question nobody wants to answer
Junior engineers learn by doing the work that agents now do. If a junior's job becomes reviewing generated code, they're being asked to exercise judgment they haven't yet built, and the traditional path to building it has been removed.
I don't have a tidy answer, and I'm suspicious of anyone who does. What I've seen work: deliberately reserving some work as hand-written, with the agent used only for review and explanation; pairing on the review of agent output, because reading code critically is a teachable skill and now the central one; and rotating people through on-call for systems they didn't write, which is where the gap between "I approved this" and "I understand this" becomes concrete very quickly.
The senior-side version of the problem is subtler: the METR result suggests experienced developers can be slower and feel faster in familiar code. Which means the individual judgment "this is helping me" is unreliable, and the team should be looking at outcomes over weeks rather than at how the afternoon felt.
Three failure modes, all of which look like success first. Rubber-stamp review. Approval latency drops, approval rate approaches 100%, and comments-per-review approach zero — those three numbers together are the clearest early warning available, and every team I've seen sliding this way had them in their tooling and wasn't looking. Test co-authorship. Coverage climbs while escaped defects climb with it, because the tests were written by the thing they're testing. The tell is a suite that has never caught a regression in an agent-authored change. Velocity theatre. The board update reports merged pull requests, the incident review reports something else, and nobody joins the two — which is exactly the shape of the story I opened with. The join is the whole discipline: report throughput and stability on the same slide, always. A team producing more change and more incidents is not going faster; it's accumulating a debt with a variable interest rate.
Where I'd actually start
If a team asked me to make this work with one quarter and no new headcount, in this order:
- Write
AGENTS.md. An afternoon, and it improves every change afterwards. - Cap pull request size and make the task breakdown the unit of work. This directly attacks the new constraint.
- Adopt the PR template above, especially "tests would fail without this change" and "what did this delete."
- Put change failure rate and review latency next to throughput on whatever dashboard leadership already looks at.
- Write acceptance tests from the spec before implementation. The one control that breaks test co-authorship.
- Then expand tooling. Not before — DORA's amplifier finding means scaling the tools ahead of the practice scales the dysfunction too.
What to carry away
AI moves the constraint from writing to verifying, and a team that adopts the tools without moving its capacity gets more change, less understanding, and a stability trend that arrives a quarter later. Anchor on the research rather than the feeling: experienced developers were measurably slower while believing they were faster, and AI amplifies whatever practice already exists.
Change review first — cap the size, review against intent, look at what was deleted or weakened, and require that the author can explain every line. Break the test co-authorship loop by writing acceptance tests from the spec before implementation, and insist tests fail without the change. Put your standards in AGENTS.md and make them executable where you can, because a rule a linter enforces is applied every time and a rule in a wiki is applied sometimes.
Then measure honestly: throughput and stability on the same slide, review latency as the direct read on the new bottleneck, and named ownership for systems nobody hand-wrote. The teams doing this well are genuinely faster. They're faster because they moved the verification capacity, not because they bought better tools.