AI-generated code can look complete while quietly changing a contract, weakening validation, or adding a dependency no one intended to own. The right response is not to reject every AI-assisted change. It is to review the change as if an unfamiliar contributor submitted it, then verify the parts a fluent explanation can hide.

Start with the diff, not the explanation

Read the actual diff line by line. Ask what behavior changed, what behavior did not change, and what input the author assumed. A generated summary may describe the goal correctly while omitting a new retry loop, a broader database query, or a changed error status.

Keep the first change small. A refactor that changes routing, persistence, and tests at once is difficult to review regardless of who wrote it. In my project, I split a similar change into smaller boundaries and ran the tests after each meaningful step; the smaller diffs made a missing error-path assertion much easier to spot.

Check the contract

Compare the implementation with the API schema, database constraints, and existing callers. A function that accepts a string may receive an empty string, a Unicode value, or a value longer than the happy-path example.

For payment and fraud workflows, check idempotency, authorization, replay behavior, and audit fields explicitly. A generated handler that returns success after writing only half the state is more dangerous than an obvious syntax error.

Test the edges yourself

Generated tests often repeat the same happy path with different names. Add cases for missing input, duplicate requests, timeouts, partial provider responses, and concurrent calls. Verify that the test would fail if the important behavior disappeared.

Do not treat a green test suite as proof that a new dependency is safe. Inspect the package name, version, license, maintenance history, and transitive dependencies. AI tools can suggest packages that look plausible but are abandoned or do not exist.

Inspect security boundaries

Look for string interpolation in SQL, shell commands, file paths, template output, and URLs. Check whether user-controlled values reach logs or external providers. Confirm that authorization runs before the object is loaded or returned.

For an AI agent, review tool permissions separately from prompt text. The agent should not receive a database credential just because one task needs a read-only query. Give tools narrow inputs, validate outputs, record the action, and require approval for destructive work.

Ask for the missing evidence

When reviewing code for a real project, request the command that ran, the environment, the input shape, and the measured result. A project example is more useful than a claim that something is “fast” or “secure.” In a backend change, record latency, error rate, or queue behavior before and after the change when possible.

That evidence also makes the pull request easier for the next engineer to trust. The goal is not to prove that AI wrote nothing. The goal is to prove that a human understood and accepted the behavior.

Final checklist

  • Read the diff before reading its generated summary.
  • Compare behavior with schemas, callers, and database constraints.
  • Add failure, duplicate, timeout, and concurrency tests.
  • Inspect new packages and transitive dependencies.
  • Review authorization and injection boundaries.
  • Record commands, environment, and measured results.

AI makes typing cheaper. It does not make responsibility cheaper. A review process that makes assumptions visible is the durable engineering skill.

Make the review repeatable

Turn the checklist into a short pull-request template. Ask for the user-visible behavior, failure cases tested, command used to run the tests, and any new dependency or permission. This keeps the review focused on evidence instead of making every reviewer remember the same questions.

For larger changes, include one example input and one rejected input. Redact secrets and personal data, but preserve the shape that matters. A reviewer can trace the input through validation, business logic, persistence, and the response.

Finally, ask what would make the change fail safely. A useful answer names the timeout, rollback, permission boundary, or alert that catches the problem. That question turns an attractive generated diff into an engineering decision the team can own.