Sub-agents in Claude Code: Delegating Work to Specialized Agents

Artificial Intelligence tutorial - IT technology blog
Artificial Intelligence tutorial - IT technology blog

Context: 2 AM and Claude Code Starts Getting Confused

I was refactoring a fairly large Python codebase — about 40 files, a mix of FastAPI, Celery workers, and a pile of business logic. I asked Claude Code to handle a combined task: read all the schemas, write unit tests, update the docs, and check for circular imports — all at once.

The result? Claude started hallucinating function names. It wrote tests for functions that didn’t exist. The docs were copy-pasted incorrectly from other files. The context window was full — and the model started “forgetting” what it had read earlier.

That’s when I looked into sub-agents. This feature lets Claude Code delegate work to specialized child agents, each handling a specific task with its own context — without being polluted by information from other tasks.

Why Sub-agents Instead of a Single Agent?

LLMs have a very real limitation: the context window. Cram too much into a single agent — reading 40 files, writing tests, updating docs, checking imports — and it will start making mistakes somewhere along the way. It’s not that the model is bad; it’s the wrong way to use it.

Sub-agents address this in a pragmatic way:

  • Isolation: Each sub-agent has its own context, uncontaminated by other tasks
  • Parallelization: Multiple sub-agents run simultaneously, reducing total time
  • Specialization: Agent A only reads code, agent B only writes tests, agent C only writes docs — each does one thing and does it better
  • Fault isolation: One sub-agent failing doesn’t bring down the entire pipeline

In practice, I used this pattern on a ~40-file codebase and saw a noticeable drop in hallucination rates — from having to fix 3–4 mistakes per run to nearly zero. Overall time also improved by around 30–40% thanks to parallel execution.

Setup: Installing Claude Code and Prerequisites for Sub-agents

Sub-agents are a built-in Claude Code feature — nothing extra to install. Just make sure a few conditions are met:

Minimum Requirements

  • Latest version of Claude Code (installed via npm)
  • Claude account with Pro or Max plan (sub-agents consume significantly more tokens)
  • Node.js 18+
# Install or update Claude Code
npm install -g @anthropic-ai/claude-code

# Check version
claude --version

# Start in your project directory
cd /path/to/your/project
claude

CLAUDE.md Structure — The Foundation for Sub-agents to Understand Each Other

This is something many people overlook. When a parent agent spawns a sub-agent, that sub-agent also reads the CLAUDE.md file in the project — like a new employee reading the onboarding docs before doing anything. This file needs to be clear enough for an agent to understand the project immediately, without needing to ask follow-up questions.

# CLAUDE.md

## Project structure
- src/api/ — FastAPI routers
- src/workers/ — Celery tasks
- src/models/ — SQLAlchemy models
- tests/ — pytest test suite

## Rules
- Always use absolute imports
- Test files mirror src/ structure: src/api/users.py → tests/api/test_users.py
- Never modify migration files directly

The clearer it is, the less the sub-agent needs to ask and the fewer mistakes it makes. I usually spend 15 minutes writing a solid CLAUDE.md before running any complex task.

Detailed Configuration: How to Delegate Work to Sub-agents

Option 1: Claude Code Spawns Sub-agents Automatically

For sufficiently complex tasks, Claude Code will recognize the need and spawn sub-agents on its own — no extra instructions needed. The terminal output will look something like this:

# Claude Code breaks down the task automatically
> Refactor authentication module and write tests for all edge cases

# Terminal output:
[Agent] Spawning sub-agent: code-explorer (reading auth module)
[Agent] Spawning sub-agent: test-writer (writing unit tests)
[Agent] Running in parallel...
[code-explorer] Read src/auth/jwt.py, src/auth/oauth.py
[test-writer] Writing tests/auth/test_jwt.py

Option 2: Using the Agent Tool in a Custom Workflow (SDK)

If you’re building an automated workflow with the Claude Agent SDK, here’s how to call a sub-agent programmatically:

import anthropic

client = anthropic.Anthropic()

# Parent agent receives a large task
def run_parent_agent(task: str):
    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=4096,
        tools=[
            {
                "name": "spawn_subagent",
                "description": "Spawn a specialized sub-agent for a specific subtask",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "task": {"type": "string"},
                        "context": {"type": "string"}
                    },
                    "required": ["task"]
                }
            }
        ],
        messages=[{"role": "user", "content": task}]
    )
    return response

Option 3: Running Multiple Independent Agents in Parallel from the CLI

This is the pattern I use most often when I need to process multiple files in parallel. The idea is simple: fork multiple processes, let the shell manage parallelism, then wait:

#!/bin/bash

# Agent 1: Review security issues
claude --print "Review src/api/ for SQL injection and XSS vulnerabilities. Output findings as JSON." \
  > security_report.json &
PID1=$!

# Agent 2: Generate API docs
claude --print "Read all FastAPI routers in src/api/ and generate OpenAPI-compatible docs." \
  > api_docs.md &
PID2=$!

# Agent 3: Find dead code
claude --print "Find unused functions and imports in src/. List file:line for each." \
  > dead_code.txt &
PID3=$!

# Wait for all agents to finish
wait $PID1 $PID2 $PID3
echo "All agents done. Check security_report.json, api_docs.md, dead_code.txt"

Passing Context Between Parent and Sub-agents

A common real-world problem: a sub-agent needs the output of a previous agent to proceed. The simplest approach is to write to an intermediate file — the next agent reads the summary file instead of having to crawl the entire codebase again:

# Step 1: Agent analyzes the schema
claude --print "Read all SQLAlchemy models in src/models/, output a JSON summary of each table: name, columns, relationships." \
  > schema_summary.json

# Step 2: Agent writes the migration based on the summary
claude --print "$(cat schema_summary.json)

Based on the schema above, write an Alembic migration to add 'updated_at' timestamp to all tables that don't have it. Output only the Python migration file content." \
  > migrations/add_updated_at.py

echo "Migration file ready: migrations/add_updated_at.py"

The schema_summary.json file here acts as a “shared memory” — compact, clear, and the next agent doesn’t need to re-read all 40 original files.

Testing & Monitoring: Knowing When Sub-agents Are Working Correctly

Viewing Each Sub-agent’s Logs

Claude Code logs every tool call in detail. Enable verbose mode to follow each step:

# Run with verbose to see every tool call
claude --verbose

# Or set the env var
export CLAUDE_LOG_LEVEL=debug
claude "refactor auth module"

In verbose output, you can clearly see which files each sub-agent reads, which tools it calls, and what results it returns. When a sub-agent does something wrong, this is the first place to look.

Always Add an Independent Review Agent at the End

This step often gets skipped, but it genuinely matters. After all the sub-agents finish, spawn one more review agent — this agent knows nothing about the previous process; it only reads the output and evaluates it:

claude --print "
Review the following files that were just auto-generated:
- tests/auth/test_jwt.py
- tests/auth/test_oauth.py

Check:
1. Do tests actually cover edge cases or just happy paths?
2. Are there any tests that test implementation details instead of behavior?
3. Will these tests break if we refactor internals?

Output a score 1-10 and specific issues found."

Signs That a Sub-agent Is Running Into Problems

  • Hallucinated function names: Agent writes tests for functions that don’t exist → provide a clearer schema in the prompt
  • Timeout or unusually long runtime: Task scope is too large — break it down further
  • Empty output or “I cannot”: Agent lacks permission to read files → check the working directory
  • Contradictory results between agents: Two parallel agents reading a file that another agent is modifying → use read-only locks or run sequentially

Four Rules I Learned the Hard Way

  1. One sub-agent, one goal: Don’t let a single agent read, write, and validate — split those into three separate agents
  2. Define output format explicitly: Ask agents to return specific JSON or markdown, not free-form text
  3. Scope by path: "Only look at files in src/api/, do not touch other directories" keeps agents focused and faster
  4. Idempotent operations: Design tasks so running them multiple times causes no harm — avoid tasks like “delete all temp files” in automated sub-agents

Sub-agents don’t solve everything. For simple tasks, a single agent is enough — adding sub-agents just burns extra tokens for no gain. But as a codebase grows, as tasks require multiple independent steps, or when you start noticing an agent “forgetting” information toward the end of its context — that’s when it’s time to split things up. Instead of one overloaded generalist agent, you have a small team where each member specializes in one thing and does that one thing well.

Share: