TLDR; Quality gates are checks that run independently of the generation step: separate review agents, deterministic tests, Stop hooks, and fact-checkers that can catch issues a same-session review misses. Separate generation from evaluation, automate the checks that can be automated, and keep human approval for decisions the tests cannot settle.
Last month, Claude built a clean invitation feature for a client, model, controller, system test, all green. The code was well-structured, the test covered the happy path and two edge cases, and I was about to commit. Then the review agent flagged a mass-assignment vulnerability in the controller’s strong parameters. The update action accepted role as a permitted parameter, which would have let any authenticated user escalate their own permissions.
I hadn’t asked Claude to include role in the params. It had inferred from the model’s attributes that role should be updatable. A reasonable inference, and exactly the kind of subtle security issue that’s hard to catch when you’re moving fast and the code looks right.
This is the core problem with AI-generated code: plausible output still needs verification. In CodeRabbit’s observational sample of 470 open-source PRs, PRs classified as AI-co-authored had about 1.7x as many findings overall, 75% more logic and correctness findings, and up to 2.74x as many security findings as those classified as human-only. The authors could not independently prove the authorship of every PR, so those results describe that sample rather than all AI-generated code. Separately, Veracode’s 2026 GenAI Code Security Report found that generated code failed its security tests nearly 44% of the time across the models it benchmarked, virtually unchanged from 2025. That is a failure rate, not a 44% increase over human code.
The answer isn’t to stop using AI for code generation. It’s to stop relying on the same session that wrote the code to verify it. Quality gates need to be built into the workflow itself: automatic, consistent, and independent of the session that did the work.
Never let Claude mark its own homework
The most common mistake I see in Claude Code workflows is reviewing code in the same session that wrote it. You ask Claude to build a feature, it builds it, then you ask “does this look right?” Claude reviews its own work and, unsurprisingly, approves it.
This fails for the same reason self-review fails in human workflows. The context is shared. The biases are shared. The blind spots are shared. Claude won’t catch the mass-assignment vulnerability it introduced because the same reasoning that decided role should be a permitted parameter will evaluate that decision as correct when asked to review it.
Separate generation from evaluation. Multiple practitioners have converged on this independently. Nick Tune uses Claude Code’s Stop hook to spawn a separate subagent with a “very critical mindset”; the hook returns an error status to force the main agent to read the review output before continuing. HAMY runs 9 parallel subagents, each specialised in one review dimension. Daniil Okhlopkov takes it further: Claude writes the plan, sends it to OpenAI’s Codex via MCP for an independent evaluation, then incorporates the feedback.
Three tiers, from practical to thorough:
-
Fresh-session subagent: the simplest approach. Commit the code,
/clear, then launch a review agent with a critical brief. The fresh context means no shared reasoning from the generation session. -
Parallel specialised subagents: multiple agents, each focused on one dimension (security, performance, style, logic). Better coverage because each agent has a distinct lens. More expensive.
-
Cross-model review: a different model reviews Claude’s output. It removes the generation transcript and changes the model family, which can diversify the review, but it does not guarantee independent or uncorrelated errors. It also adds an external API dependency.
For most day-to-day work, tier 1 is enough. For anything touching authentication, payments, or user data, tier 2 or 3 is worth the spend.
Cross-model review in practice
Tier 3 is the one I’ve leaned on more over the past few months, using OpenAI’s Codex as the second model against Claude’s work. The point isn’t that one model is smarter than the other. The second reviewer has not seen the generation transcript and comes from a different model family, so in my work it has caught issues the first pass missed. That is useful diversity, not proof that the two systems’ errors are statistically uncorrelated.
I run it two ways. Sometimes it’s wired in directly: Codex connected as an MCP server, and Claude hands it a diff or a design to attack inline. On a SwiftUI app I had it run an adversarial review of the PRD before any code was written, briefed as a skeptical staff engineer told to “attack the design’s assumptions.” It came back with numbered findings that reshaped the plan. On a backend engine I asked for a simplification pass, explicitly not a bug hunt, and it flagged three over-builds with file-level citations and confidence scores. Other times it’s looser: Codex runs in its own window and I bring its findings back as review notes. On a Rails codebase that produced a run of severity-rated catches, a load-bearing JSON guard, a denial-of-service vector, and a silent wrong-results bug, all of which Claude had shipped past.
I’ve also written this step into a project’s process doc and then, checking the logs later, found I’d skipped it every time. A cross-model gate is only a gate if you actually run it, and it’s the easiest discipline to document and the easiest to quietly drop.
The writer/reviewer pattern
The practical implementation of separated review is two sessions, one task. The first session writes the code. The second reviews it with fresh context and a critical eye.
My workflow:
- Session 1: Generate. Give Claude the task. Let it write the code, run the tests, iterate until the feature works.
- Commit the working code. This creates a clean diff for the review session to examine.
/clear: wipe the generation context entirely.- Session 2: Review. Launch a code-reviewer or security-auditor agent against the diff. The reviewer may inherit project instructions and auto-memory, but it does not receive the generation transcript or its chain of decisions. It sees the change through a fresh task brief.
The review session can catch things the generation session missed. In the invitation feature example, the review agent did not receive the reasoning that put role in the strong parameters; it saw an attribute controlling access being writable through a public endpoint and flagged it.
For automation, Nick Tune’s Stop hook approach is the cleanest pattern I’ve seen. The hook fires when Claude finishes its turn and returns a blocking error status, so the main agent must launch a critical review subagent and read its findings before it can stop. It then addresses them. No manual intervention. No forgetting to review.
The key detail: the hook returns exit code 2 when issues are found, the specific code Claude Code treats as blocking for a Stop hook (a plain exit 1 registers as a non-blocking error and Claude proceeds anyway). This blocks the main agent from completing and forces it to address each finding. Code review stops being something you remember to do and becomes something the workflow enforces. The skills and hooks guide covers the full hook implementation with configuration examples.
Automated code review at scale
The writer/reviewer pattern works for individual development. For multi-agent orchestrations or team-wide PR review, you need something more structured.
Anthropic built exactly this for their own engineering team. Their Claude Code Review system dispatches parallel specialised agents on every PR. Before deployment, only 16% of PRs at Anthropic received substantive review comments. After: 54%. On large PRs over 1,000 lines, 84% receive findings, averaging 7.5 issues per PR. Less than 1% of findings are marked incorrect, a false positive rate low enough to avoid alert fatigue.
The system catches real issues. A one-line change to a production service looked routine, the kind of diff that normally gets a quick approval. Code Review flagged it as critical: the change would have broken authentication for the service. The engineer confirmed they would have missed it.
That system is no longer internal. Claude Code now ships it in three forms:
/code-reviewruns a background review subagent against your branch locally, with effort levels that trade false-positive rate against coverage and flags to apply fixes or leave comments.- The hosted Code Review GitHub App brings the same review to every PR for Team and Enterprise orgs: findings verified, ranked by severity, and tunable through
REVIEW.mdandCLAUDE.md. /code-review ultraescalates to a cloud fleet of specialised agents with a verification pass that filters false positives before you see them. It needs a claude.ai login.
So the sequencing has changed since I first built my own reviewer: reach for the built-in command first, and build a custom review agent when you need criteria the built-in one doesn’t encode, your conventions, your compliance rules, your definition of done. That custom agent is what the rest of this section covers.
The code-reviewer agent
A dedicated review agent runs on Opus (strong reasoning for catching subtle issues) with read-only tool access; it can’t fix what it finds, it reports:
Agent (code-reviewer, Opus): "Review the git diff on the current
branch against main. Check for:
1. Security, mass assignment, SQL injection, XSS, auth bypass,
sensitive data exposure
2. Logic errors, off-by-one, nil handling, race conditions
3. Performance, N+1 queries, missing indexes, unbounded queries
4. Convention violations, naming, file structure, test coverage
Be critical. Flag anything questionable. Rank findings by
severity: critical, warning, info."
The constraint that the review agent can’t edit files is deliberate. An agent that can fix bugs it finds during review will try to, and in doing so it might introduce new issues. The review agent’s job is to flag. The fixing happens in a separate, deliberate step where you evaluate each finding.
Parallel specialised agents
HAMY’s approach scales this with 9 parallel subagents, each focused on one review dimension: test running, linting and static analysis, code review, security, quality and style, test quality, performance, dependency and deployment safety, and simplification. The main agent then combines all findings into a prioritised verdict: Ready to Merge, Needs Attention, or Needs Work.
The real win from HAMY’s setup is having AI agents run the review skill themselves and iterate on feedback before marking tasks “done,” rather than running it manually. The review step becomes part of the agent’s own workflow, not something bolted on after.
What AI review catches (and what it misses)
In my own reviews, AI reviewers catch most mechanical issues:
- null pointer exceptions
- style violations
- obvious security patterns
- missing error handling
That’s the work that makes human code review tedious and slow.
What they miss: architectural fitness, business logic correctness, and whether the abstraction is right. An AI reviewer can tell you the code is secure, performant, and well-styled, but not whether it solves the right problem. That judgement stays with you.
The practical split: let automated checks and review agents handle repeatable review work. Spend human review time on “should this exist?”, “is this the right approach?”, and any high-impact decision where accountability cannot be delegated to a model.
Fact-checking workflows
Code isn’t the only output that needs verification. Content workflows, blog posts, marketing copy, client deliverables, produce claims that need checking against reality.
Verification has a cost of its own. One Optimum Partners article reports a 4.3-hour weekly figure attributed to Forrester and derives an annual per-employee estimate from its own loaded-cost assumptions. I could not trace that number to primary Forrester research, so I treat it as an industry estimate rather than a verified benchmark. The operational point still holds: verification time should be measured alongside generation time.
The problem is subtle. AI-generated content doesn’t usually get facts completely wrong; it gets them close to right. A course price that’s $200 off. A statistic from 2023 cited as 2025. A feature described for the wrong product tier. Each error is small enough to miss in a casual read, but large enough to damage credibility or create compliance issues.
My pattern for content workflows:
Write first, verify after. Let Claude draft the content without interruption. Trying to fact-check during generation slows the writing and clutters the context.
Then verify against source documents. Every client project has canonical reference files: a service catalogue with current pricing, a sitemap with URL patterns, brand guidelines with terminology rules. The fact-checker compares every claim in the draft against these sources.
Flag what can’t be verified. Not every claim has a source document. Salary data, industry statistics, and market size figures need external verification. The fact-checker flags these for manual review rather than guessing.
For my marketing work, this is built into the orchestration. The marketing-strategist skill includes a 47-point review checklist that runs on every deliverable. It checks that no statistics are fabricated, that salary data matches the specific industry (not generic cross-industry averages), that inline hyperlinks exist for every external claim, and that page analysis is based on actual fetched content rather than speculation. The checklist doesn’t slow anything down because it’s part of the workflow, not a separate step I have to remember.
NotebookLM serves as the source of truth for client-specific facts. Source documents, course guides, pricing pages, service descriptions, are uploaded once. When the fact-checker runs, it verifies claims against these sources. The verification is only as good as the source material, but having a single canonical repository is better than relying on Claude’s training data for client-specific details.
The most common error I catch: salary and pricing data pulled from cross-industry averages instead of sector-specific sources. “Service Manager” salaries across all industries differ by $20,000+ from “Service Manager, Community Services” salaries. Claude doesn’t distinguish unless your source documents force it to.
The same grader hierarchy, cheap deterministic checks before any LLM judgement, is the backbone of the evals and drift guide: what fact-checking is to content, a regression eval is to an agent when the model underneath it changes.
Session review auditing
The quality gates discussed so far check Claude’s output. Session reviews check your own input: how effectively you’re using the tool.
I run a review at the end of significant work sessions. It looks at the conversation history and evaluates whether my prompting was effective, whether the right tools were used, and whether context was wasted on avoidable dead ends.
The patterns it catches are consistently useful:
-
Repeated re-explanations. “You explained the test naming convention three times in this session. Add it to CLAUDE.md.” That’s a signal I’m paying a context tax every session for knowledge that should be persistent.
-
Main-session exploration. “You read 14 files in the main session to understand the auth module. An Explore subagent would have returned a summary in 1,500 tokens instead of the 22,000 tokens those file reads consumed.” That’s a direct cost saving for next time.
-
Vague prompts that triggered scanning. “Your prompt ‘improve the auth module’ caused Claude to read 8 files looking for what you meant. ‘Add rate limiting to the login endpoint in auth_controller.rb’ would have cost a fraction of the tokens.” Specificity saves tokens as much as it lifts quality.
-
Missing compaction guidance. “You compacted without specifying what to preserve. The pagination decision from earlier in the session was lost.” A five-second addition to the compact command would have prevented twenty minutes of rework.
This isn’t navel-gazing. Over three months of periodic session reviews, my average session efficiency has improved noticeably. Sessions run longer before degrading because less context is wasted on repetition.
The most valuable output is the CLAUDE.md rules and hooks the reviews surface, not the immediate feedback. Every repeated re-explanation becomes a CLAUDE.md instruction. Every error caught by human attention becomes a hook that catches it automatically. Quality gates compound because reviews identify the gaps, and hooks fill them.
Quality as a system property
The gates in this guide are designed to run at defined points in the workflow. The Stop hook fires when Claude finishes a task. The fact-checker runs as part of the orchestration. A session review still needs an explicit trigger unless you automate it. The more of those triggers the system enforces, the less the process depends on memory.
That’s what Claude Code’s extensibility system, skills, hooks, and agents, buys you. A review checklist in a document is something you might follow. A review agent triggered by a Stop hook runs whether you’re feeling diligent or not.
Multi-agent workflows treat quality as a system property: separation of concerns, automated review, and canonical source verification. I have not found longitudinal evidence proving these patterns reduce production defect rates by a specific percentage. Separated review can still catch issues a same-session review missed, and its value should be measured against the defects and false positives it produces in your own workflow.
Deciding which gates AI-written code must pass before it ships is one of the calls I make as a fractional CTO.
Related reading
- Skills, hooks, agents, and commands, the definitive guide, the extensibility primitives that make quality gates automatic
- Multi-agent orchestration, running parallel agents on real projects, parallel execution, including review agent patterns
- Session craft, when to start fresh, resume, or compact, session lifecycle management and the review practice
- The tech-lead pattern, planning before coding, planning as a quality gate that prevents downstream errors
- Evals and drift, keeping agents honest when the model changes, the same grader hierarchy applied to model swaps and agent regressions
- Claude Code hook examples: turning mistakes into tested rules, gates that block a known mistake before it runs
Sources
- State of AI vs Human Code Generation, CodeRabbit. Observational comparison of 470 open-source PRs, including its authorship-classification limitations. Company research
- 2026 GenAI Code Security Report, Veracode. Security-test results across generated code from more than 100 models; source for the 44% failure rate. Company research
- Code Review for Claude Code, Anthropic. Multi-agent PR review system with performance data from internal deployment. Product announcement
- Auto-Reviewing Claude’s Code, Nick Tune, O’Reilly Radar. Stop hook pattern for automatic subagent review at session end. Practitioner guide
- 9 Parallel AI Agents That Review My Code, HAMY. Parallel specialised subagent architecture for comprehensive code review. Practitioner guide
- My Claude Code Setup After 4 Months of Daily Use, Daniil Okhlopkov. Cross-model review via Codex MCP integration. Practitioner guide
- The Hallucination Tax, Optimum Partners. Secondary attribution for the 4.3-hour figure and author-derived loaded-cost estimate; no primary Forrester publication was located. Industry analysis
- Code Review, Claude Code Docs, Anthropic. Setup and configuration guide for automated code review. Documentation
Common questions
How do you keep AI-generated code quality high?
Build the checks into the workflow instead of inspecting at the end. I use a writer/reviewer split, automated review agents and session audits, so quality is a property of the system rather than a final gate someone has to remember.
Why should the reviewer be separate from the writer?
Because a model marking its own homework misses its own mistakes, the same way a person does. A separate reviewer agent, with a fresh context and an adversarial brief, catches issues the writer is blind to.
What is the writer/reviewer pattern?
One agent produces the work and a second, independent agent reviews it against explicit criteria before it is accepted. Separating the two roles turns review into a repeatable step rather than an afterthought, and it scales to automated code review across a project.