Self-Validating Agents in Claude Code: Automated Quality at Every Step
Build Claude Code agents that validate their own output using PostToolUse hooks, Stop hooks for completion enforcement, and read-only validator agents.
Problem: Your Claude Code agents produce output that looks right but fails linting, misses required exports, or skips files entirely. You catch it during review, 20 minutes after the agent finished.
Quick Win: Add a PostToolUse hook directly to an agent definition. Every file this agent writes gets linted automatically, before it ever reaches you:
This agent cannot produce unlinted code. The validation is part of its identity, not an afterthought you bolt on later.
Three Tiers of Embedded Validation
Self-validating agents work at three levels. Each catches different categories of problems, and they stack.
Micro validation fires on every tool use. PostToolUse hooks on agent definitions run linters, formatters, and type checkers after each file write. Problems get caught within seconds of creation.
Macro validation fires when the agent tries to stop. Stop hooks check that the full output meets structural requirements: required files exist, exports are present, tests pass. The agent cannot declare "done" until the checks pass.
Team validation uses a separate agent. A read-only validator agent reviews the builder's complete output with fresh context. This is the builder-validator pattern applied at the orchestration level.
PostToolUse: Micro Validation on Every Write
Hooks embedded in agent frontmatter run only while that agent is active. This scopes validation precisely. Your frontend agent runs ESLint. Your Python agent runs Ruff. Neither interferes with the other.
Here's a Python agent with Black and mypy validation:
The key advantage: these hooks are scoped to the agent. Your project-level settings stay clean. When the orchestrator spawns this agent via the Task tool, validation travels with the agent automatically.
Stop Hooks: Macro Validation Before Completion
Micro validation catches syntax and formatting. But it won't catch missing files or incomplete implementations. For that, use a Stop hook that runs a validation script when the agent finishes.
Agent-level Stop hooks in frontmatter are converted to SubagentStop events. This script checks that required output files exist and contain expected content:
Wire it into the agent definition:
Now this agent has both tiers. Every file gets formatted on write (micro). The full output gets validated before completion (macro). If the Stop hook blocks, the agent continues working until all checks pass.
Read-Only Validator Agents
For the third tier, create a dedicated validator agent that cannot modify files. The disallowedTools field enforces this at the tool level:
This agent literally cannot write files. It can only read and report. Pair it with a builder using task dependencies:
When to Use Each Tier
Micro only (PostToolUse) works well for small, focused tasks where formatting and linting are the main quality concerns. Low overhead, immediate feedback.
Micro + macro (PostToolUse + Stop) fits agents that produce multiple files with structural requirements. The Stop hook catches what linting cannot: missing files, incomplete implementations, failing tests.
All three tiers suits critical code paths where you need both automated checks and an independent review. The validator agent provides a second opinion that the builder's hooks cannot.
Start with micro validation on your most-used agent. Add a Stop hook the first time an agent delivers incomplete output. Add the validator pattern when you need confidence that the output works as a whole, not just file by file. You can define these agent configurations in your CLAUDE.md or as standalone agent files in .claude/agents/, whichever fits your project structure better.
Beyond Single Agents
Self-validation and team validation aren't competing strategies. They're layers. An agent with embedded PostToolUse hooks and a Stop script handles 90% of quality issues before a validator ever looks at the output. The validator then focuses on integration concerns and architectural correctness instead of catching lint errors.
Build custom agents with validation baked in from the start. Set up the full hooks system for project-wide lifecycle events. And when you need team-level quality assurance, pair your self-validating builders with read-only validators that catch what automation misses.
Last updated on