ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Claude Code SubAgent与多会话并行:从单兵到团队协同的AI开发流水线

Claude Code SubAgent与多会话并行:从单兵到团队协同的AI开发流水线

1. 从单兵作战到团队协同的思维转变

一个人写代码,最怕的不是难题,而是任务多到做不完。我刚开始用 Claude Code 那会儿,习惯把所有需求一股脑塞进一个会话里,结果上下文越滚越长,模型开始“忘事”,前面说过的约束后面就不认了。后来我才意识到,这跟带团队是一个道理——一个人干不完,就得分工。

Claude Code 的分工机制,核心就是SubAgent(子代理)和多会话并行这两套东西。SubAgent 解决的是“一个任务内部怎么拆”,多会话解决的是“多个任务之间怎么并行”。两者配合起来,一个人也能撑起一个小型开发流水线。

这篇文章适合两类人看:一是已经用过 Claude Code 基础功能、但还没碰过 SubAgent 的开发者;二是任务量大、经常被上下文长度卡住的中高级用户。我会把分工的底层逻辑、配置方法、实操流程和踩坑经验全部讲清楚,让你看完就能直接上手。

先说结论:SubAgent 的本质是用独立的上下文窗口去执行特定职责,它不共享主会话的记忆,只接收你显式传给它的信息。这个设计看起来麻烦,实际上正是它高效的原因——每个子代理都专注在自己的领域里,不会被无关信息干扰。

2. SubAgent 核心机制与设计逻辑拆解

2.1 为什么需要独立上下文

大语言模型有个硬约束:上下文窗口是有限的。当你在一个会话里同时处理代码审查、测试编写、文档生成三件事时,这三件事的信息会互相挤占空间。更糟糕的是,它们会互相干扰——模型在写测试的时候,脑子里还装着刚才审查代码时的那些细节,输出质量就会下降。

SubAgent 的做法是给每个职责开一个“独立办公室”。主代理是项目经理,它把任务拆好,分给对应的子代理,子代理在自己的办公室里干活,干完把结果交回来。子代理看不到项目经理和其他子代理的对话,只看到自己那份任务说明。

这个设计的好处很直接:

  • 上下文干净:每个子代理的窗口里只有自己需要的信息,不会被污染
  • 职责明确:一个子代理只干一类事,输出更稳定
  • 可并行:多个子代理可以同时跑,互不阻塞
  • 可复用:配好的子代理可以在不同项目里反复调用

代价也有:子代理之间不能直接通信,所有协调都得通过主代理。所以任务拆分的粒度很关键,拆得太细会导致主代理来回传话的开销变大,拆得太粗又失去了分工的意义。

2.2 SubAgent 与普通会话的本质区别

很多人第一次接触 SubAgent 会疑惑:这不就是开个新会话吗?区别在于调用方式和生命周期管理。

普通新会话是你手动开的,你得自己复制粘贴上下文,自己判断什么时候该开新的。SubAgent 是主代理按需自动调用的,它有一套声明式的配置——你提前定义好“有这么几个角色,各自负责什么,能用什么工具”,主代理在遇到对应任务时会自动把活派下去。

另一个关键区别是工具权限隔离。你可以给代码审查子代理只开放读取权限,不给它写入能力,这样它就不可能误改代码。给测试子代理开放执行权限,让它能跑测试命令。这种权限控制在主会话里是很难做到的,因为主会话通常需要全量权限。

2.3 配置文件的组织方式

SubAgent 的定义通常放在项目的配置目录下,每个子代理一个文件。文件格式是带 frontmatter 的 Markdown,frontmatter 里声明元信息,正文里写系统提示词。

一个典型的子代理定义长这样:

--- name: code-reviewer description: 专门负责代码审查,检查潜在 bug 和风格问题 tools: - Read - Grep - Glob model: inherit --- 你是一名资深代码审查员。你的职责是检查代码中的潜在问题, 包括但不限于:空指针风险、边界条件遗漏、命名不规范、 重复代码、性能隐患。 审查时请按以下格式输出: 1. 问题位置(文件:行号) 2. 问题类型 3. 严重程度(高/中/低) 4. 修复建议 不要直接修改代码,只输出审查报告。

这里有几个细节值得说:

description 字段很关键。主代理是根据这个描述来判断“什么时候该调用这个子代理”的。描述写得越准确,派活就越精准。我见过有人把描述写成“一个有用的助手”,结果主代理几乎从不调用它,因为看不出它到底擅长什么。

tools 字段决定能力边界。不写这个字段,子代理会继承主会话的全部工具权限。写了就只开放列出的那些。我的习惯是最小权限原则——审查类只给读,执行类给读加执行,写入类才给全量。

model 字段可以指定模型。写inherit就跟随主会话,也可以指定具体模型。简单任务用轻量模型省钱,复杂任务用强模型保质量,这个后面会展开讲。

3. 多会话并行的实操配置与任务拆分

3.1 任务拆分的三个原则

分工的第一步不是配置,是想清楚怎么拆。我总结了三条原则,踩过不少坑才摸出来。

原则一:按职责拆,不按文件拆。新手容易犯的错是“这个文件一个代理,那个文件一个代理”。这样拆的问题是,同一个职责被切碎了,每个代理都要重新理解一遍项目背景。正确的做法是按职责拆——代码审查是一个职责,测试编写是一个职责,文档生成是一个职责。一个职责可能涉及多个文件,没关系,让这个代理自己去读。

原则二:每个子任务要能独立完成。如果一个子任务必须等另一个子任务的结果才能开始,那它们就不适合并行,应该串行或者合并。比如“先重构再测试”,测试依赖重构后的代码,这两个就不能并行。但“审查模块 A”和“审查模块 B”就可以并行,因为它们互不依赖。

原则三:粒度控制在 3 到 7 个。太少了没体现出分工价值,太多了主代理协调开销大,而且容易乱。我一般把一次大任务拆成 4 到 6 个子任务,这个区间比较舒服。

3.2 并行执行的配置方法

Claude Code 支持在一条指令里触发多个子代理并行工作。你不需要手动一个个调用,只要在提示词里描述清楚任务,主代理会自己判断该派给谁。

比如这样一个场景:你刚写完一个新模块,需要同时做代码审查、补测试、更新文档。你可以这样下指令:

我刚完成了 user-service 模块的开发,现在需要做三件事: 1. 用 code-reviewer 审查这个模块的代码质量 2. 用 test-writer 为这个模块补充单元测试 3. 用 doc-writer 更新 API 文档 这三件事互不依赖,请并行处理。

主代理会识别出三个子代理,分别派活,然后等它们都完成后汇总结果。实测下来,三个子代理并行跑,总耗时大约等于最慢那个子代理的耗时,而不是三个相加。

这里有个实操心得:并行任务之间如果有共享资源,要提前声明。比如两个子代理都要读同一个配置文件,那没问题,读操作不冲突。但如果都要写同一个文件,就会出问题。我一般会在指令里加一句“注意不要修改同一文件”,让主代理去协调。

3.3 串行与并行的混合编排

实际项目里,纯并行或纯串行都少见,更多是混合的。比如一个典型的功能开发流程:

  1. 需求分析(串行,必须先做)
  2. 代码实现(串行,依赖需求分析)
  3. 代码审查 + 测试编写 + 文档更新(并行,都依赖代码实现)
  4. 根据审查结果修复(串行,依赖审查)

这种混合编排,你可以分阶段下指令,也可以一次性描述清楚让主代理自己排。我的建议是分阶段下指令,因为阶段之间的衔接点往往需要你人工确认一下,全自动跑容易在错误的方向上越走越远。

分阶段的好处是每完成一个阶段,你可以检查一下输出质量,有问题及时调整。全自动虽然省事,但一旦某个子代理理解偏了,后面全跟着偏,返工成本更高。

4. 子代理的提示词设计与工具权限控制

4.1 提示词要写成“岗位说明书”

子代理的提示词不是随便写几句就行,它相当于这个岗位的说明书。写得好,子代理干活靠谱;写得糊,子代理就自由发挥,结果不可控。

我写子代理提示词有个固定结构:

  • 角色定位:你是谁,你的专业背景是什么
  • 职责范围:你负责什么,不负责什么
  • 工作方法:你按什么步骤干活
  • 输出格式:你交付的成果长什么样
  • 边界约束:什么情况下你应该停下来问,而不是自己决定

拿测试编写子代理举例:

--- name: test-writer description: 为指定模块编写单元测试,覆盖正常路径和边界条件 tools: - Read - Write - Grep - Glob - Bash --- 你是一名测试工程师,专注于编写高质量的单元测试。 职责范围: - 为指定模块编写单元测试 - 覆盖正常路径、边界条件、异常路径 - 不负责修改被测代码本身 工作方法: 1. 先读取被测模块的源码,理解其接口和逻辑 2. 查看项目中已有的测试文件,学习测试风格和框架用法 3. 编写测试用例,确保每个公开方法都有覆盖 4. 运行测试,确认全部通过 输出格式: - 测试文件放在与被测模块相同的目录下,命名为 xxx.test.js - 每个测试用例要有清晰的描述 - 最后汇报:新增测试数量、覆盖率估算、未覆盖的分支及原因 边界约束: - 如果被测模块依赖外部服务且没有 mock 方案,停下来询问 - 如果发现被测代码有明显 bug,不要自行修复,在报告中指出

这个提示词里,“不负责修改被测代码”和“不要自行修复”这两条特别重要。我踩过坑——有一次测试子代理发现代码有 bug,顺手就给改了,结果改错了,还很难追溯。从那以后我所有子代理的提示词里都会明确写“什么不要做”。

4.2 工具权限的最小化配置

工具权限控制是 SubAgent 最实用的特性之一。我整理了一张常用子代理的权限配置表:

子代理类型ReadWriteEditBashGrep/Glob说明
代码审查是否否否是只读,防止误改
测试编写是是否是是能写测试能跑测试,不改源码
文档生成是是否否是只写文档
重构执行是是是是是需要全量权限
依赖分析是否否是是只读加执行分析命令

这张表的核心逻辑是:能不给写权限就不给,能不给执行权限就不给。审查类任务永远只给读权限,这样即使子代理判断失误,也不会造成破坏。

有个细节要注意:Bash 权限其实很危险,因为通过 Bash 可以执行任意命令,包括写文件。所以给 Bash 权限的时候要谨慎,最好配合提示词里的约束一起用。比如测试子代理给了 Bash 权限,但提示词里明确写“只允许运行测试命令,不允许执行其他 shell 操作”。

4.3 模型选择的成本考量

不是所有子代理都需要用最强的模型。我的经验是:

  • 审查类、分析类:用强模型,因为需要深度理解
  • 格式转换、简单生成:用轻量模型,省钱又快
  • 执行类、机械操作:用轻量模型足够

在配置文件里通过 model 字段指定。如果项目里子代理调用频繁,这个成本差异会很明显。我有个项目一天要跑几十次子代理,把简单任务的模型换成轻量级之后,成本降了大概六成,质量没感觉到明显下降。

5. 实操全流程:从零搭建一个分工协作的开发流水线

5.1 环境准备与目录结构

先确认你的 Claude Code 版本支持 SubAgent。然后在项目根目录下创建配置目录。不同版本的目录约定可能不同,常见的是.claude/agents/或者项目配置目录下的agents/子目录。

目录结构大概是这样:

项目根目录/ ├── .claude/ │ └── agents/ │ ├── code-reviewer.md │ ├── test-writer.md │ ├── doc-writer.md │ └── refactor-executor.md ├── src/ └── ...

每个.md文件就是一个子代理定义。文件名建议和 name 字段保持一致,方便管理。

5.2 编写第一个子代理

我们从最简单的代码审查子代理开始。创建code-reviewer.md,内容按前面说的结构写。写完之后,怎么验证它能不能被正确调用?

我的做法是先做一次小范围测试。找一个已知有问题的文件,下指令让主代理审查它,看主代理会不会自动调用 code-reviewer。如果没调用,说明 description 写得不够明确,主代理没识别出这个任务该派给它。

测试指令可以这样写:

请审查 src/utils/format.js 这个文件,检查有没有潜在问题。

如果配置正确,主代理会调用 code-reviewer 子代理,然后返回审查报告。如果主代理自己动手审查了,说明它没找到合适的子代理,这时候要回去检查 description 字段。

5.3 编排一次完整的并行任务

假设你刚完成一个功能模块,现在要跑完整的收尾流程。指令可以这样下:

我刚完成了 order-service 模块的开发,代码在 src/services/order/ 目录下。 现在需要并行执行以下任务: 1. 代码审查:检查 src/services/order/ 下所有文件的代码质量 2. 测试编写:为这些文件编写单元测试 3. 文档更新:更新 docs/api/order.md 文档 三个任务互不依赖,请同时启动。

主代理接到指令后,会做几件事:识别出三个子任务,匹配到三个子代理,分别派发,等待完成,汇总结果。

这里有个实操细节:并行任务的结果汇总顺序可能和你预期的不同。因为三个子代理完成时间不一样,先完成的先返回。如果你对汇总顺序有要求,可以在指令里说明“按审查、测试、文档的顺序汇总”。

5.4 结果验收与迭代

子代理跑完之后,不要直接信任输出,要验收。我的验收清单:

  • 审查报告里的问题是否真实存在(抽查几条)
  • 测试是否真的能跑通(自己跑一遍)
  • 文档更新是否准确(对照代码检查)

验收发现问题,不要直接改,而是把问题反馈给对应的子代理让它重做。这样能保持职责清晰,也方便追溯。比如测试没覆盖某个分支,就下指令“test-writer 补充对 xxx 分支的测试”,而不是自己动手加。

迭代几次之后,你会发现某些子代理的提示词需要调整。比如审查子代理总是漏掉某类问题,那就在提示词里把这类问题明确列进去。子代理的提示词是活的,要跟着项目一起演进。

6. 常见问题排查与避坑经验实录

6.1 子代理不被调用怎么办

这是最常见的问题。主代理该派活的时候自己干了,或者派给了错误的子代理。排查思路:

第一步,检查 description。主代理是根据 description 做匹配的。如果描述太笼统,比如“处理代码相关任务”,主代理就不知道什么时候该用它。改成“审查代码质量,检查 bug、风格、性能问题”这种具体的描述。

第二步,检查任务描述。你下的指令如果太模糊,主代理也难判断。比如“看看这个模块”,主代理可能觉得这是闲聊,自己就回答了。改成“审查这个模块的代码质量”,意图就明确了。

第三步,显式指定。如果自动匹配总是不准,可以在指令里直接点名:“用 code-reviewer 审查这个模块”。这样主代理就不会自作主张了。

6.2 并行任务互相干扰怎么破

两个子代理同时写同一个文件,后写的覆盖先写的,这是并行最典型的坑。避免方法:

  • 任务拆分时确保写操作不重叠。审查和测试可以并行,因为审查只读、测试只写测试文件,不冲突。但两个都要改源码的任务就不能并行。
  • 在指令里声明资源约束。比如“test-writer 只允许创建新的测试文件,不允许修改 src 下的任何文件”。
  • 用文件锁的思路。如果确实需要多个子代理写同一区域,改成串行执行。

我遇到过一次比较隐蔽的干扰:两个子代理都要读同一个大文件,结果其中一个读的时候另一个正在被主代理修改,读到了中间状态。这种问题很难排查,后来我的做法是并行任务开始前先冻结输入,确保所有子代理读到的都是同一版本。

6.3 上下文传递的常见误区

子代理不共享主会话的记忆,这意味着你以为了解的背景信息,子代理可能完全不知道。常见误区:

误区一:以为子代理知道项目约定。比如项目里有个约定“所有 API 返回都用 Result 包装”,你没在子代理提示词里写,子代理就不知道,生成的代码就不符合约定。解决办法是把关键约定写进子代理的提示词,或者让子代理自己去读项目的规范文档。

误区二:以为子代理能看到之前的对话。你在主会话里讨论了半天需求,然后派活给子代理,子代理对这些讨论一无所知。解决办法是在派活时把必要的背景信息显式传过去,或者让子代理自己去读需求文档。

误区三:以为子代理之间能互相看到结果。审查子代理发现的问题,测试子代理看不到。如果测试需要根据审查结果调整,就得等审查完成后再派测试任务,或者让主代理把审查结果转述给测试子代理。

6.4 性能与成本的平衡

子代理用多了,成本和耗时都会上去。几个优化方向:

  • 能并行的才并行。串行任务强行并行,只会增加协调开销。
  • 简单任务用轻量模型。前面说过,格式转换、机械操作这类任务没必要用强模型。
  • 复用子代理定义。同一类任务用同一个子代理,不要每次重新定义。
  • 控制子代理数量。3 到 7 个是甜区,超过 10 个协调成本会急剧上升。

我做过一个对比测试:同一个任务,单会话串行做耗时约 25 分钟,拆成 4 个子代理并行做耗时约 9 分钟,但 token 消耗增加了约 40%。所以并行是用成本换时间,值不值得看具体场景。紧急任务值得,日常任务可以串行。

6.5 常见问题速查表

问题现象可能原因解决方法
子代理不被调用description 太笼统改成具体职责描述
子代理调用错误多个子代理职责重叠明确各自边界,或显式指定
并行结果互相覆盖写操作冲突拆分任务或改串行
子代理输出不符合项目规范缺少背景信息提示词里补充约定
子代理擅自修改代码权限过大收紧 tools 配置
成本超预期简单任务用了强模型按任务复杂度分配模型
子代理卡住不返回任务描述有歧义检查指令,补充边界条件

7. 进阶玩法:动态编排与子代理复用

7.1 让主代理自己决定怎么拆

前面讲的都是你手动拆好任务再下指令。进阶玩法是只给目标,让主代理自己拆。比如:

我要给项目加一个用户反馈功能,从需求到上线你安排一下。

主代理会自己分析需要哪些步骤,调用哪些子代理。这种方式适合你对项目很熟、信任主代理判断的场景。但风险是主代理可能拆得不符合你的预期,所以第一次用建议盯着点,看它的拆分逻辑合不合理。

7.2 子代理的跨项目复用

配好的子代理可以复制到其他项目里用。但要注意,提示词里如果写了项目特定的约定,换项目就不适用了。我的做法是把子代理分成两类:

  • 通用型:提示词里不写项目特定内容,只写职责和方法,可以跨项目复用
  • 项目型:提示词里包含项目特定的约定和规范,只在本项目用

通用型子代理我一般放在一个公共目录里,需要的时候软链接到项目里。这样维护一份,多个项目共享。

7.3 子代理的版本管理

子代理的提示词会随着项目演进不断调整,建议纳入版本管理。每次调整提示词都提交一次,写清楚改了什么、为什么改。这样出问题的时候可以回溯,看看是哪次改动导致的。

我还会给子代理写测试用例——准备几个典型任务,每次改完提示词跑一遍,看输出质量有没有下降。这个做法有点像给提示词做回归测试,虽然土但很有效。

8. 我个人的一些实操体会

分工这件事,工具只是表象,核心还是任务拆解的思维。我用了大半年 SubAgent,最大的体会是:拆任务的能力比配子代理的能力更重要。子代理配置再漂亮,任务拆得不对,照样一团糟。

另一个体会是不要追求全自动。全自动跑起来很爽,但一旦方向偏了,返工成本很高。我现在更倾向于半自动——关键节点人工确认一下,其余交给子代理。这样既享受了分工的效率,又保留了纠偏的机会。

最后分享一个小技巧:给每个子代理起个好记的名字。名字本身就是一种提示,主代理在匹配任务时会参考名字。code-reviewer比agent-1好用得多,test-writer比helper精准得多。这个细节看起来不起眼,实际用起来差别很明显。

子代理的提示词也不是一次写好的,我现在的几个常用子代理,提示词都改过十几版。每次遇到输出不理想的情况,就回去补一条约束或改一处描述。慢慢磨,磨到它稳定输出你想要的结果为止。这个过程没有捷径,但磨好之后,它就成了你团队里最靠谱的那个成员。

返回列表