← Back to index
Chapter 4

Multi-Agent Architecture

Six built-in agent roles, how AgentTool.tsx dispatches sub-agents, fork path cache optimization, and the full agent lifecycle in runAgent.ts.

Six Built-In Agents

Claude Code ships with six named agent roles, each with a distinct system prompt and permission profile:

General Purpose — the default agent you interact with. Full tool access, full permission scope. This is the agent that runs in the main loop.

Explore — strict read-only. No writes, no shell commands that modify state, no external calls. Designed for codebase reconnaissance: understanding structure, finding relevant files, mapping dependencies. Defaults to Haiku (the smaller, faster model) for external users because exploration tasks are high-volume and relatively low-complexity.

Plan — takes the output of Explore and produces a structured plan. No execution, no writes. The output is a task plan document, not code.

Verification — the adversarial agent. Its 130-line system prompt explicitly instructs it to try to break what the main agent produced. It looks for rationalization traps: cases where the main agent convinced itself something worked when it doesn’t, or where a test passes for the wrong reason. The prompt lists specific failure modes by name.

Claude Code Guide — knows the Claude Code system itself: tools, commands, slash commands, configuration options. Used when the agent needs to answer questions about its own capabilities.

Statusline Setup — narrow-scope specialist for configuring terminal statusline integrations (shell prompts, tmux status bars). Constrained to that domain.

Explore Agent: Read-Only With Teeth

The Explore agent’s read-only constraint isn’t just “don’t call Write.” It includes explicit prohibitions:

  • No Bash commands that have side effects (even git commands that could modify state)
  • No creating files, even temporary ones
  • No modifying any configuration
  • Treat any ambiguous action as prohibited

“Strict read-only” in this context means the agent was designed with the assumption that it will be invoked on unknown codebases that may be sensitive, and that its job is to gather information without leaving any trace. The model selection (Haiku by default) also reflects this: the task is pattern recognition and summarization, not complex reasoning.

Verification Agent: “Try to Break It”

The Verification agent’s system prompt deserves attention as a design artifact. It’s 130 lines. The core instruction is simple: your job is not to confirm that the implementation works, but to find evidence that it doesn’t.

The prompt explicitly names rationalization traps:

  • Tests that pass because they’re testing the wrong thing
  • Logic that’s correct in the test environment but would fail in production
  • Edge cases the main agent assumed wouldn’t occur
  • Assumptions buried in comments that are actually load-bearing

The framing matters. A verification agent told “check if this is correct” will often find it correct. An agent told “try to break it” will approach the same code adversarially and find different issues. The 130-line prompt is largely an extended elaboration of this adversarial stance.

AgentTool.tsx: 1397 Lines of Dispatch

AgentTool.tsx is the dispatch center for all sub-agent invocations. When the main agent calls AgentTool, this file handles:

  • Role selection (which of the six agents to use, or a custom role)
  • System prompt assembly for the sub-agent
  • Inherited context packaging
  • Spawning the sub-agent’s own runAgent loop
  • Result collection and packaging for return to the main agent

At 1397 lines, it’s the fourth-largest file in the codebase. The complexity comes from the combination of role management, context inheritance, permission scoping, and the mechanics of running a full agent loop as a tool call within another agent loop.

Fork Path and Cache Optimization

When the main agent spawns a sub-agent, it has a choice: give the sub-agent a fresh system prompt, or pass the main agent’s system prompt byte-for-byte.

Claude Code uses the byte-for-byte fork path when possible. The reason is prompt caching. The model caches KV representations of prompts — but only if the prompt is identical to one it’s seen before. If the sub-agent’s system prompt is a substring or modified version of the parent’s, the cache misses. If it’s identical, the cache hits.

The fork path means the sub-agent pays no additional cost to process the static portion of the system prompt — it was already cached from the parent’s invocation. On tasks that spawn many sub-agents (exploratory codebase analysis, parallel verification runs), this cache reuse compounds into significant cost reduction.

runAgent.ts: The Full Lifecycle

runAgent.ts (973 lines) contains the complete agent lifecycle:

  • Pre-run setup: context initialization, tool registration, permission scope setup
  • The run loop: calls into query.ts’s state machine
  • Tool result handling: collecting results from tool calls back into context
  • Mid-run state management: handling interrupts, pauses, context compression triggers
  • Post-run cleanup: result packaging, state persistence, telemetry recording

Every agent — main or sub — runs through runAgent. The main loop in main.tsx is runAgent with the General Purpose role. The Explore agent spawned by AgentTool is runAgent with the Explore role and a constrained permission set.

Task System

The task system provides five task types for tracking units of work within an agent run: task, subtask, parallel_task, sequential_task, and checkpoint. These feed into the tasks/ directory (12 files). Tasks are not just bookkeeping — they’re used by the Verification agent to know what was supposed to happen, and by the Plan agent to structure its output so downstream agents can consume it.


Reference: This chapter draws on Xiao Tan’s (@tvytlx) Claude Code Architecture Deep Dive V2.0 report.