Reviewing AI-generated code: a checklist for senior engineers

Short answer: review AI-generated code from the diff, not from the agent's summary, and look hardest where models fail most: swallowed errors, security, tests that were weakened, invented APIs and changes nobody asked for. If you can't explain a line, it doesn't get merged. The checklist below takes ten minutes per change and catches most of what matters.

A real example: a search endpoint that looked fine

I asked an agent for "a search endpoint for policies by holder name". It produced this, with a cheerful summary saying it handles errors gracefully:

app.MapGet("/policies/search", async (string q, AppDbContext db) =>
{
    try
    {
        var sql = $"SELECT * FROM Policies WHERE HolderName LIKE '%{q}%'";
        return Results.Ok(await db.Policies.FromSqlRaw(sql).ToListAsync());
    }
    catch (Exception)
    {
        return Results.Ok(new List<Policy>());
    }
});

It compiles, and on the happy path it works. It also has a SQL injection, no authorization, returns every column (including the national ID and phone number), has no paging, and turns a database outage into "no results", which is the worst kind of failure: silent. The reviewed version:

app.MapGet("/policies/search",
    async (string q, int page, AppDbContext db, CancellationToken ct) =>
    {
        if (q.Length < 3) return Results.BadRequest("Enter at least 3 characters.");

        var items = await db.Policies
            .AsNoTracking()
            .Where(p => EF.Functions.Like(p.HolderName, $"%{q}%")) // parameterised
            .OrderBy(p => p.Id)
            .Skip(Math.Max(page, 0) * 20).Take(20)
            .Select(p => new PolicySummary(p.Id, p.Number, p.HolderName, p.Status))
            .ToListAsync(ct);

        return Results.Ok(items);
    })
    .RequireAuthorization("PolicyReader");

None of the problems were exotic. They were just easy to miss because the code looked finished.

The checklist

  1. Scope. Does the diff do what was asked and only that? Unrequested refactors, renamed files and "while I was here" changes get reverted or split out.
  2. Read the diff, not the chat. The summary describes intent. The diff is what ships.
  3. Tests. Were any tests deleted, skipped or loosened to make the build green? Do new tests assert behaviour, or only that mocks were called?
  4. Error handling. Look for catch (Exception) that returns a default, empty catches, and errors logged but not surfaced.
  5. Security. String-built SQL, missing [Authorize] or RequireAuthorization, secrets in code or config, sensitive data in logs or responses.
  6. Data and concurrency. Multi-step writes without a transaction, read-then-write races on balances, retries without idempotency.
  7. APIs that exist. Methods, overloads and NuGet packages that look right but don't exist, or exist in another version.
  8. Performance. Queries inside loops, loading whole tables, missing CancellationToken, no paging.
  9. Conventions. Does it follow the project's rules (money type, time provider, error style)? Recurring misses belong in your AGENTS.md.
  10. Can you explain it? If a line is clever and you can't say why it's correct, ask the agent to simplify it or explain it, then decide.

Habits that make review cheaper

  • Small steps. Ask for one change at a time; a 200-line diff gets a real review, a 2,000-line diff gets a skim.
  • Tests first. When the tests describe the behaviour, the review becomes "are these the right tests?".
  • A second pass by a fresh session. Ask a new agent session to review the diff against this checklist before you do. Then do your own.

Pros and cons of a strict review

Pros

  • You keep the speed of AI-generated code without inheriting its blind spots.
  • Problems are caught when they cost minutes, not after an incident.
  • Over time the checklist feeds back into AGENTS.md and the agent makes fewer of the same mistakes.

Cons

  • It takes discipline: the temptation to merge "obviously fine" code is strong.
  • Reviewing is slower than generating, so it becomes the bottleneck. That's the right bottleneck.

Want a second pair of eyes on an AI-built codebase before it goes to production? See how I can help.

Frequently asked questions

Is reviewing AI code different from reviewing a colleague's code?

The checks are similar, the failure modes are not. A colleague rarely invents an API or silently weakens a test; an agent sometimes does, and writes it all in confident, tidy code. So read more of the diff and trust the summary less.

Can I ask the AI to review its own code?

Yes, as a first pass: ask a fresh session to review the diff against a checklist like this one. It catches a fair amount. It doesn't replace your review, because it shares the same blind spots as the model that wrote the code.

How big should an AI-generated change be?

Small enough that you can read every line in one sitting, ideally a few hundred lines at most. Ask the agent for one step at a time; ten small reviewed commits beat one large unreadable one.