← back to manual

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 Bash approval 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:

  1. 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.
  2. settings.json field (e.g. translator_subagent_model) — model-only override that leaves the embedded body intact.
  3. 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 + architect and all three become available via Task(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 the agent dirs the 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 /agent when 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).