子代理协作模式
理解和使用 Claude Code 的子代理 — 并行探索、后台任务、隔离执行
子代理协作模式¶
想象一下:你让 Claude 帮你重构一个大模块,但在重构之前,你需要它先搞清楚三件事 — 现有的 API 接口有哪些、数据库 schema 是什么样的、测试覆盖率如何。在普通模式下,Claude 只能串行地一件一件查。但如果它能同时派出三个"分身"去分别调查呢?
这就是子代理的魅力。
什么是子代理¶
Agent 工具的概念¶
子代理(Subagent)是 Claude Code 中一种特殊的工具,它允许主会话创建独立的 Claude 实例来执行特定任务。你可以把它理解为"Claude 雇了一个助手"。
主会话的 Claude 是项目经理,负责统筹全局。当遇到需要深入调查的子任务时,它可以启动一个子代理去专门处理,自己则继续处理其他事情。
子代理 vs 主会话的区别¶
| 特性 | 主会话 | 子代理 |
|---|---|---|
| 上下文 | 包含完整对话历史 | 独立的上下文窗口,只包含任务描述 |
| 生命周期 | 持续到你关闭 Claude Code | 任务完成后自动结束 |
| 工具访问 | 所有已授权工具 | 可被限制为特定工具子集 |
| 执行方式 | 与你交互式对话 | 自主执行,完成后返回结果 |
| 上下文消耗 | 所有操作消耗同一上下文 | 不消耗主会话的上下文 |
| 结果 | 直接展示 | 以摘要形式返回给主会话 |
最关键的区别是独立上下文窗口。子代理有自己的上下文空间,它的探索过程不会撑大主会话的上下文。只有最终结果会被传回主会话 — 这就像你派人出差调研,他回来后只需要给你一份报告,而不是把整个调研过程复述一遍。
独立上下文窗口的优势¶
为什么独立上下文这么重要?举个实际例子:
假设你需要 Claude 分析一个有 200 个文件的项目。如果在主会话中逐个读取文件,每个文件平均 200 行,光文件内容就占了 40000 行上下文。加上 Claude 的分析过程,很快就会把上下文撑满。
用子代理就不一样了。子代理在自己的上下文里读取和分析这些文件,最后只传回一份几百行的分析报告。主会话的上下文几乎没有增加,你还有充足的空间继续后续工作。
内置子代理类型¶
Claude Code 的子代理实际上并不是固定的"类型",而是由主会话根据任务性质灵活创建的。不过在实践中,子代理通常承担以下几类角色:
Explore(代码搜索和探索)¶
这是最常见的子代理用途。当 Claude 需要理解项目的某个方面时,它会启动一个 Explore 子代理:
能力:
- 读取文件(Read)
- 搜索代码(Grep、Glob)
- 查看目录结构
- 分析代码依赖关系
限制:
- 通常只赋予只读工具
- 不能修改文件
- 不能执行命令
典型场景:
分析 src/services/ 目录下所有服务的公共接口
找出所有引用了 UserService 的文件
理解认证中间件的工作流程
Plan(架构设计和规划)¶
用于制定计划或设计方案的子代理:
能力:
- 所有 Explore 能力
- 网络搜索(查文档、最佳实践)
- 生成详细的方案文档
典型场景:
设计一个缓存层的架构方案
评估从 REST 迁移到 GraphQL 的可行性
制定数据库分表策略
通用任务(General-Purpose)¶
处理具体执行任务的子代理,拥有完整的工具访问权限:
能力:
- 读写文件
- 执行命令
- 运行测试
- 安装依赖
典型场景:
在后台运行完整的测试套件
生成 API 文档
执行代码格式化
使用子代理的场景¶
场景 1:代码搜索和理解¶
当你需要 Claude 深入理解一个陌生的代码库时,子代理可以高效地完成探索:
我刚接手这个项目,请帮我全面了解它的架构:
1. 用子代理分析后端的目录结构和核心模块
2. 用子代理分析前端的组件树和状态管理
3. 用子代理分析数据库 schema 和实体关系
然后综合三方面的信息,给我一份项目架构概览。
Claude 可能会启动三个子代理并行执行这些任务,然后汇总它们的报告。
场景 2:并行调研多个方案¶
需要比较多种技术方案时,子代理的并行能力非常有用:
我需要为项目选择一个消息队列。请分别调研以下方案:
1. Redis Streams — 查看我们现有的 Redis 配置是否支持
2. RabbitMQ — 评估引入新依赖的成本
3. 直接用 PostgreSQL 的 LISTEN/NOTIFY
对每个方案,分析优缺点和与我们项目的兼容性。
场景 3:后台运行长任务¶
某些任务耗时较长(如运行测试、生成文档),可以放到子代理中后台执行:
请在后台运行项目的完整测试套件,我继续做其他事情。
测试跑完后告诉我结果。
Claude 会启动一个后台子代理来执行测试,你可以继续和主会话对话,不需要等待。
场景 4:隔离高风险操作¶
当你需要执行一些可能有风险的操作时,可以用子代理来隔离:
请用子代理尝试以下操作:
1. 切换到一个临时分支
2. 尝试升级 React 到 19.x
3. 运行构建,看有多少兼容性错误
4. 把错误列表发给我
不要在主分支上操作。
子代理实战教程¶
示例 1:用子代理理解陌生代码库¶
假设你第一天接手一个中型 Python 项目(约 50 个源文件),需要快速了解它的结构。
你的提示词:
这是我第一天接手这个项目,请帮我快速建立对项目的理解。
用子代理来并行分析以下方面:
1. 项目结构和入口点 — 扫描目录结构,找到 main 入口、路由定义、配置文件
2. 数据模型 — 分析所有 model 文件,画出实体关系
3. 业务逻辑 — 分析 services 目录,理解核心业务流程
4. 外部依赖 — 分析 requirements.txt 和实际的 import,找出关键依赖
最后请综合所有信息,给我一份不超过 500 字的项目概览。
Claude 的执行过程:
Claude 会创建多个子代理分别执行任务。每个子代理独立探索,然后返回结果。整个过程你会看到类似这样的输出:
正在启动 4 个子代理进行并行分析...
[子代理 1] 分析项目结构...
- 扫描了 52 个 Python 文件
- 找到入口点:main.py → FastAPI app
- 路由定义在 routers/ 目录(8 个路由模块)
- 配置:config.py + .env
[子代理 2] 分析数据模型...
- 找到 12 个 SQLAlchemy 模型
- 核心实体:User, Organization, Project, Task, Comment
- 关键关系:User ← many-to-many → Organization, Project → has-many → Task
[子代理 3] 分析业务逻辑...
- 9 个 service 文件
- 核心流程:用户管理、项目管理、任务分配、通知系统
- 异步任务处理使用 Celery
[子代理 4] 分析外部依赖...
- 32 个直接依赖
- 关键依赖:FastAPI, SQLAlchemy, Celery, Redis, Alembic
- 发现 2 个未使用的依赖(requests, beautifulsoup4)
最后 Claude 综合四个子代理的结果,给你一份结构清晰的项目概览。
示例 2:并行启动多个子代理对比方案¶
你正在考虑如何实现实时通知功能,想比较几种方案:
我需要给项目添加实时通知功能。请帮我并行评估以下三种方案:
方案 A:WebSocket(使用 FastAPI 内置的 WebSocket 支持)
方案 B:Server-Sent Events(SSE)
方案 C:轮询(Polling)
对每种方案,请分析:
1. 与我们现有架构的兼容性(检查现有代码)
2. 实现复杂度(大约需要改多少文件)
3. 性能和可扩展性
4. 客户端兼容性
然后给我一个对比表格和你的推荐。
Claude 的对比结果可能是:
三个子代理已完成分析。综合对比如下:
| 评估维度 | WebSocket | SSE | 轮询 |
|----------|-----------|-----|------|
| 架构兼容性 | 需要新增 WebSocket 路由 | 可复用现有 HTTP 路由 | 完全兼容 |
| 实现复杂度 | 高(约 8 个文件) | 中(约 4 个文件) | 低(约 2 个文件) |
| 实时性 | 最好(全双工) | 好(服务端推送) | 一般(取决于轮询间隔) |
| 可扩展性 | 需要 WebSocket 负载均衡 | 可用 CDN | 最简单 |
| Celery 集成 | 需要额外的消息桥接 | 可直接消费 Celery 事件 | 轮询数据库即可 |
**推荐**:考虑到你们已经使用 Celery + Redis,SSE 是最佳选择。
它可以直接订阅 Redis 频道获取 Celery 事件,实现复杂度适中,
而且不需要额外的基础设施。
示例 3:后台子代理运行测试¶
你正在修改代码,同时想知道测试结果:
请在后台运行 pytest,跑完整个测试套件。我继续改代码,跑完了告诉我。
Claude 会启动一个后台子代理执行测试。你可以继续和 Claude 对话、修改代码。当测试完成后,你会看到结果通知:
后台测试已完成。结果:
- 总计:247 个测试
- 通过:241 个
- 失败:4 个
- 跳过:2 个
失败的测试:
1. test_order_service.py::test_calculate_total_with_discount
AssertionError: 99.99 != 100.0
2. test_user_service.py::test_create_user_duplicate_email
IntegrityError: 测试数据库未正确清理
3. ...
需要我帮你分析这些失败的测试吗?
子代理配置¶
通过 CLAUDE.md 引导子代理行为¶
虽然你不能直接"配置"子代理的参数,但可以通过 CLAUDE.md 来引导 Claude 在何时以及如何使用子代理:
## 子代理使用规范
### 何时使用子代理
- 分析超过 10 个文件的任务,应使用子代理
- 需要对比多个方案时,为每个方案启动独立子代理
- 运行测试应在后台子代理中执行
### 子代理任务描述模板
启动子代理时,任务描述应包含:
1. 明确的目标(做什么)
2. 范围限制(不做什么)
3. 输出格式(返回什么样的结果)
### 子代理结果处理
子代理的结果必须包含:
- 分析摘要(不超过 200 字)
- 关键发现列表
- 相关文件路径
- 潜在风险或问题
理解子代理可用的工具¶
子代理能使用哪些工具,取决于主会话对它的授权。在实践中:
- 只读任务:通常只赋予 Read、Grep、Glob 等搜索工具
- 执行任务:赋予 Bash、Write、Edit 等写入工具
- 网络任务:赋予 WebSearch、WebFetch 等网络工具
你可以通过自然语言来暗示工具范围:
请用子代理分析(只读)src/models/ 目录下所有模型的关系。
加上"只读"这个提示,Claude 就倾向于创建一个只有搜索和阅读能力的子代理。
后台执行¶
子代理可以在后台运行,不阻塞你和主会话的交互。当你说"在后台..."或"异步..."时,Claude 会使用 run_in_background 参数:
请在后台帮我做两件事:
1. 运行完整的 lint 检查
2. 检查所有依赖是否有已知的安全漏洞
我继续改代码,完成后告诉我结果。
后台子代理完成后,系统会通知 Claude,Claude 再把结果转告你。
最佳实践¶
1. 给子代理清晰的任务描述¶
子代理的上下文是全新的 — 它不知道你之前和主会话聊了什么。所以任务描述必须自包含:
不好的做法:
用子代理检查一下刚才说的那个问题。
(子代理不知道"刚才说的那个问题"是什么)
好的做法:
用子代理检查 src/services/payment_service.py 中的
process_refund() 方法是否正确处理了并发退款请求。
需要关注数据库事务隔离级别和乐观锁的使用。
2. 善用并行子代理提升效率¶
当多个任务之间没有依赖关系时,让它们并行执行:
请并行执行以下任务:
1. [子代理 A] 分析前端代码中所有的 API 调用点
2. [子代理 B] 分析后端的 API 端点和参数定义
3. [子代理 C] 检查 API 文档是否与实际接口一致
三个任务完成后,汇总出 API 不一致的地方。
3. 不要过度使用子代理¶
子代理不是万能的。以下场景直接在主会话中处理更高效:
- 简单的文件查看:读一两个文件,直接
@引用就行 - 简单的搜索:搜索一个关键词,主会话做更快
- 需要持续交互的任务:子代理是"一次性"的,不适合需要多轮对话的任务
- 依赖前一步结果的串行任务:用子代理反而增加复杂度
经验法则:如果任务可以用一两句话描述清楚,而且不需要读取大量文件,就直接在主会话做。
4. 理解子代理的结果传递机制¶
子代理完成任务后,它的结果会以摘要形式传回主会话。这意味着:
- 子代理读取的文件原文不会完整传回(太大了)
- 只有子代理的分析结论和关键信息会传回
- 如果你需要看子代理发现的某个具体文件,要在主会话中自己再读一次
子代理告诉我 payment_service.py 第 127 行有问题,
请帮我看看这个文件的 120-140 行。
5. 用子代理做"试探性"操作¶
不确定某个方案是否可行?用子代理来试探,而不是在主分支上冒险:
请用子代理做个实验:
1. 创建一个临时目录 /tmp/experiment
2. 把 src/models/user.py 复制进去
3. 尝试用 dataclasses 替代 SQLAlchemy 的声明式模型
4. 看看会有什么问题
不要动项目的任何文件。
进阶:子代理与其他功能配合¶
子代理 + Plan 模式¶
Plan 模式下也可以使用子代理。这是一个强大的组合 — 用子代理在计划阶段做深入调研:
(Plan 模式下)
请用子代理帮我调研以下问题,然后基于调研结果制定迁移计划:
1. 当前所有 REST API 的端点列表和调用频率
2. 哪些端点已经有 GraphQL 的等价实现
3. 客户端代码中对 REST API 的依赖程度
子代理 + MCP 工具¶
如果你配置了 MCP 服务器(如数据库查询工具),子代理也可以使用它们:
请用子代理连接数据库,分析以下内容:
1. 各表的数据量
2. 慢查询 Top 10
3. 缺失的索引
用数据库 MCP 工具来执行查询。
子代理 + Hooks¶
你可以通过 Hooks 在子代理执行特定操作时触发自定义逻辑。例如,当子代理完成测试后自动发送通知:
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "curl -X POST https://hooks.slack.com/... -d '{\"text\": \"$MESSAGE\"}'"
}
]
}
]
}
}
常见问题¶
Q:子代理能看到我和主会话的对话历史吗?
A:不能。子代理的上下文是全新的,只包含 Claude 给它的任务描述。这也是为什么任务描述必须自包含。不过,子代理可以读取 CLAUDE.md,所以项目级的规范和约定对子代理也有效。
Q:子代理可以启动"子子代理"吗?
A:可以,但不建议嵌套太深。通常一层子代理就够了。
Q:多个子代理之间可以通信吗?
A:不能直接通信。如果你需要子代理 B 依赖子代理 A 的结果,只能等 A 完成后,由主会话把结果传给 B。
Q:子代理会消耗额外的 API 配额吗?
A:是的。子代理使用独立的上下文窗口,每个子代理的输入和输出都会消耗 token。不过由于子代理的上下文通常较小(只包含特定任务),总体消耗往往比在主会话中做同样的事情更少。
Q:如何知道子代理正在做什么?
A:Claude 会在主会话中显示子代理的执行状态。你可以看到它启动了哪些子代理、每个子代理正在做什么、是否已完成。