Building Claude SubAgents 101.
Claude Code ships three subagents by default. Explore is read-only, runs on Haiku, and handles file discovery and codebase search. Plan gathers context in plan mode. General-purpose covers multi-step work that mixes research and edits. I try these before writing any config they cover most of what I'd reach for a custom agent to do.
Creating a custom agent
/agents
Library tab → Create new agent → Personal (saves to ~/.claude/agents/, works in every project) → Generate with Claude → describe what you want. Claude writes the config. No restart needed. Files I edit on disk do need a restart.
Restrict tools
An agent inherits every tool the main session has unless I limit it. Give a code reviewer write access and it will rewrite files I never asked it to touch. Minimal config:
---
name: code-reviewer
description: Reviews code for quality and best practices
tools: Read, Glob, Grep
model: sonnet
---
You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.
tools is an allowlist. disallowedTools is a denylist. The markdown body is the system prompt.
Persistent memory
Every invocation starts cold by default. The memory field gives the agent a directory that persists across conversations:
---
name: code-reviewer
description: Reviews code for quality and best practices
memory: project
---
You are a code reviewer. As you review code, update your agent memory
with patterns, conventions, and recurring issues you discover.
Scope options: user (all projects), project (version-controllable), local (not checked in). With memory on, the first ~200 lines of MEMORY.md get injected into the agent's prompt at startup. I use project as the default so teammates get the accumulated knowledge instead of starting from scratch each session.
Scope MCP servers to the agents that need them
Model Context Protocol tool descriptions consume tokens in my main context just by being connected. If only my browser-testing agent needs Playwright, I define it on that agent. Claude Code connects it when the agent starts and drops it when the agent finishes:
---
name: browser-tester
description: Tests features in a real browser using Playwright
mcpServers:
- playwright:
type: stdio
command: npx
args: ["-y", "@playwright/mcp@latest"]
- github
---
Use the Playwright tools to navigate, screenshot, and interact with pages.
String references like github point to a server already configured in the parent session, so I get the shared connection without re-defining it.
Hooks for finer control
The tools field can't see inside command contents. To let a database agent run SELECT but block DROP, I use a PreToolUse hook:
---
name: db-reader
description: Execute read-only database queries
tools: Bash
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/validate-readonly-query.sh"
---
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if echo "$COMMAND" | grep -iE '\b(INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|TRUNCATE)\b' > /dev/null; then
echo "Blocked: Only SELECT queries are allowed" >&2
exit 2
fi
exit 0
Exit code 2 blocks the call and feeds the error back to Claude.
Parallelism and chaining
For independent research tasks, I spawn agents simultaneously. Each runs in its own context and Claude synthesizes the results. Worth knowing: parallel subagent workflows cost roughly 7x a single thread, per Anthropic's own estimates. On a tight token budget, I run sequentially.
For sequential work, I chain from the main thread:
Use the code-reviewer subagent to find performance issues, then use the optimizer subagent to fix them
Subagents can't spawn subagents, so all chaining gets orchestrated from the main conversation.
Skip the subagent for small tasks
A subagent gathers context before it does anything. For a five-line change, that startup cost outweighs the edit itself. For a quick question about something already in my conversation, /btw sees my context, carries no tools, and discards its output instead of cluttering history.
I delegate tasks that return verbose output I don't need to read in full. Tight, targeted edits stay in the main thread.
Posted Jun 8, 2026, 4:38 PM UTC