CloudCodeTree LogoCloudCodeTree
AI NewsTutorialsAbout
CloudCodeTree Logo
CloudCodeTree
  • AI News
  • Tutorials
  • About
← Back to AI News
The Critic-Then-Merge Pattern: Wire a Reviewer Subagent Into Your Claude Code Workflows

Photo: Boris K. / Pexels

The Critic-Then-Merge Pattern: Wire a Reviewer Subagent Into Your Claude Code Workflows

Chris Harper

3 min read

Jul 16, 2026 · 12:05 UTC

AI
Workflow
Claude Code
Agents
Best Practices

After an implementation agent writes code, spawn a critic subagent that reads only the diff and is explicitly prompted to find problems — the agent that wrote the code is not the right agent to review it.

One of the most reliable quality improvements you can make to a Claude Code Workflow is a "critic" stage after generation. A dedicated reviewer subagent sees no history of how the code was written and has no investment in keeping it. Its sole job is to find problems.

The pattern

// In a Claude Code Workflow script
const diffOutput = await agent(
  'Generate the requested feature and apply it to the codebase',
  { label: 'implement', isolation: 'worktree' }
)

// Critic sees only the diff — none of the implementation reasoning
const review = await agent(
  `Review this diff for correctness, security, and edge cases.
   Be adversarial — your job is to find problems, not to validate the work.
   If you find a blocking issue, start your response with BLOCK.

   Diff:
   ${diffOutput}`,
  { label: 'critic' }
)

if (!review.startsWith('BLOCK')) {
  await agent('Merge the implementation branch to main', { label: 'merge' })
} else {
  log(`Critic blocked merge:\n${review}`)
}

Why a separate agent?

The implementation agent carries the full context of every decision it made. A fresh subagent sees only what the diff shows. This catches:

  • Off-by-one errors that "look right" after 20 minutes writing the loop
  • Missing input validation that seemed obvious given the calling context
  • Race conditions that only appear when reading code cold
  • Security issues that are easy to spot in isolation but invisible during construction

Make the critic adversarial by default

The single most important line in the critic prompt: "your job is to find problems, not to validate the work."

Without explicit adversarial framing, language models tend toward agreement (sycophancy toward the previous turn's output). "Be skeptical" isn't strong enough — "assume there's a bug, find it" is the right register.

Scaling to majority vote

For high-stakes code, run 2-3 independent critics and require majority approval:

const votes = await parallel([
  () => agent(`Review this diff for correctness: ${diff}`, { label: 'critic-correctness' }),
  () => agent(`Review this diff for security: ${diff}`, { label: 'critic-security' }),
  () => agent(`Review this diff for missing edge cases: ${diff}`, { label: 'critic-edges' }),
])

const approvals = votes.filter(Boolean).filter(v => !v.startsWith('BLOCK')).length
if (approvals >= 2) {
  await agent('Merge the implementation branch', { label: 'merge' })
} else {
  log(`Blocked by ${3 - approvals}/3 critics`)
}

Running critics in parallel() means all three run concurrently — same wall-clock time as one, three independent perspectives.

This is the same adversarial-verify pattern used in the Claude Code Workflow SDK docs — structured into a reusable shape here so you can drop it into any implementation workflow.

Sources: Workflow docs — Claude Code · Agent spawning and subagents — Claude Code Docs