Claude Code 中主 Agent 与子 Agent 的交互机制
引言
用 Claude Code 写代码的时候,你会发现一个有意思的行为模式:遇到复杂或多步骤的任务时,它不会一个人硬扛,而是会派出"子 Agent"来并行或分步处理。
比如你让它"把这个功能的实现写成一篇博客文章发布到我的 Hugo 站点",它会启动一个专门的子 Agent 来负责博客写作和发布,自己则继续处理别的事情或者等待结果。
这篇文章基于我在实际使用中的观察,拆解这套多 Agent 协作机制的工作方式。
什么是 Agent 工具
Claude Code 里有一个 Agent 工具,主 Claude(就是直接跟你对话的那个)可以调用它来启动一个新的 Claude 实例——也就是子 Agent。
子 Agent 是一个完全独立的进程,拥有自己的上下文窗口,能使用 Read、Write、Edit、Bash、Grep 等工具自主工作。你可以把它理解为主 Agent 招来的一个临时同事:给它一个任务描述,它就独立干活,干完了交结果。
几个关键点:
- 子 Agent 看不到主 Agent 和用户之间的对话历史。它的上下文是全新的,只有启动时收到的 prompt。
- 子 Agent 启动后自主决策和执行,直到任务完成才返回结果。中间不需要主 Agent 干预。
- 主 Agent 只能看到子 Agent 最终返回的摘要,看不到它中间调用了哪些工具、读了哪些文件、做了哪些尝试。
- 用户看不到子 Agent 的返回内容,需要主 Agent 转述和过滤。
这个设计很像现实中的"委托"模式——你把任务交给别人,拿到结果,但不需要(也无法)微观管理每一步。
Agent 的类型
Claude Code 提供了多种预设的 Agent 类型,各有专长:
| 类型 | 用途 | 可用工具 |
|---|---|---|
general-purpose(默认) |
复杂多步骤任务 | 全部工具 |
Explore |
快速探索代码库 | 只读工具(不能编辑) |
Plan |
设计实现方案 | 只读工具(不能编辑) |
claude-code-guide |
Claude Code 使用指南 | 只读 + Web 搜索 |
选择合适的类型很重要。比如 Explore 类型的 agent 无法修改文件,这是一种安全约束——你只是想让它看看代码库的结构,不希望它动手改什么东西。而 general-purpose 拥有完整能力,适合需要读写文件、执行命令的任务。
在实际使用中,主 Agent 会根据任务性质自动选择合适的类型。探索性质的任务用 Explore,需要动手的任务用 general-purpose,这种分工让每个 agent 的"权限"刚好够用,不多也不少。
主 Agent 如何给子 Agent 下达任务
这是整个机制中最关键的一环。
因为子 Agent 的上下文是全新的——它什么都不知道,不知道你在做什么项目,不知道代码结构,不知道你之前跟主 Agent 聊了什么。所以主 Agent 必须在 prompt 中提供所有必要信息,就像给一个刚加入项目的同事做 briefing。
一个好的 Agent prompt 应该包含:
- 背景:项目是什么,当前状态如何
- 具体任务:明确要做什么
- 关键信息:文件路径、代码结构、命名规范等细节
- 约束条件:不要做什么,注意事项
- 预期产出:期望什么样的结果
用一个实际的例子:在我的图形引擎项目中,我让 Claude Code 把 Shadow Mapping 的实现写成一篇技术博文,发布到我的 Hugo 博客。主 Agent 给博客管理子 Agent 的 prompt 大致结构是这样的:
你是一个博客管理 agent。你负责管理位于 /path/to/blog 的 Hugo 博客。
## 博客项目关键信息
- 框架: Hugo,主题 Ananke
- 文章目录: content/zh/post/
- Frontmatter 格式: TOML(用 +++ 包围)
- 部署方式: GitLab Pages,push 到 master 自动部署
- ...
## 文章内容要求
基于以下技术实现写一篇教学博文...
(附上所有技术细节、代码片段、解释要点)
## 完成后操作
1. 写完文章后 git add、git commit
2. 不要 push(等用户确认后再 push)
注意这个 prompt 的详细程度——它把博客框架、目录结构、frontmatter 格式、文章内容、代码片段、注意事项全部交代清楚了。因为子 Agent 不知道之前的任何对话,少给一条关键信息就可能导致结果偏差。比如不告诉它 frontmatter 用 TOML 格式,它可能默认用 YAML;不告诉它文章目录在 content/zh/post/,它可能放到错误的位置。
子 Agent 的执行过程
子 Agent 收到任务后,会像一个独立的开发者一样自主工作。以博客发布 agent 为例,它内部的执行链大致是这样的:
收到 prompt
→ Read hugo.toml(确认项目配置)
→ Read 几篇现有文章(学习格式和风格)
→ Write 新文章到 content/zh/post/xxx.md
→ Bash: git add content/zh/post/xxx.md
→ Bash: git commit -m "feat: add blog post..."
→ 返回执行摘要给主 Agent
主 Agent 全程看不到这些中间步骤,只能等最终结果。
这意味着几件事:
- 如果子 Agent 做了什么意料之外的事(比如创建了临时文件、修改了配置),主 Agent 并不知情,需要事后检查。
- 子 Agent 可能对环境做出主 Agent 不了解的改动,所以主 Agent 通常会在收到结果后做一轮验证——检查文件是否正确生成、git 状态是否干净等。
- 如果子 Agent 执行失败了,主 Agent 只能从返回的摘要中推断原因,然后决定是重试还是换个方式处理。
通信模式
子 Agent 和主 Agent 之间有几种不同的通信模式,适用于不同场景。
单次通信(Fire and Forget)
最常见的模式。主 Agent 启动子 Agent,给一个完整的任务描述,然后等待结果。子 Agent 完成后返回摘要,交互结束。每次启动都是全新上下文,之前干过什么全部清零。
大多数任务用这种模式就够了——写一篇文章、探索一段代码、执行一组命令。
继续对话(SendMessage)
每个子 Agent 返回时会带一个唯一 ID(类似 agentId: a2d5c7e40fddc8d63)。主 Agent 可以通过 SendMessage 向同一个 agent 追加指令,此时 agent 保留之前的完整上下文。
这个模式适合需要多轮交互或迭代修正的场景。比如子 Agent 第一次写的文章格式不太对,主 Agent 可以通过 SendMessage 说"把 frontmatter 的 date 字段改成 TOML 格式",子 Agent 就能在已有上下文的基础上继续修改,不需要重新理解整个任务。
并行执行
主 Agent 可以在一条消息中同时启动多个子 Agent,它们并行工作互不干扰。
主 Agent 的一条消息中:
Agent("探索渲染管线", type=Explore) ─┐
├─ 并行执行
Agent("探索场景系统", type=Explore) ─┘
这在探索大型代码库时特别有用。比如同时派出两个 Explore agent:一个分析渲染管线,一个分析场景管理系统。两边的结果汇总后,主 Agent 就能对整个项目有一个全面的理解,效率比串行探索高很多。
后台执行
子 Agent 可以在后台运行(run_in_background: true),主 Agent 不需要等待结果就能继续和用户对话或处理其他任务。任务完成时会收到通知。
这个模式适合耗时较长但不阻塞主流程的任务,比如跑一组测试、做一次大范围的代码搜索等。
交互流程全景图
把上面的所有概念串起来,一个完整的三方交互流程是这样的:
用户 (User)
│
│ "把 Shadow Mapping 的实现写成博客发布"
▼
主 Agent (Main Claude)
│
│ ① 理解需求
│ ② 整理所有必要信息(项目结构、技术内容、格式要求)
│ ③ 编写详细的 prompt
│ ④ 调用 Agent 工具启动子 Agent
▼
子 Agent (Sub Claude) ← 独立实例,全新上下文
│ 收到 prompt,开始自主工作
│ Read → Write → Bash(git add/commit)
│ 完成后返回摘要
▼
主 Agent (Main Claude)
│
│ ⑤ 收到子 Agent 的返回结果
│ ⑥ 验证结果(检查文件是否正确、清理临时文件)
│ ⑦ 向用户汇报
▼
用户 (User)
│
│ "确认没问题,发布吧"
▼
主 Agent → 再次启动子 Agent 或直接执行 git push
注意其中的信息流方向:
- 用户 ↔ 主 Agent:双向实时对话
- 主 Agent → 子 Agent:单向任务下发(通过 prompt)
- 子 Agent → 主 Agent:单向结果返回(通过摘要)
- 用户 ↔ 子 Agent:没有直接通信
用户全程只和主 Agent 对话,子 Agent 的存在对用户来说是半透明的——你能看到"正在使用 Agent 工具"的状态提示,但看不到子 Agent 内部在做什么。
关键特性总结
| 特性 | 说明 |
|---|---|
| 上下文隔离 | 子 Agent 看不到主 Agent 和用户的对话,必须在 prompt 中给足信息 |
| 单向通信 | 主 Agent 给任务 → 子 Agent 返回结果,中间无实时交互 |
| 结果不透明 | 用户看不到子 Agent 的返回内容,由主 Agent 转述和过滤 |
| 工具共享 | 子 Agent 能使用和主 Agent 相同的工具(受 Agent 类型限制) |
| 可并行 | 多个子 Agent 可同时启动并行工作 |
| 可继续 | 通过 agentId + SendMessage 可继续之前的 agent 上下文 |
| 可隔离 | 可在独立的 git worktree 中运行,避免影响主工作区 |
实际使用中的观察和思考
用了一段时间后,我总结了一些关于这套机制的经验和感受。
Prompt 质量决定一切
子 Agent 的产出质量几乎完全取决于主 Agent 给的 prompt 质量。信息不足会导致子 Agent 反复试探或产出偏差;信息冗余虽然浪费 token 但结果更可靠。
我观察到主 Agent 在给子 Agent 写 prompt 时,会把当前上下文中所有相关的信息都整理进去——项目路径、文件结构、编码规范、甚至之前几轮对话中讨论过的决策。这个"信息打包"的过程其实就是主 Agent 最核心的价值之一。
主 Agent 的角色是"项目经理"
主 Agent 负责理解用户需求、拆解任务、分配工作、检查结果、汇报进展。子 Agent 是执行者。
这种分工让复杂任务变得可管理。你不需要自己把一个大任务拆成小步骤逐一指导,主 Agent 会帮你完成这个拆解过程。但你需要意识到这层中间人的存在——有时候主 Agent 的理解和你的意图之间可能存在偏差,这个偏差会被放大到子 Agent 那里。
事后验证很重要
子 Agent 可能会产生意料之外的副作用。我遇到过子 Agent 在写博客时顺手创建了一个临时的测试 markdown 文件,也遇到过子 Agent 修改了 .gitignore 来排除它自己生成的临时文件。
主 Agent 通常会在收到结果后做一轮检查——跑 git status 看看有没有多余的改动,检查文件内容是否符合预期。但如果主 Agent 自己也没想到要检查某些东西,那些副作用就可能被忽略。
选择合适的 Agent 类型
用 Explore 做探索、Plan 做设计、general-purpose 做执行,可以利用类型约束来降低风险。
比如你只是想了解代码库的结构,用 Explore 类型就够了,它无法修改代码,不会意外搞坏什么东西。这种"最小权限"原则在多 Agent 系统中特别重要——每个 agent 只拥有完成任务所需的最少权限。
结语
这套多 Agent 机制本质上是一个"分布式协作"系统:
- 通过上下文隔离保证安全性——子 Agent 无法访问它不需要的信息
- 通过prompt 传递保证信息完整性——所有必要的上下文都显式传递,没有隐式依赖
- 通过并行执行提升效率——多个独立任务可以同时进行
- 通过类型约束控制风险——不同 agent 有不同的权限边界
理解这个机制有助于更好地利用 Claude Code。当你知道主 Agent 在背后是怎么调度子 Agent 的,你就能更有效地描述你的需求——给足上下文、明确约束、分清哪些事情可以并行做。从某种意义上说,你也在参与这个"分布式协作"系统,你是这个系统中最重要的角色:需求的发起者和最终结果的验收者。