A workflow and a reusable prompt for running code reviews with an AI coding agent. The goal is a review that checks correctness and impact, not style, and finishes in seconds instead of minutes.
Two things tend to make AI reviews slow and noisy:
- Spending time on formatting and naming, which linters and CI already cover.
- Exploring the repo one call at a time: checking out branches, reading file after file, grepping for usages.
The workflow below avoids both.
- Approve improvements. If the PR moves the codebase forward, approve it. Don't block on personal preference.
- Read the discussion first. Review only new code and unresolved threads. Don't re-raise resolved comments.
- Calibrate to size. Aim for around 100 changed lines. Flag PRs over 300 lines; recommend splitting anything over 1,000.
- No formatting comments. Leave formatting and linting to tooling. Review correctness, concurrency, resource handling, and impact.
- Fetch everything in parallel. PR metadata, discussion, and diff in the same turn.
- Map the impact. Use a call graph to find callers and affected code.
- Check intent. If a ticket is linked, compare the change to its acceptance criteria.
- Analyze and report. Review against the checklist below and output findings by severity.
Don't check out the branch locally, run commands one after another, or write temp files. Pull what you need straight from the remote, in parallel, and keep it in context.
The example uses the GitHub CLI. Other Git hosts have equivalent APIs.
gh api graphql -F owner="<OWNER>" -F repo="<REPO>" -F pr=<PR_NUMBER> -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr) {
title
body
author { login }
commits(last: 20) { nodes { commit { oid messageHeadline } } }
comments(last: 20) { nodes { author { login } body } }
reviewThreads(first: 50) {
nodes {
isResolved
path
line
comments(first: 10) { nodes { author { login } body } }
}
}
}
}
}'
gh pr diff <PR_NUMBER> -R <OWNER>/<REPO>
Don't let the agent grep for usages or pull whole files into context to find where a function is called. Give it a code index it can query instead.
I use CodeGraph, which builds a symbol graph from the AST (Tree-sitter, 20+ languages) and exposes it to agents over MCP. With it, the agent can:
- Trace callers and callees of every changed symbol.
- Follow interface-to-implementation and other dynamic-dispatch hops that grep can't follow.
- Find downstream consumers and the full impact radius of the change.
One query replaces a chain of searches, and the result comes from the actual code structure rather than text matching.
Clean code can still miss the requirement.
- If the PR description links a ticket (Jira, Linear, GitHub Issues, etc.), fetch its description and acceptance criteria.
- Use a 5-second timeout (for example,
curl --max-time 5). If there's no linked ticket, or the tracker doesn't answer in time, skip this step and continue.
Review the diff against these areas:
| Area | What to look for |
|---|---|
| Concurrency and async | Fire-and-forget tasks nobody awaits or catches errors from, missing cancellation propagation, deadlocks, race conditions, worker/thread pool starvation |
| Memory and I/O | Heavy allocations in hot paths or tight loops, unbuffered I/O, connections not returned to the pool, N+1 queries |
| Time and state | Server-local time instead of UTC, nullable values used without a check, swallowed exceptions |
| Boundaries | Business logic in the wrong layer, hardcoded config instead of injected config, over-engineering, dead code |
| Security and contracts | Unsanitized input, exposed secrets, missing authorization checks, breaking changes to public APIs |
Every finding gets a severity:
- Blocking : bugs, security issues, data corruption, resource leaks. Must be fixed before merge.
- Recommended : performance, resilience, or design improvements. Worth doing, doesn't block.
- FYI : context for later.
Each finding follows this template:
### [Severity] Short title
- Location: path/to/file.ext:line
- Issue: what goes wrong and when
- Reference: link to relevant docs (language docs, OWASP, etc.)
- Fix: a code snippet that can be applied as-is
Works with any coding agent that can run shell commands (Claude Code, Codex, Gemini CLI, Cursor, etc.).
You are reviewing a pull request. Focus on correctness, impact, and risk. Do not comment on formatting or style.
1. Fetch in parallel: in your first turn, fetch PR metadata and review threads in one query, and fetch the diff from the remote. Do not check out the branch or write files to disk.
2. Read the discussion first. Skip any thread that is resolved.
3. Use the code index (e.g. CodeGraph over MCP) to find callers, implementations, and affected code. Do not grep for usages.
4. If the PR links a ticket, fetch its acceptance criteria with a 5-second timeout. If there is no ticket or it does not respond, continue without it.
5. Check the diff for:
- Concurrency: unawaited background tasks, missing cancellation, deadlocks, race conditions
- Memory and I/O: allocations in hot paths, unbuffered I/O, leaked connections, N+1 queries
- Time and state: local time instead of UTC, unchecked nulls, swallowed exceptions
- Boundaries: logic in the wrong layer, hardcoded config, dead code
- Security: unsanitized input, exposed secrets, missing authorization, breaking API changes
6. Output findings grouped by severity: Blocking, Recommended, FYI. For each, give file and line, the issue, a documentation link, and a concrete fix.
7. Size check: flag PRs over 300 changed lines, recommend splitting over 1,000.