Skip to content

AgentTool 深度解读 —— Claude Code 中最复杂的单个模块

AgentTool 不是一个普通工具 —— 它是 「生成 Agent 的 Agent」,负责子代理的定义加载、上下文隔离、执行编排、通信协调和生命周期管理。单文件 ~1400 行,加上 Swarm 系统总计超过 4000 行,是 Claude Code 中最复杂的子系统。

AgentTool 生态全景
├── tools/AgentTool/ ← Agent 工具本体
│ ├── AgentTool.tsx (1397 行) 工具定义 + UI 渲染
│ ├── runAgent.ts (36KB) Agent 执行引擎
│ ├── forkSubagent.ts (211 行) Fork 语义实现
│ └── loadAgentsDir.ts (26KB) Agent 定义加载
├── utils/swarm/ ← 多 Agent 编排系统
│ ├── inProcessRunner.ts (1552 行) 进程内 Teammate 运行时
│ ├── permissionSync.ts (928 行) 跨进程权限同步
│ ├── teamHelpers.ts (683 行) 团队文件管理
│ └── spawnInProcess.ts (329 行) Teammate 生成
├── utils/worktree.ts (16KB) Git Worktree 隔离
└── tasks/ ← 任务系统集成
├── LocalAgentTask/ (682 行) 本地 Agent 任务
├── InProcessTeammateTask/ (125 行) 进程内 Teammate 任务
└── RemoteAgentTask/ (855 行) 远程 Agent 任务

关键文件tools/AgentTool/loadAgentsDir.ts

// 基础定义
type BaseAgentDefinition = {
agentType: string // 如 "general-purpose", "Explore"
tools: string[] | ['*'] // 可用工具列表,'*' 表示全部
model: string | 'inherit' // 使用的模型,'inherit' 继承父级
maxTurns: number // 最大轮次
permissionMode: string // 'default' | 'auto' | 'bypass' | 'bubble'
getSystemPrompt(): string // 系统提示词生成
mcpServers?: McpServerConfig[] // Agent 专属 MCP 服务器
}
// 三种来源
type BuiltInAgentDefinition // 内置 Agent(代码定义)
type CustomAgentDefinition // 用户自定义(~/.claude/agents/*.md)
type PluginAgentDefinition // 插件提供
Agent 类型模型工具集模式用途
general-purpose继承父级全部 (*)default通用研究/执行
ExploreHaiku (快速)只读工具,排除 AgentONE_SHOT代码库探索
Plan继承父级只读工具ONE_SHOT架构设计
Verification继承父级全部default「破坏性测试」验证
Code Guide继承父级7 个工具default交互式指导
Statusline Setup继承父级终端配置工具default状态栏设置
built-in → plugin → user (~/.claude/agents/) → project → flag → policy
后加载的覆盖前面的(同名时)

自定义 Agent 格式(Markdown Frontmatter)

Section titled “自定义 Agent 格式(Markdown Frontmatter)”
---
agentType: my-reviewer
tools: [Read, Grep, Glob]
model: haiku
maxTurns: 10
permissionMode: auto
---
你是一个代码审查专家...(系统提示词)
  • Explore Agent 用 Haiku 模型 —— 探索类任务不需要最强模型,用快速模型降本提速
  • ONE_SHOT 模式 —— Explore 和 Plan Agent 执行一次就返回,不进入交互循环
  • Agent 专属 MCP —— 每个 Agent 可以有自己的 MCP 服务器,生命周期与 Agent 绑定

关键文件tools/AgentTool/AgentTool.tsx

const inputSchema = z.object({
// ═══ 核心参数 ═══
description: z.string(), // 任务描述(3-5 词)
prompt: z.string(), // 完整任务提示
// ═══ Agent 选择 ═══
subagent_type: z.string().optional(), // Agent 类型(省略则 Fork)
model: z.enum(['sonnet', 'opus', 'haiku']).optional(), // 模型覆盖
// ═══ 执行方式 ═══
run_in_background: z.boolean().optional(), // 后台运行
isolation: z.enum(['worktree']).optional(), // Worktree 隔离
// ═══ 团队协作 ═══
name: z.string().optional(), // Agent 名称(可通过 SendMessage 寻址)
team_name: z.string().optional(), // 所属团队
mode: z.enum([...]).optional(), // 权限模式
})
type Output =
| { type: 'sync_completion', result: string } // 同步完成
| { type: 'async_launched', taskId: string } // 异步启动
| { type: 'teammate_spawned', agentId: string } // Teammate 生成(内部)
| { type: 'remote_launched', taskId: string } // 远程启动(内部)
call(input)
├─ Phase 1: 参数校验
│ ├─ 防止嵌套团队生成
│ └─ 校验 Agent 类型是否存在
├─ Phase 2: Agent 选择
│ ├─ 有 subagent_type → 查找对应 Agent 定义
│ └─ 无 subagent_type → Fork 模式(继承父上下文)
├─ Phase 3: 系统提示词构建
│ ├─ Agent 自定义提示词
│ ├─ + 工具使用说明
│ └─ + 上下文注入(CLAUDE.md 等)
├─ Phase 4: 隔离环境设置
│ ├─ Worktree 模式 → 创建 Git Worktree
│ ├─ Remote 模式 → 连接远程 CCR 实例
│ └─ 普通模式 → 使用当前工作目录
├─ Phase 5: 工具池组装
│ ├─ tools: ['*'] → 继承父级全部工具
│ ├─ tools: ['Read', 'Grep'] → 精确工具集
│ └─ Fork 模式 → useExactTools=true(复制父级完整工具池)
├─ Phase 6: MCP 服务器准备
│ ├─ 等待 Agent 专属 MCP 连接(最多 30s)
│ └─ 合并继承的 + Agent 定义的 MCP 服务器
├─ Phase 7: 执行分支
│ ├─ 同步执行 → runAgent() → 等待完成
│ └─ 异步执行 → registerAsyncAgent() → 后台运行
└─ Phase 8: 清理
├─ 关闭 Agent 专属 MCP 服务器
├─ 清理 Worktree(如果没有变更)
└─ 返回结果

3. Fork 语义 —— Prompt Cache 共享的精髓

Section titled “3. Fork 语义 —— Prompt Cache 共享的精髓”

关键文件tools/AgentTool/forkSubagent.ts

Fork 是当 subagent_type 省略时的默认行为。它的核心思想是:子 Agent 继承父对话的完整上下文,并通过字节级相同的前缀最大化 Prompt Cache 命中率

父 Agent 对话:
┌────────────────────────────────────────┐
│ System Prompt │ ← 字节相同
│ Message 1 (user) │ ← 字节相同
│ Message 2 (assistant + tool_use) │ ← 字节相同
│ Message 3 (tool_result) │ ← 字节相同
│ ... │ ← 字节相同
│ 当前 assistant 消息 (含 Agent tool_use) │ ← 字节相同
└────────────────────────────────────────┘
Fork 子 Agent A: Fork 子 Agent B:
┌────────────────────────────────────────┐ ┌────────────────────────────────────────┐
│ 【完全相同的前缀】 │ │ 【完全相同的前缀】 │
│ tool_result: placeholder (相同) │ │ tool_result: placeholder (相同) │
│ 子 Agent A 的具体指令 ← 唯一差异点 │ │ 子 Agent B 的具体指令 ← 唯一差异点 │
└────────────────────────────────────────┘ └────────────────────────────────────────┘
↑ ↑
共享 Prompt Cache 共享 Prompt Cache
// 1. 生成合成 Fork Agent 定义
const FORK_AGENT = {
tools: ['*'], // 继承所有工具
model: 'inherit', // 继承模型
permissionMode: 'bubble', // 权限冒泡到父级
maxTurns: 200, // 高轮次上限
}
// 2. 克隆父对话的所有 tool_use,创建相同的 placeholder tool_result
// 这保证所有 Fork 子 Agent 的消息前缀字节级相同
const placeholderResults = parentToolUses.map(tu => ({
type: 'tool_result',
tool_use_id: tu.id,
content: '[placeholder]' // 所有子 Agent 都用相同的 placeholder
}))
// 3. 只有最后的「指令」不同
const childDirective = `
Scope: ${input.prompt}
Result: 必须包含 Key Files / Files Changed / Issues
10 条不可违反的规则(禁止递归 Fork、禁止对话、直接使用工具...)
`
路径 1(主): querySource === 'agent:builtin:fork'
→ 如果当前已经是 Fork 子 Agent,禁止再次 Fork
路径 2(备): 扫描消息中的 <fork_boilerplate> 标签
→ 防止 autocompact 后 querySource 丢失的情况
  • 字节级前缀相同 → Prompt Cache 命中 —— 这是成本优化的核心。多个 Fork 子 Agent 共享同一份 cache,避免重复计算
  • permissionMode: 'bubble' —— Fork 子 Agent 的权限请求「冒泡」到父 Agent,由父 Agent 的 UI 处理
  • 10 条不可违反规则 —— 用自然语言约束子 Agent 的行为边界,包括「禁止递归 Fork」「不要对话,直接干活」等

关键文件tools/AgentTool/runAgent.ts

async function* runAgent(config): AsyncGenerator<Message> {
// 1. 上下文初始化
const fileStateCache = parentCache.clone() // 克隆文件状态缓存
const perfTrace = createPerfettoAgent() // 性能追踪
const mcpServers = setupAgentMcp() // MCP 服务器
const systemPrompt = buildSystemPrompt() // 系统提示词
const hooks = registerAgentHooks() // Hook 注册
// 2. 进入查询循环
for await (const event of query({
messages: initialMessages,
tools: toolPool,
systemPrompt,
maxTurns: agent.maxTurns,
})) {
// 3. 流式 yield 消息给父 Agent
if (event is AssistantMessage) yield event
if (event is ToolUseSummary) yield event
if (event is Progress) yield event
// 4. 超过 maxTurns → 生成 TombstoneMessage
if (turnCount > maxTurns) {
yield TombstoneMessage("max turns reached")
break
}
}
// 5. 清理
await cleanupMcpServers()
await unregisterHooks()
}
Fork 模式 vs 普通模式:
Fork 模式:
- useExactTools = true → 完全继承父级工具池(不重新组装)
- forkContextMessages → 携带完整父对话历史
- systemPrompt override → 使用父级系统提示词(保证字节相同)
普通模式:
- useExactTools = false → 按 Agent 定义组装工具池
- 空消息历史 → 全新对话
- 独立 systemPrompt → 按 Agent 定义生成

关键文件utils/swarm/inProcessRunner.ts(1552 行)

Leader Agent Teammate Agent(进程内)
┌──────────┐ ┌──────────┐
│ │── sendMessage() ──→ │ │
│ REPL │ │ 独立的 │
│ UI │←── mailbox 通知 ── │ 查询循环 │
│ │ │ │
│ 权限 │←── 权限请求桥接 ── │ 共享 │
│ 对话框 │── 权限结果返回 ──→ │ 进程空间 │
└──────────┘ └──────────┘

子 Agent 在进程内运行,但权限对话框在父 Agent 的 UI 中。怎么办?

createInProcessCanUseTool() {
// 方案 1(标准路径): 直接使用 Leader 的 React 对话框
// → Leader UI 显示 "[Worker: agent-name] 请求执行 git push"
// → 用户批准/拒绝
// → 结果返回给 Worker
// 方案 2(Mailbox 回退): 当 Leader 不可用时
// → Worker 将权限请求写入 pending/ 目录
// → Leader 轮询 pending/ 目录(500ms 间隔)
// → 处理后写入 resolved/ 目录
// → Worker 轮询 resolved/ 获取结果
}

关键文件utils/swarm/permissionSync.ts(928 行)

Worker 进程 Leader 进程
┌──────────┐ ┌──────────┐
│ 工具执行 │ │ REPL │
│ ↓ │ │ UI │
│ 需要权限 │ │ │
│ ↓ │ │ │
│ 写入 │──→ pending/perm-xxx.json │ │
│ pending/ │ │ 扫描 │
│ ↓ │ │ pending/ │
│ 轮询 │ │ ↓ │
│ resolved/│ │ 显示 │
│ ↓ │←── resolved/perm-xxx.json│ 对话框 │
│ 获取结果 │ │ ↓ │
│ ↓ │ │ 写入 │
│ 继续执行 │ │ resolved/│
└──────────┘ └──────────┘

权限请求数据结构

type SwarmPermissionRequest = {
id: string // perm-{timestamp}-{random}
workerId: string // 发起请求的 Worker ID
toolName: string // 工具名
toolUseId: string // 工具调用 ID
input: Record<string, unknown> // 工具输入
status: 'pending' | 'resolved'
feedback?: string // 用户反馈
permissionUpdates?: PermissionRule[] // 权限规则更新
}

关键文件utils/swarm/teamHelpers.ts

~/.claude/teams/{team-name}/
├── config.json ← 团队配置文件
│ {
│ "members": [
│ {
│ "agentId": "reviewer@my-team",
│ "tmuxPaneId": "...",
│ "sessionId": "...",
│ "mode": "auto",
│ "color": "#ff6b6b"
│ }
│ ]
│ }
└── permissions/ ← 权限同步目录
├── pending/ ← 待处理请求
└── resolved/ ← 已处理请求
type ProgressTracker = {
toolUseCount: number // 工具使用次数
latestInputTokens: number // 最近一次输入 Token
cumulativeOutputTokens: number // 累计输出 Token
recentActivities: string[] // 最近 5 条活动(用于 UI 显示)
}
Teammate 空闲时:
1. 检测到没有更多工具调用
2. 发送 TeammateIdle 通知给 Leader
3. Leader 可以:
a. 发送新消息(SendMessage)继续任务
b. 等待其他 Teammate 完成
c. 终止 Teammate

关键文件utils/worktree.ts

多个 Agent 同时修改同一个代码库会产生文件冲突。Git Worktree 为每个 Agent 创建独立的工作树。

创建:
1. getOrCreateWorktree(slug, sessionId)
2. git fetch origin (获取最新代码)
3. git worktree add -B claude-code/session-{id} .claude/worktrees/{slug}/
4. 可选: sparse-checkout (只检出需要的文件)
5. 创建 symlinks → node_modules 等大目录(避免重复)
6. 触发 WorktreeCreate Hook
使用:
- Agent 的 cwd 指向 worktree 路径
- 所有文件操作在隔离环境中进行
- 独立的 Git 分支
清理:
1. hasWorktreeChanges() → git diff + git status
2. 有变更 → 保留 worktree,返回路径和分支信息
3. 无变更 → git worktree remove --force + git branch -D
4. 触发 WorktreeRemove Hook
repo-root/
└── .claude/
└── worktrees/
└── {flattened-slug}/ ← 每个 Agent 一个目录
├── .git ← 独立的 Git 工作树
├── src/ ← 代码(独立副本)
└── node_modules → ../../node_modules ← symlink(共享)
// Slug 校验:防止路径遍历
validateSlug(slug) {
// 最大 64 字符
// 只允许 [a-zA-Z0-9._-]
// 禁止 . 和 .. 段
}
// 环境变量:防止凭据泄露
env = {
GIT_TERMINAL_PROMPT: '0', // 禁止交互式密码提示
GIT_ASKPASS: '', // 禁止密码对话框
}
stdin: 'ignore' // 不允许标准输入

维度进程内 (InProcess)本地子进程 (Local)远程 (Remote)
运行位置同一进程独立进程CCR 远程实例
状态共享共享内存文件系统通信HTTP/WebSocket
权限桥接React 对话框直接访问Mailbox 文件轮询API 调用
MCP 服务器共享 + Agent 专属独立远程实例的 MCP
文件隔离共享(或 Worktree)Worktree独立文件系统
生命周期AsyncLocalStoragesubprocessHTTP session
适用场景快速任务、需要共享上下文需要隔离的任务跨机器协作

8. 架构洞察:多 Agent 协作的工程模式

Section titled “8. 架构洞察:多 Agent 协作的工程模式”

模式 1: Context Isolation vs Context Sharing

Section titled “模式 1: Context Isolation vs Context Sharing”
完全隔离(Remote) ←──────────────────→ 完全共享(Fork)
部分隔离(Worktree)

Claude Code 提供了一个谱系,从完全隔离到完全共享,让用户根据任务需要选择。

子 Agent(无 UI)
↓ 权限请求
冒泡
父 Agent(有 UI)
↓ 显示对话框
用户决策
↓ 结果传回
子 Agent(继续执行)

这解决了「子 Agent 没有 UI 但需要人工审批」的问题。

成本对比:
普通模式: N 个子 Agent × 完整上下文 = N × 100% Token 成本
Fork 模式: 1 × 完整上下文 + N × 增量指令 ≈ 1 × 100% + N × 5%
假设父上下文 10K tokens,5 个子 Agent:
普通: 50K tokens(输入)
Fork: 10K + 5×500 = 12.5K tokens(75% 节省!)
Worktree 隔离的价值:
- 子 Agent A 在 worktree-a 中执行 `git reset --hard` → 不影响主仓库
- 子 Agent B 在 worktree-b 中修改 package.json → 不影响 Agent A
- 执行失败 → 直接删除 worktree,零副作用
permissionMode 谱系:
'default' → 每次询问(最安全)
'auto' → ML 分类器自动判断(平衡)
'bypass' → 跳过大部分检查(高效)
'bubble' → 冒泡到父级(Fork 专用)

子 Agent 可以有不同于父 Agent 的权限模式,实现「渐进式信任」。