obsidian/wiki/claude-code/custom-subagents.md
2026-04-17 12:41:33 +01:00

304 lines
9.2 KiB
Markdown

---
title: "Custom Subagents in Claude Code"
aliases: [subagents, claude-code-subagents, custom-agents]
tags: [claude-code, subagents, multi-agent, context-management, automation]
sources: [raw/Create custom subagents.md]
created: 2026-04-17
updated: 2026-04-17
---
# Custom Subagents in Claude Code
Subagents are specialized AI assistants that run in their **own context window** with a custom system prompt, specific tool access, and independent permissions. Claude automatically delegates tasks to them based on description matching, or you can invoke them explicitly.
**Primary use case:** isolate side tasks (search, test runs, log parsing) that would flood the main conversation with output you won't reference again — the subagent returns only the summary.
See also: [[wiki/claude-code/overview|Claude Code Overview]], [[wiki/agent-sdk/configure-permissions|Permissions Guide]], [[wiki/claude-code/mcp-integration|MCP Integration]]
---
## Built-in Subagents
| Name | Model | Tools | Purpose |
|------|-------|-------|---------|
| **Explore** | Haiku | Read-only | Codebase search and analysis |
| **Plan** | inherit | Read-only | Architecture and implementation planning |
| **General-purpose** | inherit | All | Catch-all delegation |
Explore takes a thoroughness hint: `quick`, `medium`, or `very thorough`.
---
## Creating Subagents
### Via `/agents` command (recommended)
Opens a tabbed UI: **Running** tab (live subagents) + **Library** tab (create/edit/delete). Loads the subagent immediately without restarting.
### Via markdown file
```markdown
---
name: code-reviewer
description: Reviews code for quality and best practices
tools: Read, Glob, Grep
model: sonnet
---
You are a code reviewer. Analyze code and provide specific, actionable feedback.
```
Save to:
- `.claude/agents/` — project scope (check into git for team sharing)
- `~/.claude/agents/` — user scope (all projects)
Manually added files require a session restart or `/agents` reload.
### Via CLI flag (session-only)
```shell
claude --agents '{
"code-reviewer": {
"description": "Expert code reviewer. Use proactively after code changes.",
"prompt": "You are a senior code reviewer...",
"tools": ["Read", "Grep", "Glob", "Bash"],
"model": "sonnet"
}
}'
```
---
## Frontmatter Fields
| Field | Required | Notes |
|-------|----------|-------|
| `name` | Yes | Lowercase with hyphens |
| `description` | Yes | Used by Claude to decide when to delegate |
| `tools` | No | Allowlist; inherits all if omitted |
| `disallowedTools` | No | Denylist applied before `tools` allowlist |
| `model` | No | `sonnet`, `opus`, `haiku`, full model ID, or `inherit` (default) |
| `permissionMode` | No | `default`, `acceptEdits`, `auto`, `dontAsk`, `bypassPermissions`, `plan` |
| `maxTurns` | No | Cap agentic turns |
| `skills` | No | Inject skill content at startup (not inherited from parent) |
| `mcpServers` | No | Inline or named server references |
| `hooks` | No | Lifecycle hooks scoped to this subagent |
| `memory` | No | `user`, `project`, or `local` — persistent cross-session memory |
| `background` | No | `true` to always run as background task |
| `isolation` | No | `worktree` — isolated git copy, auto-cleaned if no changes |
| `effort` | No | `low`, `medium`, `high`, `xhigh`, `max` |
| `color` | No | `red`, `blue`, `green`, `yellow`, `purple`, `orange`, `pink`, `cyan` |
| `initialPrompt` | No | Auto-submitted first turn when used as main session agent |
---
## Scope & Priority
| Location | Scope | Priority |
|----------|-------|----------|
| Managed settings | Organization | 1 (highest) |
| `--agents` CLI flag | Current session | 2 |
| `.claude/agents/` | Current project | 3 |
| `~/.claude/agents/` | All user projects | 4 |
| Plugin `agents/` dir | Where plugin enabled | 5 (lowest) |
When names collide, higher priority wins. Plugin subagents **cannot** use `hooks`, `mcpServers`, or `permissionMode`.
---
## Model Selection
Resolution order for a subagent's model:
1. `CLAUDE_CODE_SUBAGENT_MODEL` env var
2. Per-invocation `model` parameter
3. Subagent frontmatter `model`
4. Main conversation model
---
## Tool Control
**Allowlist** (`tools`): only these tools are available.
**Denylist** (`disallowedTools`): inherit all except these.
**Both**: denylist applied first, then allowlist from the remainder.
To restrict which subagent types can be spawned (when running as main thread via `--agent`):
```yaml
tools: Agent(worker, researcher), Read, Bash
```
Omit `Agent` entirely to prevent spawning any subagent.
---
## Persistent Memory
```yaml
memory: project # or user / local
```
| Scope | Location | Use when |
|-------|----------|----------|
| `user` | `~/.claude/agent-memory/<name>/` | Cross-project learnings |
| `project` | `.claude/agent-memory/<name>/` | Project-specific, shareable via git |
| `local` | `.claude/agent-memory-local/<name>/` | Project-specific, not in git |
When enabled, the subagent gets Read/Write/Edit tools automatically and its system prompt includes first 200 lines of `MEMORY.md`.
---
## Hooks in Subagents
### Frontmatter hooks (subagent-scoped)
Fire only while that subagent is active. **Do not fire** when running as main session via `--agent`.
```yaml
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/validate-command.sh"
PostToolUse:
- matcher: "Edit|Write"
hooks:
- type: command
command: "./scripts/run-linter.sh"
```
`Stop` hooks in frontmatter are converted to `SubagentStop` at runtime.
### Session-level hooks (settings.json)
```json
{
"hooks": {
"SubagentStart": [{ "matcher": "db-agent", "hooks": [...] }],
"SubagentStop": [{ "hooks": [...] }]
}
}
```
---
## Invoking Subagents
| Method | Effect |
|--------|--------|
| Natural language ("use the X subagent") | Claude decides whether to delegate |
| `@"subagent-name (agent)"` | Guarantees that subagent runs |
| `claude --agent code-reviewer` | Whole session uses that subagent's prompt + tools |
| `agent` key in `.claude/settings.json` | Default for every session in the project |
---
## Foreground vs Background
- **Foreground**: blocks main conversation; permission prompts pass through
- **Background**: concurrent; permissions approved upfront; `AskUserQuestion` fails silently
- Press **Ctrl+B** to background a running task
- Disable all background tasks: `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1`
---
## Common Patterns
### Isolate high-volume operations
```text
Use a subagent to run the test suite and report only failing tests with error messages
```
### Parallel research
```text
Research the auth, database, and API modules in parallel using separate subagents
```
### Chain subagents
```text
Use code-reviewer to find performance issues, then use optimizer to fix them
```
---
## When NOT to Use a Subagent
- Task needs frequent back-and-forth or iterative refinement → main conversation
- Quick targeted change → main conversation
- Latency matters → main conversation (subagents start fresh)
- Reusable prompt/workflow in main context → [[wiki/agent-sdk/skills-in-sdk|Skills]]
- Nested delegation needed → Skills or chain from main conversation
- Quick question already in context → `/btw` command (no tools, answer discarded)
**Note:** Subagents cannot spawn other subagents.
---
## Example Subagents
### Code Reviewer (read-only)
```markdown
---
name: code-reviewer
description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
tools: Read, Grep, Glob, Bash
model: inherit
---
You are a senior code reviewer...
```
### Debugger (read + write)
```markdown
---
name: debugger
description: Debugging specialist for errors, test failures, and unexpected behavior. Use proactively when encountering any issues.
tools: Read, Edit, Bash, Grep, Glob
---
```
### DB Query Validator (hook-gated Bash)
```markdown
---
name: db-reader
description: Execute read-only database queries.
tools: Bash
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/validate-readonly-query.sh"
---
```
Exit code 2 from the hook blocks the command and returns the error to Claude.
---
## Disabling Subagents
```json
{
"permissions": {
"deny": ["Agent(Explore)", "Agent(my-custom-agent)"]
}
}
```
Or via CLI: `claude --disallowedTools "Agent(Explore)"`
---
## Key Takeaways
- Subagents run in **isolated context windows** — verbose output never pollutes your main conversation
- Define them as `.md` files in `.claude/agents/` (project) or `~/.claude/agents/` (user)
- The `description` field is the routing key — write it clearly so Claude knows when to delegate
- Use `tools` or `disallowedTools` to enforce least-privilege access
- `model: haiku` for fast/cheap research tasks; `model: opus` for deep analysis
- `memory: project` enables cross-session learning stored alongside the codebase
- `isolation: worktree` gives the subagent a throwaway git clone — safe for risky operations
- Subagents **cannot** spawn other subagents; use Skills or chain from main conversation
- Background subagents run concurrently; permissions must be approved upfront
---
## Sources
- [Create custom subagents — Claude Code docs](https://code.claude.com/docs/en/sub-agents)