Reviewing AI Pull Requests: The Human Gate
How I review agent-authored pull requests: CI reads first, changes stay small, and a person asks what the model cannot see.
On my team, agents write much of the first draft and a person decides what merges. That decision is where the engineering now happens. Review is not a formality at the end of the work; it is the step that makes the rest of the pipeline trustworthy.
Locally correct, globally wrong
The most common problem with AI-written code is not that it fails. It is that it works and is still wrong.
A model reasons well about the files it was shown. It does not know that a component doing most of this already exists three folders away, that the pattern it chose was abandoned for reasons that live in an old pull request, or that the state it introduced belongs in a store the rest of the application already uses. Those are properties of the system, invisible from inside the diff. Birgitta Böckeler lists duplicating a component that already exists elsewhere among the missteps she has to correct.
A diff can pass review while the codebase fails it. Reading the diff and reading the codebase are different activities. The second one is the job.
CI reads first
Reviewer attention is the scarcest resource in the pipeline, so I don't spend it on anything a machine can judge. Types, lint, formatting, tests and static analysis run before a person opens the pull request. If a reviewer is commenting on style or naming, the tooling has failed.
One check matters more with agents than with people: the tests themselves. An agent pushed to get a green build will sometimes weaken the check instead of fixing the code. GitHub's guidance on reviewing AI output calls out tests that are deleted or skipped instead of fixed. A change to a test file gets read as carefully as a change to production code.
Small enough to read properly
Agents will happily produce a whole feature in one pull request. That is the fastest route to a rubber stamp. DORA's guidance for AI-assisted teams is direct about it: reviewing machine-generated code can take more effort per line than reviewing human-written code, so the batches have to stay small.
I would rather review five focused pull requests than one large one. Each gets a real reading.
What I ask of every agent-authored change
- Does it fit the architecture? Is this our pattern, not just a reasonable one, and does it sit in the right layer?
- Does something like it already exist? Duplication is a common defect in generated code, and it gets more expensive every month it stays.
- Does it handle the failure paths? Generated code is strongest on the happy path. Timeouts, empty states, partial failures and retries are where I look hardest.
- Does it change a contract? An API shape, a shared type, a schema, an event payload. The change was tested; the question is what else depends on it.
- Does it add a dependency? Every new package is a decision about maintenance and supply chain. OWASP lists insecure or non-existent libraries among the risks of model output, and attackers register the package names models tend to invent.
- Does it touch security-sensitive code? Authentication, authorization, input handling, secrets, infrastructure. These get a slower read however clean the diff looks.
- Does it match the ticket's intent, not only its words? Meeting every acceptance criterion and solving the problem are not always the same thing.
Must change, suggestion, note for next time
I comment on everything, and I weight every comment explicitly. Must change blocks the merge. Suggestion is the author's call. Note for next time is context, not a request.
The vocabulary doesn't change when the first draft came from an agent. An author who can't tell a blocker from a preference will either fight every comment or comply with every comment, and both are bad. If I make the same comment twice, it belongs in a lint rule, a documented convention or the agent's instructions, not in a third review.
Re-specify or fix by hand
When an agent's pull request is wrong, there are two ways forward. If the problem is small and local, such as a missed edge case, fixing it by hand is faster than another round trip. If the problem is the approach, I reject the pull request and fix the input instead: the ticket was unclear, a constraint was unwritten, or context was missing. Patching a wrong approach by hand leaves the next generated change free to repeat it.
The speed the agents add only holds while someone keeps an eye on what they do and fixes after them. That is not a temporary phase. It is the shape of the work.
Whoever approves owns it
Nothing merges on a machine's say-so. A merged commit is a promise to whoever depends on the code, and "an agent wrote it" does not change who made that promise. The person who approved it did.
Treat generated code like a pull request from a brilliant contractor who started this morning: strong fundamentals, fast, and no idea what your team decided last spring or why. You wouldn't merge their first pull request unread. You also wouldn't refuse to hire them.