Chapter 15 — Subagents
The Task tool lets the main agent delegate to a sub-agent: a
fresh, isolated copy of the agent with its own tool scope and its own
goal. Useful for branching work (explore multiple approaches in
parallel), protecting the main context (run a noisy exploration in a
child), or specialisation (hand off to a “reviewer” agent with
read-only tools).
Subagents are part of the same process — they run in-memory, not as separate OS processes. For true parallelism across processes, see Agent Teams in Chapter 17.
How it looks
❯ are the REST endpoints in this repo consistent with our naming
convention in AGENTS.md?
[tool: Task: (agent=reviewer, prompt=Check every route under src/api …)] …
[child:reviewer] Using Glob to find route files…
[child:reviewer] Found 14 routes; 3 don't match the convention
[tool: Task] ✓
Looking at the sub-agent's findings:
- `src/api/v1/getUsers.ts` should be `get_users.ts` per convention.
- `src/api/v1/FetchOrders.ts` should be `fetch_orders.ts`.
- `src/api/v2/createPost.ts` should be `create_post.ts`.
The parent sees only the sub-agent’s final text response, keeping the intermediate tool chatter out of the main context.
Agent definitions
Specific sub-agent behaviours are configured in
.thclaws/agents/*.md (project) or ~/.config/thclaws/agents/*.md
(user):
---
name: reviewer
description: Read-only code review with focus on conventions
model: claude-haiku-4-5
tools: Read, Glob, Grep, Ls
permissionMode: auto
maxTurns: 20
color: cyan
---
You are a code reviewer. Look at the code the parent points you at.
Flag:
- Naming inconsistencies with the project's `AGENTS.md` conventions.
- Missing tests alongside new code.
- Security-sensitive patterns (raw SQL, unsanitised input).
Return a concise bullet list. Don't propose fixes unless asked.
Frontmatter fields:
| Field | Purpose |
|---|---|
name |
Unique id (defaults to filename stem) |
description |
When-to-use text the parent sees |
model |
Model override for this agent |
tools |
Comma-separated tool allowlist |
disallowedTools |
Tool denylist |
permissionMode |
auto or ask (useful for “read-only” agents) |
maxTurns |
Max iterations (default 200) |
color |
Terminal colour for child output |
isolation |
worktree — give this agent its own git worktree (teams only) |
Invoking
There are two surfaces for spawning a subagent:
Model-driven — the Task tool
The parent agent invokes via Task:
Task(agent: "reviewer", prompt: "Check src/api for naming violations")
Typically you don’t call this directly — you ask the parent a question in English and it decides. The model sees the list of available agents in its system prompt (rendered from the agent defs).
The Task tool blocks the parent’s turn until the child finishes — the parent then sees the result as a tool result and continues. The child’s intermediate reasoning isn’t echoed into the parent’s context (that’s the whole point — keep main context clean), but the parent does pay for one full child run before its next move.
User-driven — the /agent slash command (GUI)
In the desktop GUI, you can spawn a subagent yourself without going through the main agent’s reasoning:
/agent translator แปลไฟล์ src/foo.md เป็นภาษาไทย
The chat surface confirms: ✓ spawned background agent 'translator' (id: side-abc123). While the translator runs:
- Main agent keeps accepting input — you can keep working with it. Side-channel agents run on their own tokio task, concurrent with main.
- Main’s history is unaffected. The prompt + result never enter the main conversation. The side-channel result lands as a separate bordered card in the chat surface (amber border = running, green = done, red = error).
- Cancel is independent. Pressing the main agent’s stop button does NOT kill side-channels. To cancel a side-channel use
/agent cancel <id>. - Permission requests stay distinguishable. If the side-channel asks for
Bashapproval while main is also doing tool calls, the approval modal labels each request with its source (“translator (background) wants to run Bash” vs “Main wants to run Bash”) so you don’t accidentally approve the wrong one.
/agents # list active background agents
/agent cancel side-abc123 # signal cancel to a specific channel
Side-channel agents share the same AgentDef registry — the named agents available via Task are the same ones available via /agent. Permissions, sandbox, MCP servers, and KMS access all behave identically.
/agent is the right surface when you know specifically what you want done, the work is well-scoped, and you want to keep doing other things in the main conversation while it runs. The model-driven Task tool stays the right choice when the parent agent’s reasoning should decide whether/when to delegate.
Recursion
A sub-agent can spawn further sub-agents up to max_depth = 3 by
default. Each level is more scoped:
parent (depth 0)
├─ reviewer (depth 1) — "look at auth routes"
│ └─ specialist (depth 2) — "audit JWT signing"
└─ tester (depth 1) — "write integration tests"
The Task tool at depth 3 disables recursion to prevent runaway chains.
Load order
Built-in (binary) → ~/.config/thclaws/agents.json → ~/.claude/agents/*.md →
~/.config/thclaws/agents/*.md → .thclaws/agents/*.md. Later wins
by name.
Built-in subagents
thClaws ships a curated set of subagents compiled into the binary —
no install step required. They appear alongside any user-defined
agents in Task(agent: "...") and /agent <name> invocations. A
disk-resident agent at .thclaws/agents/<name>.md of the same name
overrides the built-in.
| Name | Default model | What it does |
|---|---|---|
dream |
claude-opus-4-7 |
Consolidate the project’s KMS by mining recent sessions, deduping pages, surfacing insights. Invoked via the /dream slash command. See Chapter 9. |
translator |
gpt-4.1 |
Translate text or files between languages while preserving structure (markdown headings, lists, code blocks, frontmatter). Invoked via /agent translator <prompt> or Task(agent: "translator"). |
Override the model via settings.json
Each built-in subagent’s recommended model can be overridden from
settings.json without forking the embedded AgentDef body. Single
string only (AgentDef.model is Option<String>, no priority list):
// .thclaws/settings.json (project) or ~/.config/thclaws/settings.json (user)
{
"translator_subagent_model": "claude-sonnet-4-6"
}
Resolution chain:
- Disk-resident
<scope>/.thclaws/agents/translator.md— full override (replaces the entire AgentDef including instructions). Use this when you want to customize the prose, not just the model. settings.jsonfield (e.g.translator_subagent_model) — model-only override that leaves the embedded body intact.- Embedded built-in
model:frontmatter — fallback when neither is configured.
Each future built-in subagent that needs settings tunability gets its
own field (<name>_subagent_model). Same per-agent named-field
convention as the skill side (extract_save_skill_models etc.) — more
discoverable in settings.json than a generic map.
Plugin-contributed agents
Plugins (Chapter 16) can ship agent defs via an agents entry in
their manifest. Those dirs are walked after the standard ones and
merged additively — a plugin agent cannot override a user’s or
project’s existing agent with the same name. That means:
- You can install a plugin that ships a
reviewer+tester+architectand all three become available viaTask(agent: "…")and team spawns. - If you later add your own
.thclaws/agents/reviewer.md, it wins — the plugin’s is ignored until you remove yours. /plugin show <name>lists theagent dirsthe plugin contributes.
Subagents vs Side-channel agents vs Teams
| Task subagent | /agent side-channel |
Teams | |
|---|---|---|---|
| Trigger | Model decides via Task tool |
User types /agent |
Model uses SpawnTeammate |
| Process model | In-process, blocks parent’s turn | In-process tokio task, concurrent with parent | Multiple thclaws --team-agent processes, tmux-orchestrated |
| Parallelism | Serial (recursion depth, not concurrency) | Concurrent with main, but each side-channel sequential | Truly concurrent |
| Main’s history | Tool result lands in parent’s context | Untouched — result is a separate side bubble | Untouched — teammates have their own sessions |
| Isolation | Shared sandbox | Shared sandbox | Optional git worktree per teammate |
| Cancel | Inherits parent’s cancel | Independent — own cancel via /agent cancel <id> |
Independent — kill the teammate process |
| Messaging | None — child returns a string | None — final result delivered as event | Filesystem mailbox + task queue |
| Overhead | Negligible | Negligible | High — spins up 1+ extra processes |
| Use for | Model-driven sub-problem reduction | User-driven side errands while main works | Parallel streams of long-running work |
Rule of thumb:
- Default to model-driven
Task— let the parent agent decide when to delegate. Lowest ceremony. - Reach for
/agentwhen you (the user) know specifically what you want a specialist to do AND want to keep working in main while it runs. “Translate this file to Thai while I keep coding.” - Reach for teams when the work genuinely fans out across long-running parallel streams (build backend + frontend + ops in three parallel processes).