Module 1: Custom Subagents
4. Output Parsing and Communication Between Agents
4. Output Parsing and Communication Between Agents
Description
You already know how to create subagents with an identity of their own (capsule 02) and restrict what they can do (capsule 03). But an isolated subagent doesn't solve complex flows. The real value appears when one agent's output becomes the next one's input — when the reviewer finds problems, the implementer fixes them, and the tester verifies. That chain requires structured communication, and communication depends on a detail that defines everything: only the subagent's final message returns to the main conversation.
The intermediate tool calls, the internal reasoning, the files read — all of it stays in the subagent's context and disappears when it finishes. If that final response is a narrative paragraph, you won't be able to extract data reliably. If it's a report with consistent headers or a structured JSON, you can build pipelines where Claude processes the output and delegates to the next agent with exactly the information it needs.
This capsule teaches you to design system prompts that produce parseable outputs, to chain subagents sequentially, to choose between foreground and background execution, and to handle errors when an agent returns something unexpected. It all connects directly to capsule 05, where you'll build the reviewer → implementer → tester pipeline using these patterns.
How a Subagent's Output Flows
The correct mental model
When Claude delegates to a subagent, a separate session is created. The subagent runs tools, reasons, reads files — but none of that returns to the parent. Only the final message crosses the boundary:
Main conversation
│
├── You: "Use the reviewer to analyze the recent changes"
│
├── Claude: [delegates to the reviewer subagent]
│ │
│ │ ┌── Subagent context (invisible to the parent) ──┐
│ │ │ - Reads git diff, analyzes 5 files │
│ │ │ - Runs grep, reasons about findings │
│ │ │ - FINAL MESSAGE: structured report ←────────────┤
│ │ └─────────────────────────────────────────────────┘
│ │
│ ↓ [Only the final message returns]
│
├── Claude receives: "### Code Review Report\n#### CRITICAL..."
│
└── Claude shows you the result (or passes it to another subagent)
Practical implications
- 📦 The final message is all you have. If the subagent found 3 issues but only mentioned 2 in its report, the third doesn't exist for the rest of the flow.
- 📏 The size consumes main context. A 200-line report takes up 200 lines of your context window. Running 5 subagents with detailed reports can fill the context quickly.
- 🔗 Claude processes before delegating. There's no direct connection between subagents — Claude acts as an intermediary, interpreting one's output and building the next one's prompt.
What does NOT return: intermediate tool calls, internal reasoning, files read, errors the subagent resolved on its own. What DOES return: the final text message.
This is a feature. The isolation keeps the main context clean. But it means your system prompt must instruct the subagent to include everything relevant in its final message.
The System Prompt Defines the Output
The golden rule
If you want parseable output, specify it in the system prompt. A subagent without format instructions produces free prose. One with a defined format produces structured data.
Before vs after: the impact of format
System prompt without a defined format:
---
name: reviewer
description: Reviews code for issues
tools: Read, Grep, Glob
---
You are a code reviewer. Analyze the code and report any problems you find.
Typical output (unpredictable):
I looked at the recent changes and found some issues. In auth.py,
there's a potential SQL injection on line 45 where user input is
directly interpolated. Also, the products endpoint doesn't have
pagination. The error handling looks good overall, though I'd
suggest adding retry logic for external API calls.
The structure changes with each run — sometimes it mentions lines, sometimes not. Sometimes it organizes by severity, sometimes not.
System prompt with explicit format:
---
name: reviewer
description: Reviews code changes and produces structured severity reports
tools: Read, Grep, Glob
---
## Role
Code reviewer. Analyze recent changes. Produce structured report.
## Output Format (follow EXACTLY)
### Code Review Report
**Files reviewed:** [list]
#### CRITICAL (must fix)
- **[file:line]** — Description
- Evidence: `code snippet`
- Fix: Specific recommendation
#### WARNING (should fix)
- **[file:line]** — Description
#### Summary
- Critical: [n] | Warning: [n] | Suggestion: [n]
- Verdict: PASS | PASS_WITH_WARNINGS | NEEDS_REVISION
If no issues in a category: "None found."
Resulting output (predictable):
### Code Review Report
**Files reviewed:** src/auth.py, src/routes/products.py
#### CRITICAL (must fix)
- **src/auth.py:45** — SQL injection via string interpolation
- Evidence: `query = f"SELECT * FROM users WHERE id = '{user_id}'"`
- Fix: Use parameterized query with SQLAlchemy
#### WARNING (should fix)
- **src/routes/products.py:62** — No pagination on GET /products
#### Summary
- Critical: 1 | Warning: 1 | Suggestion: 0
- Verdict: NEEDS_REVISION
Now Claude can extract the CRITICAL findings and pass them to the implementer.
Three formats for three situations
| Format | When to use it | Advantage | Disadvantage |
|---|---|---|---|
| JSON | Output processed by another agent or script | Maximum parseability | Less readable for humans |
| Markdown with headers | Output read by humans AND agents | Readability/structure balance | Parsing depends on consistent headers |
| Narrative report | Output presented directly to the user | More readable | Hard to parse programmatically |
For the reviewer → implementer → tester flow, Markdown with headers is the best balance. Claude parses it reliably and humans can inspect intermediate steps.
Chaining Subagents: The Chain Pattern
How chaining works
There's no direct connection between subagents. Claude acts as an intermediary:
You: "Review the code, fix the problems, and verify with tests"
Claude (internally):
│
├── 1. Delegates to the reviewer
│ → Receives: report with 2 critical, 1 warning
│
├── 2. Processes the report — extracts findings
│
├── 3. Delegates to the implementer with context:
│ "Fix these issues: SQL injection in auth.py:45,
│ missing validation in api.py:23, no pagination in products.py:62"
│ → Receives: report of changes made
│
├── 4. Processes the changes — extracts modified files
│
├── 5. Delegates to the tester with context:
│ "Run tests. Modified files: src/auth.py, src/api.py,
│ src/routes/products.py"
│ → Receives: test report
│
└── 6. Presents you with the consolidated summary
The instruction that triggers the chain
A natural prompt triggers the pattern:
Use the reviewer to analyze the recent changes.
Then, use the implementer to fix the problems found.
Finally, use the tester to verify that everything works.
Claude understands the implicit sequence: the reviewer's output informs the implementer, and the implementer's result defines what the tester verifies.
This is exactly what you'll build in capsule 05. The reviewer → implementer → tester pipeline is this chain pattern with the subagents you already designed in the previous capsules.
Foreground vs Background: When to Use Each Mode
Foreground (blocking)
The default mode. Claude waits for the subagent to finish before continuing:
You: "Use the reviewer to analyze the auth module"
Claude: [delegating to the reviewer...] ← You wait here
Claude: "The reviewer found 2 critical issues..."
Background (concurrent)
Background subagents run while you keep working. Claude requests permissions before launching, because it won't be able to ask you during execution:
You: "Use the reviewer in the background to analyze the whole project"
Claude: "May I allow the reviewer to run shell commands? [Yes/No]"
You: "Yes"
Claude: [launches the reviewer in the background]
You: "Meanwhile, explain the payments module to me"
Claude: [responds while the reviewer works in parallel]
...
Claude: "The reviewer finished. It found 3 issues..."
To run in the background: indicate it in the prompt, set background: true in the frontmatter, or press Ctrl+B to send a running subagent to the background.
Comparison: Foreground vs Background
| Aspect | Foreground (Blocking) | Background (Concurrent) |
|---|---|---|
| Blocks the conversation | ✅ Yes | ❌ No |
| Permissions | During execution | All before launching |
| Ideal for | Sequential chains (A → B → C) | Independent tasks in parallel |
| If it fails on permissions | Asks and retries | Stops; resume in foreground |
| When NOT to use | Long independent tasks | Chains where output feeds the next |
Practical rule
Is the output input for the next agent? → Foreground
Is the task independent and long? → Background
Do you need 3 independent analyses? → Background × 3
To disable background tasks globally:
export CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1
Resuming Subagents: Context Continuity
A subagent finishes, but you need it to continue with additional context. Without resume, it would start from scratch:
You: "Use the reviewer to review the authentication module"
[The reviewer analyzes auth.py, middleware.py, tokens.py — returns a report]
You: "Continue that review and now also analyze authorization"
[Claude resumes the SAME subagent — it keeps context, doesn't re-read auth.py]
[Analyzes authorization.py, permissions.py — returns a complementary report]
Agent IDs are stored in ~/.claude/projects/{project}/{sessionId}/subagents/agent-{agentId}.jsonl.
If a background subagent stops on permissions, you can resume it in foreground:
Resume it in foreground so it can request the necessary permissions
| Situation | Resume | New |
|---|---|---|
| Expand the scope of the same task | ✅ | |
| Completely different task | ✅ | |
| Fix something it did wrong | ✅ | |
| Background failed on permissions | ✅ (foreground) |
Context Window Management
Each subagent output consumes space in the main context window. With 3 subagents the impact is manageable. With 10 detailed subagents, the context compacts frequently.
Strategies to control size
1. Explicit limits in the system prompt:
## Output Constraints
- Maximum 10 findings (prioritize by severity)
- Code snippets: max 3 lines each
- No explanations longer than 2 sentences
- Total response: under 80 lines
2. Isolate heavy operations in subagents:
BAD: In the main conversation, read 50 files and analyze them
→ Everything takes up main context
GOOD: A subagent reads 50 files, returns a 20-line summary
→ Only 20 lines take up main context
This is a key advantage of subagents: they isolate voluminous operations. The subagent reads 50 files within its own context but only returns the summary.
3. Auto-compaction: At ~95% capacity, Claude Code compacts automatically. Adjust the threshold:
export CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=80
Communication Patterns
Pattern 1: Sequential chain (A → B → C)
Each agent produces an output that informs the next. The implementer needs to know what to fix before starting.
reviewer → findings → implementer → changes → tester → results
Pattern 2: Parallel research
Multiple subagents analyze different aspects simultaneously:
┌→ security-reviewer → findings ─┐
Your prompt ────┼→ perf-reviewer → findings ─────┼→ Claude consolidates
└→ style-reviewer → findings ────┘
Pattern 3: Isolating heavy operations
Delegate voluminous operations so only a summary returns:
Your prompt → subagent reads 200 files → returns a 30-line summary
Pattern 4: Chain with validation
If the tester finds failures, re-run part of the chain:
reviewer → implementer → tester
├── ALL_PASS → done
└── FAILURES → implementer → tester (retry)
Key limitation
A subagent cannot spawn other subagents. Only the main conversation can delegate. For multi-level orchestration, module 4 (Agent Teams) is the solution. In this module, Claude in the main conversation acts as the coordinator.
Error Handling: Unexpected Output
What can go wrong
| Error | Cause | Impact |
|---|---|---|
| Output without structure | Weak system prompt | Next agent doesn't receive parseable data |
| Truncated output | Subagent reached maxTurns | Incomplete report |
| Empty output | Found nothing and didn't report it | Chain stops without data |
| Different format between runs | LLM variation | Parsing fails |
Defense in the system prompt
Handle "nothing found":
- If no issues found: respond with EXACT text:
"### Review: CLEAN — No issues found in [n] files reviewed"
- NEVER return an empty response
- NEVER skip the Summary section
Force consistency:
## Critical Output Rules
1. ALWAYS include the Summary section, even if empty
2. ALWAYS use the EXACT headers specified
3. If a category has no items, write "None found."
4. NEVER wrap output in markdown code fences
Handle tool errors:
- If git diff fails: report "ERROR: Could not read git history"
- If a file cannot be read: skip it, note in "Files Skipped" section
- If tests fail to RUN (not test failures, execution errors):
report under "### EXECUTION ERROR" with the error message
Connection to the Project (Capsule 05)
The pipeline you'll build in capsule 05 is this chain pattern in action:
Step 1: reviewer analyzes → returns structured findings
Step 2: Claude extracts CRITICAL and WARNING from the report
Step 3: implementer receives findings as context → returns changes
Step 4: Claude extracts modified files
Step 5: tester runs tests → returns pass/fail
Step 6: If there are failures, Claude passes details to the implementer (iteration)
Everything you practiced here — system prompts with explicit format, sequential chains, output handling, context control — materializes in that project.
Troubleshooting
"The subagent's output doesn't have the structure I defined"
Cause: The system prompt describes the format but doesn't show it with a literal example.
Solution: Include a complete example with fictional data and add "follow this EXACT structure." A literal example is more effective than a description of the format.
"The subagent returns too much information"
Cause: Without explicit limits, it reports everything in maximum detail.
Solution: Add numeric constraints: "Maximum 10 findings. Code snippets: 3 lines max. Total response: under 80 lines."
"Claude doesn't pass the right context to the next subagent"
Cause: The first subagent's output doesn't have the information the second one needs.
Solution: Be explicit: "From the report, extract ONLY the CRITICAL items. Pass to the implementer: file, line, and description of each one."
"The background subagent failed silently"
Cause: It needed a permission that wasn't granted before launching.
Solution: Resume in foreground. Preventive alternative: use permissionMode: bypassPermissions for background subagents if you trust their tool restrictions.
"Inconsistent results between runs"
Cause: Subjective criteria in the system prompt.
Solution: Replace subjectivity with measurables: "functions with cyclomatic complexity > 8" instead of "important issues."
Exercises
Exercise 1: Design output for chaining (Easy)
You have a dependency-checker whose output will be consumed by a dependency-updater. Design the checker's system prompt with a format the updater can consume directly. It should include: package, current version, new version, and risk level (major/minor/patch).
See solution
---
name: dependency-checker
description: Checks for outdated dependencies with risk classification
tools: Read, Glob, Bash
disallowedTools: Write, Edit
model: haiku
maxTurns: 10
---
## Role
Dependency auditor. Check for outdated packages. Report for updater agent.
## Process
1. Identify package manager (requirements.txt, pyproject.toml, package.json)
2. Run check: pip list --outdated --format=json OR npm outdated --json
3. Classify by semver risk
## Output Format (EXACT structure)
### Dependency Audit
**Package manager:** [pip|npm]
**Config file:** [path to config file]
#### MAJOR (breaking changes possible)
- **[package]** current=[version] → latest=[version]
#### MINOR (backward compatible)
- **[package]** current=[version] → latest=[version]
#### PATCH (bug fixes only)
- **[package]** current=[version] → latest=[version]
#### Summary
- Major: [n] | Minor: [n] | Patch: [n]
- Recommendation: UPDATE_ALL | UPDATE_MINOR_PATCH | REVIEW_MAJOR_FIRST
The format separates by risk so the updater knows what to update with confidence. "Config file" indicates which file to edit.
Exercise 2: 3-agent chain prompt (Easy)
Write the prompt you would give Claude for: lint-checker analyzes, lint-fixer fixes errors, lint-verifier verifies no errors remain. Include instructions for what to transfer between each step.
See solution
Run this flow in sequence:
1. Use the lint-checker to analyze all Python files in src/.
Wait for its complete report.
2. From the lint-checker's report, extract all errors (not warnings).
Pass to the lint-fixer: the list of files with errors, the error
code (E501, W291, etc.), and the specific line.
3. Use the lint-verifier to run the linter on the files
that were modified. If it reports 0 errors, the flow ends.
If it reports remaining errors, show them to me without trying to fix them.
The key is being explicit about what data Claude transfers: Checker → Fixer (files, error codes, lines). Fixer → Verifier (modified files).
Exercise 3: Foreground vs background — Decide the mode (Medium)
For each scenario, decide foreground or background and justify:
- Reviewer analyzes auth, its output goes to the implementer
- Three independent reviewers analyze security, performance, and style
- A tester runs a suite that takes 5 minutes
- An implementer needs permissions to install a package
See solution
1. Reviewer → implementer: FOREGROUND. The implementer needs the output before starting. The chain is blocked waiting for the result.
2. Three independent reviewers: BACKGROUND × 3. They're independent — real parallelism. Claude consolidates when they all finish.
3. Tester with a long suite: BACKGROUND. 5 minutes would block the conversation. In the background you can keep working.
4. Implementer with permissions: FOREGROUND. npm install may require confirmation. In the background it would stop, unable to request permissions interactively.
Rule: Sequential dependency → foreground. Independence → background. Interactive permissions → foreground.
Exercise 4: System prompt before and after (Medium)
This system prompt produces unpredictable output. Rewrite it for consistent, parseable output:
---
name: test-analyzer
description: Analyzes test results
tools: Bash, Read
---
Run the tests and tell me what happened. Include any failures
with details about why they failed.
See solution
---
name: test-analyzer
description: Runs tests and produces structured pass/fail report
tools: Bash, Read, Glob
disallowedTools: Write, Edit
model: haiku
maxTurns: 10
---
## Role
Test executor and reporter. NEVER modify source code or tests.
## Process
1. Detect framework (pytest.ini, pyproject.toml, package.json)
2. Run with verbose: `python -m pytest -v --tb=short 2>&1`
3. Parse and report
## Output Format (EXACTLY)
### Test Report
**Framework:** [pytest|jest|vitest]
**Command:** [exact command]
#### Results
- Passed: [n] | Failed: [n] | Skipped: [n]
#### Failures
- **[test_file::test_name]**
- Expected: [assertion]
- Actual: [what happened]
- Root cause: [one sentence]
If no failures: "None"
#### Verdict: [ALL_PASS | HAS_FAILURES | EXECUTION_ERROR]
## Rules
- ALWAYS include all sections
- NEVER include full stack traces
- NEVER suggest fixes — only report
Key changes: explicit process, fixed format with sections that always appear, failures with a parseable structure, verdict as a defined enum.
Exercise 5: Control output size (Medium)
Your codebase-auditor analyzes 100+ files and produces 500+ line reports. Redesign the system prompt for a maximum of 50 lines without losing critical information.
See solution
---
name: codebase-auditor
description: Audits codebase and produces compact summary
tools: Read, Grep, Glob
model: haiku
maxTurns: 20
---
## Role
Codebase auditor. COMPACT output — will be consumed by other agents.
## Output Constraints (MANDATORY)
- MAXIMUM 50 lines total
- Top 5 findings only (by severity)
- One line per finding: **[file:line]** severity — description
- No code snippets longer than 1 line
- Aggregate similar issues: "N+1 queries in 4 files" not 4 entries
## Output Format
### Audit Summary
**Files:** [n] | **Issues:** [n] | **Severity:** [highest]
#### Top Findings (max 5)
1. **[file:line]** CRITICAL — [description]
2. **[file:line]** WARNING — [description]
#### Patterns
- [pattern]: [n] files ([abbreviated list])
#### Health: [0-100] — [one sentence]
## Aggregation
- Same issue in 3+ files: aggregate into one finding
- Group by pattern, not by file
- Priority: security > correctness > performance > style
Instead of 500 detailed lines: top 5 findings + aggregated patterns + health score. If you need more detail, resume the subagent: "Give me details on finding #1."
Exercise 6: Chain with error handling (Hard)
Design a scanner → fixer → verifier chain with handling for: scanner finds nothing, fixer can't fix an issue, verifier detects regressions. Write the complete prompt.
See solution
Run this flow with error handling:
## Step 1: Scanner
Use the security-scanner to analyze src/.
- If it returns "CLEAN — No issues": stop here, report that it's clean.
- If it returns findings: continue to step 2.
- If it returns an execution error: report the error to me and stop.
## Step 2: Fixer
Pass to the security-fixer ONLY the CRITICAL items from the scanner.
Include: file, line, description, recommendation.
- If it reports "Not addressed" items: note which ones and why. Continue.
- If it couldn't fix ANY: stop, report to me that it requires a manual fix.
## Step 3: Verifier
Use the security-verifier to test files modified by the fixer.
- If ALL_PASS: report success with a summary.
- If HAS_FAILURES: pass failures to the fixer for a second attempt.
Maximum 1 retry. If it keeps failing: stop and report to me
which tests fail and what fixes caused them.
## Final Report (always)
- Issues found: [n]
- Fixed: [n]
- Not fixed: [n] (with reason)
- Tests: PASS / FAIL
- Status: RESOLVED | PARTIALLY_RESOLVED | NEEDS_MANUAL_FIX
Every branch covered. Iteration limit to avoid loops. Final report independent of where the flow ended.
Summary
- Only the final message of the subagent returns to the main conversation — intermediate tool calls and reasoning stay in the subagent's context
- The system prompt is the key to parseable output — without a defined format, you get unpredictable free prose
- A literal example of the expected output is more effective than a description of the format
- The chain pattern (A → B → C) works because Claude processes one subagent's output and builds the next one's context
- Foreground for chains where each step depends on the previous one; background for independent tasks in parallel
- Resume preserves a subagent's context to continue without starting from scratch
- Each output consumes main context — use size constraints and isolate heavy operations in subagents
- Subagents cannot spawn other subagents — multi-level delegation requires Agent Teams (module 4)
- Auto-compaction at ~95% protects against overflow; adjust it with
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE - The reviewer → implementer → tester pipeline of capsule 05 is this chain pattern with structured format
Additional Resources
- Create Custom Subagents (Anthropic Docs) — Official subagent documentation including output handling and chaining
- Claude Code Sub-Agents — Reference for foreground/background and resume
- Claude Code Best Practices — Delegation and context-handling best practices
- Prompt Engineering: Be Clear and Direct — Clarity techniques transferable to system prompts
- Claude Code CLI Reference — Flags for background tasks and compaction
- Claude Code Settings — Environment variables: CLAUDE_AUTOCOMPACT_PCT_OVERRIDE, CLAUDE_CODE_DISABLE_BACKGROUND_TASKS
- Prompt Engineering: Give Claude a Role — How to define roles that produce consistent outputs
- Claude Code Tips and Tricks — Tips on context handling and delegation
Next capsule: In capsule 05 you'll build the module's project: a functional pipeline of 3 subagents (reviewer → implementer → tester) that analyzes real code, fixes problems, and verifies that the tests pass. Everything you learned in capsules 02-04 — subagent files, tool restrictions, and structured communication — is integrated into a development flow you can use tomorrow in your project.