To review AI-written code, ignore the agent’s summary and read the diff. Check, in this order: did it change only what the task needed, did it weaken any tests, do the functions and options it calls really exist, and does it handle errors instead of hiding them. Then run the tests and the feature yourself. Agent code looks polished whether or not it is right, so the review has to look for specific mistakes, not for style.
What it looks like in practice
The agent says: “Fixed the date parsing bug and added tests. All tests pass.”
You run:
git status
git diff --stat
src/dates/parse.ts | 6 +++---
src/dates/parse.test.ts | 14 +++++++-------
package.json | 1 +
.eslintrc.json | 2 +-
Four files for a one-function bug. The diff shows a new date library in package.json, a lint rule switched off, and two test assertions changed from exact values to “is defined”. The tests pass because they no longer test anything. That took a minute to find, and the summary mentioned none of it.
Why is reviewing AI code different?
With a human author, you can assume they understood the problem and made choices on purpose. With an agent, you can’t. The code reads well, compiles and is consistently formatted even when it solves a slightly different problem. That fluency makes it easy to skim and approve.
The mistakes are different too. People leave typos and obvious gaps. Agents leave plausible code, quiet workarounds and changes nobody asked for.
Step 1: Read the diff, not the summary
The final message is a claim, not evidence.
git status
git diff --stat
git diff
Start with --stat. If you asked for a one-line fix and see eleven files, you know where to look.
git status matters because git diff doesn’t show new files the agent created. They appear in git status as untracked. To see everything, including new files, stage it and diff the stage:
git add -A
git diff --staged
On a branch per task, compare against where you started:
git diff main...HEAD
If the agent reformatted files, git diff -w hides whitespace-only changes so the real edits stand out. See Git workflow with AI agents for the branch setup.
Step 2: Did it change only what the task needed?
Ask of every file: did this task need it?
- Drive-by refactors: renamed variables, reordered imports, reformatted blocks. Harmless or not, they bury the real change.
- New dependencies in
package.json,go.modorrequirements.txt. Each is its own decision. Check that the package exists and is the one you think it is. - Config changes to CI, linters,
tsconfigor build files. These often hide a workaround for something the agent couldn’t fix. - Deleted code. Make sure every removal was meant.
Revert what is out of scope instead of keeping it to save time. That is where regressions hide.
git restore path/to/unrelated-file
Step 3: Did it weaken the tests?
This is where agents most often take shortcuts. In the test diff, look for:
- Assertions loosened, such as
toEqual(expected)becomingtoBeDefined(). - Tests skipped, deleted or marked as expected to fail, such as a new
test.skiporxit. - Mocks that replace the very code being tested.
- New tests that only try the happy path.
- Snapshot files regenerated wholesale.
Then run the tests yourself. Don’t rely on the transcript:
npm test
One more check is worth it for any bug fix: undo the fix, keep the new test, and run it. It should fail. A test that passes either way doesn’t test the fix.
Step 4: Do the APIs it calls exist?
Models sometimes call functions, options or flags that don’t exist, or that existed in an older version of a library. Compilers and type checkers catch some of this. Dynamic languages, config files and shell scripts often don’t.
For any call you don’t recognize, jump to its definition or check the docs for the version you actually have installed, not the latest.
Step 5: Does it behave correctly?
Formatting is the linter’s job. Spend your attention here:
- Error handling: errors swallowed, logged and ignored, or turned into default values that hide the problem.
- Edge cases: empty input, null, zero, very large values, time zones, two requests at once.
- Security: input not validated, SQL built from strings, secrets in code or logs, permissions wider than needed.
- Performance: queries inside loops, loading a whole table to find one row.
- Fit: does it reuse what the codebase already has, or invent a second way of doing the same thing?
Step 6: Try it
For anything a user would notice, run the program and use the change. An agent can make the tests pass while the feature still doesn’t work end to end.
Can I have another AI review it?
Yes, as a first pass, not instead of you. A fresh session that never saw the agent’s reasoning isn’t swayed by it. Claude Code’s /code-review, for example, reviews the diff in a separate subagent. Give the reviewer the original task and tell it to skip style. A reviewer asked to find problems will always find some, and fixing every nitpick adds code you didn’t need.
Do I have to read every line?
For anything that ships, yes. If a diff is too big to read, the task was too big. Ask the agent to split the change, or start over with smaller tasks. Reading the diff carefully is cheaper than debugging code nobody understood.
What you can skip: lines the formatter changed, if you have checked with git diff -w that nothing else hides there.
Make the next review easier
Most review pain is set up before the agent starts:
- Smaller tasks, smaller diffs. See how to write good tasks for coding agents.
- Say “don’t change the existing tests” in the task when that applies.
- Put repeated corrections in AGENTS.md so you stop making them. See AGENTS.md explained.
- Watch the session, not just the result. Which files it read and which commands it ran tell you how far to trust the outcome.
- Make risky actions ask first. See AI agent permissions.
In the Contenox desktop app, the Diff pane lists the files a session’s edits changed and shows each one’s diff. Changes made by commands the agent ran, such as a formatter or a code generator, don’t appear there, so finish with git status and git diff.
Review checklist
-
git statusandgit diff --statread, then the full diff - New, untracked files checked
- Every changed file needed for the task
- No surprise dependencies, config or CI changes
- No tests weakened, skipped or deleted
- New tests fail without the fix
- Tests run by you
- Unfamiliar APIs checked against the docs for your version
- Errors handled, not swallowed
- Edge cases and security considered
- Change tried by hand where a user would notice it
Related guides
- Git workflow with AI agents: branches and undo so review is easy
- How to write good tasks for coding agents: smaller diffs start with smaller tasks
- AI agent permissions: stop risky actions before review is too late
- What is an AI coding agent?: why agents make these mistakes