tools/AgentTool/ — Sub-Agent Orchestration Tool

Spawns child agent tasks for parallel or delegated work

Creates sub-agents that can independently use tools, process queries, and return results. Core of the multi-agent architecture (swarms). Manages agent lifecycle, configuration loading, memory persistence, prompt caching, and result aggregation across built-in, custom, and plugin agent types.

15
Files
5
Agent Sources
3
Memory Scopes
200
Max Turns

📚 What is this & why does it exist?

AgentTool is how Claude Code delegates complex tasks to specialized sub-agents. Instead of one monolithic AI trying to do everything, AgentTool lets the parent agent spawn child workers — each with its own tool access, working directory, and system prompt. This is the foundation for features like parallel task execution, specialized exploration agents, and team-based multi-agent swarms.

💡 Real-world analogy

Think of AgentTool as a team lead who can hire temporary contractors. Each sub-agent gets its own workspace (potentially an isolated git worktree), tool access (a filtered set of available tools), and a clear assignment (the prompt). The team lead tracks progress, can run multiple contractors in parallel, and aggregates their reports into a final deliverable. Some contractors are built-in specialists (Explore, Plan), while others are custom-trained for specific project needs. The team lead manages their memory so past learnings carry forward across sessions.

Contents

Architecture

flowchart TD
  A["Parent Agent"] -->|"tool_use: Agent"| B["AgentTool.call()"]
  B --> C{"Fork enabled?"}
  C -->|"yes + no subagent_type"| D["buildForkedMessages()"]
  C -->|"no / explicit type"| E{"team_name set?"}
  E -->|"yes"| F["spawnTeammate()"]
  E -->|"no"| G["resolveAgentTools()"]
  D --> H["runAgent() with fork context"]
  F --> I["Multi-agent spawn"]
  G --> J["filterToolsForAgent()"]
  J --> K["loadAgentMemoryPrompt()"]
  K --> L["runAgent() async generator"]
  L --> M["Stream events + progress"]
  M --> N{"Background?"}
  N -->|"yes"| O["Register LocalAgentTask"]
  N -->|"no"| P["finalizeAgentTool()"]
  O --> P

Agent Type Hierarchy

flowchart LR
  AD["AgentDefinition"] --> BA["BuiltInAgentDefinition"]
  AD --> CA["CustomAgentDefinition"]
  AD --> PA["PluginAgentDefinition"]
  BA --> EX["Explore agent"]
  BA --> PL["Plan agent"]
  BA --> FK["Fork agent"]
  CA --> MD["Markdown config"]
  CA --> JS["JSON settings"]
  PA --> MCP["MCP plugin agents"]
  style BA fill:#1a3a2a,stroke:#3fb950
  style CA fill:#2a2a1a,stroke:#d29922
  style PA fill:#2a1a2a,stroke:#f85149

Key Classes & Functions

Class / FunctionFilePurpose
AgentToolAgentTool.tsxMain tool definition via buildTool(); handles fork routing, team spawning, agent selection, worktree isolation
runAgent()runAgent.tsCore async generator: MCP setup, tool assembly, system prompt construction, stream event generation (973 LOC)
resumeAgentBackground()resumeAgent.tsResumes interrupted background agents; restores state from persisted messages
filterToolsForAgent()agentToolUtils.tsFilters parent tool set for agent context; blocks disallowed/async tools
resolveAgentTools()agentToolUtils.tsResolves agent tool spec ('*' wildcard, explicit list) to actual tool instances
finalizeAgentTool()agentToolUtils.tsGenerates final tool result with usage stats, model info, context metadata
buildForkedMessages()forkSubagent.tsBuilds byte-identical message prefixes for fork children (prompt cache sharing)
isForkSubagentEnabled()forkSubagent.tsFeature gate check for implicit fork when subagent_type omitted
getAgentDefinitionsWithOverrides()loadAgentsDir.tsLoads agents from all sources: built-in, user (~/.claude), project (.claude), plugin, CLI args
getBuiltInAgents()builtInAgents.tsReturns built-in agent definitions (Explore, Plan) gated by feature flags
loadAgentMemoryPrompt()agentMemory.tsLoads MEMORY.md contents with scope-specific guidelines; injects into system prompt
checkAgentMemorySnapshot()agentMemorySnapshot.tsDetects newer project snapshots; returns initialize | prompt-update | none
getAgentColor()agentColorManager.tsAssigns unique color to agent type for UI grouping (8 colors)
resolveAgentOverrides()agentDisplay.tsDeduplicates agents by source priority; marks overridden agents for display
getPrompt()prompt.tsGenerates agent list injection for system prompt; formats available agents

Data Structures

TypeNameDescription
InputpromptTask description and instructions for the sub-agent
Inputsubagent_typeAgent type selector: general-purpose, explore, plan, fork, or custom name
Inputdescription3–5 word human-readable summary for UI display
InputmodelModel override: sonnet | opus | haiku | inherit
InputisolationExecution isolation: worktree (git) or remote (CCR)
Inputname / team_nameMulti-agent addressing: agent name + team name for swarm spawning
OutputAgentToolResultStatus (success | failed | timeout | killed), usage stats, model, agent ID
TypeAgentMemoryScopeuser | project | local — memory persistence scope
TypeAgentColorName8 colors for UI: red, blue, green, yellow, purple, orange, pink, cyan
TypeResolvedAgentToolsResolved tool spec with valid/invalid tools, wildcard flag, allowed types
ConstONE_SHOT_BUILTIN_AGENT_TYPESBuilt-in agents that skip agentId/SendMessage to save tokens
ConstFORK_SUBAGENT_TYPEType identifier for fork-based sub-agents: 'fork'

Interactions

DirectionPartnerInterfaceDescription
→Model APIqueryModelWithStreaming()Sub-agent makes its own API calls with inherited or overridden model
→MCP serversinitializeAgentMcpServers()Initializes agent-specific MCP server connections; tracks new vs shared clients
→Permission systemToolPermissionContextSupports plan | acceptEdits | bubble permission modes per agent
→Git worktreescreateAgentWorktree()Creates isolated git worktree for parallel file operations without conflicts
→Task systemLocalAgentTaskBackground agents registered as async tasks with streaming progress
→Memory filesystem~/.claude/agent-memory/Persists and loads agent-specific MEMORY.md across sessions
←Parent AgentLooptool_use blockReceives spawn request from model’s tool call
→Skills systemloadSkillsDir()Plugin agents may activate additional skills on demand
→AnalyticslogEvent()Records agent spawn, completion, token usage, and model selection
↔SendMessageToolspawnTeammate()Multi-agent swarm: teammates communicate via SendMessage

Agent Source Priority

When multiple sources define agents with the same type, higher-priority sources override lower ones. The resolution order (highest to lowest):

  1. CLI argument agents — Passed via command-line flags, highest priority
  2. User agents — Defined in ~/.claude/agents/ (markdown or JSON)
  3. Project agents — Defined in .claude/agents/ (shared via VCS)
  4. Local agents — Machine-specific, not in version control
  5. Managed agents — Organization-provided agent definitions
  6. Plugin agents — Loaded from MCP plugin servers
  7. Built-in agents — Explore, Plan, Fork (lowest priority, always available)

Configuration

Knob / ParameterDefaultDescription
maxTurns200Maximum conversation turns before agent auto-terminates
modelinheritModel selection: sonnet, opus, haiku, or inherit from parent
permissionModebubblePermission handling: plan | acceptEdits | bubble to parent
memorynoneMemory scope: user | project | local for MEMORY.md persistence
isolationnoneExecution isolation: worktree (git) or remote (CCR)
tools['*']Tool allowlist; '*' expands to all minus restricted set
disallowedTools[]Tool denylist; takes precedence over allowlist
FORK_SUBAGENT gateoffFeature flag enabling implicit fork when subagent_type omitted
BUILTIN_EXPLORE_PLAN_AGENTSonFeature flag for Explore & Plan built-in agents
tengu_auto_background_agentsoffAuto-background agents after 120s timeout
CLAUDE_CODE_SIMPLEfalseEnv var: skip custom agents, load only built-ins
CLAUDE_CODE_REMOTE_MEMORY_DIRunsetMount point for persistent agent memory in remote environments

Directory Map

Source tree for AgentTool
AgentTool/
├── AgentTool.tsx              ← Main tool definition: call(), fork routing, team spawn, worktree
├── UI.tsx                     ← React rendering: agent progress, status badges, color display
├── agentColorManager.ts       ← Color assignment for multi-agent UI grouping (8 colors)
├── agentDisplay.ts            ← Agent deduplication, override resolution, source grouping
├── agentMemory.ts             ← MEMORY.md loading with user/project/local scopes
├── agentMemorySnapshot.ts     ← Project snapshot sync: initialize, replace, mark synced
├── agentToolUtils.ts          ← Tool filtering, resolution, finalization, async lifecycle
├── built-in/                  ← Built-in agent prompt templates and definitions
├── builtInAgents.ts           ← Explore, Plan, Fork agent definitions with feature gates
├── constants.ts               ← AGENT_TOOL_NAME, ONE_SHOT types, disallowed tool lists
├── forkSubagent.ts            ← Fork experiment: message building, cache sharing, guards
├── loadAgentsDir.ts           ← Multi-source agent loading: markdown, JSON, plugins, CLI
├── prompt.ts                  ← Agent list injection, formatting, system prompt generation
├── resumeAgent.ts             ← Background agent resumption from persisted state
└── runAgent.ts                ← Core execution engine: MCP, tools, streaming (973 LOC)

Deep-Dive Highlights

Core mechanisms from AgentTool have been extracted into dedicated focus pages for in-depth exploration. Each page covers one algorithm, protocol, or subsystem with diagrams, code walks, and configuration details.

Deep-Dive Pages

Fork Sub-Agent Experiment Focus

Byte-identical message prefixes for prompt cache sharing, recursive fork guards, per-child directives, and worktree context notices.

Extracted topic page

Agent Memory System Focus

Three-scope memory persistence (user, project, local), snapshot synchronization, remote mount support, and MEMORY.md lifecycle.

Extracted topic page

Agent Loading & Resolution Focus

Multi-source agent discovery from markdown, JSON, plugins, and CLI args. Override priority, deduplication, and MCP requirement filtering.

Extracted topic page

Execution Engine & Streaming Focus

The runAgent() async generator: MCP initialization, tool pool assembly, system prompt construction, stream event generation, and Perfetto tracing.

Extracted topic page

Code Examples

Example: Agent Tool Resolution with Wildcards

// agentToolUtils.ts — Resolve agent tool spec to actual tools
export function resolveAgentTools(
  agentDef: AgentDefinition,
  availableTools: Tools,
): ResolvedAgentTools {
  const toolSpec = agentDef.tools ?? ['*'];
  const hasWildcard = toolSpec.includes('*');

  if (hasWildcard) {
    // Expand '*' to all available tools minus restricted set
    const restricted = new Set([
      ...ALL_AGENT_DISALLOWED_TOOLS,
      ...(agentDef.disallowedTools ?? []),
    ]);
    return {
      hasWildcard: true,
      validTools: availableTools
        .filter(t => !restricted.has(t.name))
        .map(t => t.name),
      invalidTools: [],
      resolvedTools: availableTools.filter(t => !restricted.has(t.name)),
    };
  }

  // Explicit tool list — validate each name exists
  const validTools: string[] = [];
  const invalidTools: string[] = [];
  for (const name of toolSpec) {
    if (name.startsWith('mcp__') || availableTools.find(t => t.name === name)) {
      validTools.push(name);
    } else {
      invalidTools.push(name);
    }
  }
  return { hasWildcard, validTools, invalidTools,
    resolvedTools: availableTools.filter(t => validTools.includes(t.name)) };
}

Example: Fork Message Building for Cache Sharing

// forkSubagent.ts — Build byte-identical prefixes for fork children
export function buildForkedMessages(
  directive: string,
  assistantMessage: AssistantMessage,
): MessageType[] {
  // All fork children share identical placeholder results for tool_use blocks
  // Only the final directive text differs per child → maximizes cache hits
  const placeholderResults = assistantMessage.content
    .filter(block => block.type === 'tool_use')
    .map(block => ({
      type: 'tool_result' as const,
      tool_use_id: block.id,
      content: 'Fork started — processing in background',
    }));

  return [
    ...historyMessages,
    { role: 'assistant', content: assistantMessage.content },
    { role: 'user', content: [
      ...placeholderResults,
      { type: 'text', text: buildChildMessage(directive) },
    ]},
  ];
}