深入浅出:Claude Code 的 Subagent 与 Fork Agent —— 多 Agent 协作的两种"分身术"
主 Agent 的上下文是稀缺资源。Subagent 用"新建一个干净的专家"来省它,Fork 用"复制一份自己"来延续它。同样叫"派个 Agent",底层是两种完全不同的策略。
目录
- 一、为什么一个 Agent 不够用?
- 二、Subagent:一次性的专家
- 三、Fork Agent:父会话的分身
- 四、核心差异对比
- 五、自定义一个 Subagent
- 六、并发与隔离的工程细节
- 七、总结
一、为什么一个 Agent 不够用?
1.1 三个绕不过去的瓶颈
| 瓶颈 | 症状 | 后果 |
|---|---|---|
| 上下文污染 | 为了找一行代码,读了 30 个文件 | 噪音永久留在主上下文,挤掉真正重要的信息 |
| 单线程执行 | 只能一个工具接一个工具跑 | 三个独立子问题要串行做完,慢 |
| 视角单一 | 写方案的和评方案的"是同一个人" | 自己审自己,盲区照不到 |
1.2 两种解法
解法 A:新建一个干净的专家 → Subagent(上下文隔离) 解法 B:复制一份当前的自己 → Fork Agent(上下文继承)💡核心观点:Subagent 解决的是"别把噪音带回家",Fork 解决的是"别丢掉已有的背景"。方向正好相反。
二、Subagent:一次性的专家
2.1 它是什么
Subagent 是主 Agent 通过Agent工具拉起的独立子任务执行体,关键特征只有一个 ——独立的上下文窗口。
主 Agent 上下文 ┌────────────────────┐ │ 用户需求 │ │ 讨论过程 / 关键决策 │ │ 少量摘要 │◀── 只有 final message 回得来 └─────────┬──────────┘ │ Agent 工具(只传一个 prompt 出去) ▼ ┌──────────────────────┐ │ Subagent 上下文 │ 全新的、空的窗口 │ ├ 自己的 system 提示 │ │ ├ 自己的工具集 │ │ ├ 读 30 个文件的噪音 │ ← 噪音到这里为止 │ └ 产出结论 │ └──────────────────────┘2.2 四个"自己的"
| 维度 | Subagent 的行为 |
|---|---|
| 上下文 | 全新,不继承父会话历史 |
| 系统提示词 | 来自 agent 定义,不是主 Agent 那份 |
| 工具集 | 定义里声明,可以是子集(如只读) |
| 模型 | 定义里的model,或调用时覆盖 |
2.3 内置的几种 Subagent
| 类型 | 定位 | 工具 |
|---|---|---|
| Explore | 广撒网搜索,只读 | 只读类 |
| Plan | 设计实现方案 | 排除编辑类 |
| general-purpose | 通用、多步、可写 | 全部 |
| claude-code-guide | 回答 Claude Code / SDK / API 用法 | 只读 + 联网 |
| statusline-setup | 配置状态栏 | 受限 |
💡核心观点:
Plan拿不到写工具、Explore拿不到写工具 ——能力靠工具集裁剪,不靠提示词嘱咐。这是"权限优于禁令"在 Agent 层的又一次体现。
三、Fork Agent:父会话的分身
3.1 它是什么
Fork 是通过subagent_type: "fork"拉起的 Agent。它和 Subagent 最大的不同:
Fork 是父会话的一个分支 —— 继承父的上下文与模型。
主 Agent 上下文(已跑了 50 轮) ┌────────────────────────────┐ │ 需求 → 调研 → 方案 A 讨论 │ │ 读过的文件 / 踩过的坑 │ └──────┬──────────────┬──────┘ │ fork │ fork ▼ ▼ ┌─────────┐ ┌─────────┐ │ 分支 1 │ │ 分支 2 │ ← 带着完整背景分头推进 │ 方案 A │ │ 方案 B │ └─────────┘ └─────────┘3.2 一条暴露设计的硬约束
Agent 工具的参数说明里有一句很值得玩味的话:
model: 可选,覆盖该 Agent 的模型。 若省略,用 agent 定义的模型,否则继承父。 ⚠️ 对 subagent_type: "fork" 无效 —— fork 永远继承父模型。为什么 fork 偏偏不许换模型?
| 原因 | 说明 |
|---|---|
| 前缀相同 | fork 带着父的完整上下文前缀 |
| 缓存命中 | 同模型 + 同前缀 → prompt cache 直接命中 |
| 换成别的模型 | 前缀优势归零,等于白 fork |
💡核心观点:Fork 继承模型不是"没做这个功能",而是为了 prompt cache。上下文一旦复制,模型就必须跟着复制,否则缓存失效 —— 这条限制是性能设计,不是功能缺失。
四、核心差异对比
| 维度 | Subagent | Fork Agent |
|---|---|---|
| 起点上下文 | 空白,只有传入的 prompt | 继承父会话全量历史 |
| 系统提示词 | 自己的 agent 定义 | 与父相同 |
| 模型 | 可独立指定 / 可覆盖 | 强制继承父,不可覆盖 |
| 工具集 | 定义里声明的子集 | 与父相同 |
| 缓存友好度 | 低(前缀不同) | 高(前缀相同,易命中) |
| 典型用途 | 搜索、审查、隔离噪音 | 并行试方案、延长当前思路 |
| 回传内容 | 只有 final message | 只有 final message |
| 能否续聊 | SendMessage可续 | SendMessage可续 |
4.1 一句话选型
要"干净的专家"(隔离噪音、独立视角、省 token) → Subagent 要"另一个我"(保留全部背景、分头并行推进) → Fork五、自定义一个 Subagent
5.1 Agent 定义文件
自定义 Subagent 就是一个带 frontmatter 的 Markdown 文件:
--- name: code-reviewer description: 审查代码变更,找出 bug 与安全风险。提交前主动使用。 tools: Read, Grep, Glob, Bash model: sonnet --- 你是资深代码审查员。审查时: 1. 先读 diff,理解变更意图 2. 重点检查:边界条件、错误处理、并发安全 3. 只报告你**确认**的问题,附 file_path:line_number 4. 不要复述代码,不要给无依据的猜测5.2 三个字段各自决定什么
| 字段 | 作用 | 设计要点 |
|---|---|---|
description | 主 Agent 据此判断"什么时候派它" | 写清触发时机,这是路由的依据 |
tools | 能力边界 | 只读任务就别给写工具 |
model | 成本 / 质量取舍 | 简单任务用轻模型 |
⚠️最容易写坏的字段是
description:它不是给人看的简介,是给主 Agent 看的路由条件。写"审查代码"太糊,写"提交前审查 diff,找 bug 与安全风险"才可路由。
六、并发与隔离的工程细节
6.1 并发:一条消息里发多个工具调用
| 机制 | 做法 | 效果 |
|---|---|---|
| 并发 | 同一条消息里放多个Agent调用 | 多个子 Agent 同时跑 |
| 异步 | run_in_background: true | 不阻塞主线程,完成再通知 |
| 文件隔离 | isolation: "worktree" | 各给一个 git worktree,互不踩踏 |
| 目录固定 | 工作目录在启动时 pin 住 | 子 Agent 切目录不影响父会话 |
要并行 → 一条消息多个 Agent 调用 要隔离 → isolation: worktree(改动冲突时必用,代价是 ~200-500ms + 磁盘) 要异步 → run_in_background6.2 隔离的代价与适用
| 场景 | 要不要 worktree |
|---|---|
| 只读搜索 / 审查 | ❌ 不需要 |
| 多个 Agent 同时改不同文件 | ⚠️ 视冲突风险 |
| 多个 Agent 同时跑迁移/重构 | ✅ 必须 |
6.3 结果回传:一个容易踩的坑
子 Agent 产出 final message │ ▼ 作为 tool result 返回给主 Agent │ ▼ ⚠️ 这个 result 不会展示给用户! │ ▼ 主 Agent 必须自己转述关键结论 ← 否则用户什么都看不到| 现象 | 原因 |
|---|---|
| 用户说"你派了 Agent 但我没看到结果" | final message 只回到主 Agent,不回显 |
| 主 Agent 回一句"已完成" | 偷懒了,应该转述结论 |
6.4 复用优先于重建
对于有状态的专家类 Agent(如claude-code-guide),正确做法是:
先检查是否已有在跑的或已完成的同类 Agent;有就用
SendMessage续聊,而不是新建一个。
| 做法 | 结果 |
|---|---|
SendMessage续聊 | 上下文保留,追问不丢背景 |
新建Agent | 从零开始,之前的调研全部白做 |
💡核心观点:新建 Agent 是"重新雇人",SendMessage 是"接着问他"。前者贵且会丢上下文,后者才是追问的正确姿势。
七、总结
7.1 核心要点
- Subagent = 干净的专家:独立上下文 / 独立 prompt / 独立工具集 / 可独立模型
- Fork = 父会话的分身:继承上下文与模型,
model覆盖对它无效 - Fork 不许换模型是为了缓存:前缀相同 + 模型相同 → prompt cache 命中
- 能力靠工具集裁剪:
Plan/Explore没有写工具,而非靠提示词劝阻 - 回传只有 final message:且不展示给用户,主 Agent 必须转述
- 追问用 SendMessage,别新建:新建 = 重新雇人,上下文全丢
7.2 最后的话
💡核心观点:多 Agent 协作的本质不是"人多力量大",而是上下文管理。Subagent 是在做减法 —— 把噪音挡在主上下文之外;Fork 是在做加法 —— 让已有的判断力可以并行复制。选错了,不是慢一点,而是主 Agent 的上下文被一步步撑爆。
记住:
- 面试/设计题常考:Agent 之间如何隔离上下文、如何避免"上下文爆炸"
- 工程红线:并行改文件必须隔离(worktree),否则互相覆盖
- 进阶方向:子 Agent 的提示词隔离、Workflow 的 pipeline/parallel 编排、
budget预算控制
标签:Claude Code, Subagent, Fork Agent, 多智能体, 上下文工程, AI Agent