把一个大项目直接丢给 Claude Code 单线程硬肝,是很多人刚接触 Agent 编程时都会踩的坑。你让它一边重构后端、一边写前端页面、一边还要盯着测试跑,结果就是上下文越来越臃肿,它开始"前面说过的话全忘了",改一处接口另外三个文件跟着崩,最后你不得不在一堆半成品里手动收拾残局。我就是从这种狼狈状态里走过来的,后来认真研究了 Claude Code Agents 的多代理协作与任务委托机制,才算是把 AI 编程的"单人模式"升级成了"团队作战模式"。
这篇内容我会讲清楚多代理协作到底是怎么回事、什么样子的任务值得拆出去交给子代理、怎么在 Claude Code 里配置自定义 Agent 和 Skills、以及一次完整任务委托的实战复盘和常见问题排查。适合已经用过 Claude Code、但觉得单会话不够用的人,也适合正在研究 Agent 工程化、想把 AI 编程从"玩具"推向"生产力工具"的开发者。读完你会发现,多代理协作的核心其实不在"多",而在"边界切得清楚"。
1. 多代理协作的本质:从单兵作战到团队分工
1.1 单会话的瓶颈:为什么需要把任务"交出去"
先说一个我在真实项目里反复撞见的场景。有一次我给 Claude Code 派了个任务,让它给一个中等规模的 Web 项目加"订单导出"功能,同时顺手把相关测试补一补。刚开始它跑得挺顺畅,写了后端接口、改了前端按钮,但当一个对话里的 token 越积越多,它就开始"精神涣散",一会儿觉得订单字段应该用order_no,一会儿又改回id,测试文件里引用了一个根本不存在的导出函数,它还信誓旦旦说"已通过验证"。
这不是模型变笨了,而是单个会话的上下文像一个越堆越乱的办公桌。所有历史内容——包括中间过程、错误尝试、无关讨论——都堆在主对话里,模型每次生成都要在这个混乱现场里找线索,出错率自然指数上升。更现实的问题是,一个会话只能串行干活,写接口的时候它没法同时去跑测试,整体耗时被拉得很长。
所以多代理协作不是锦上添花,而是把"一个人干所有事"改成"项目经理分派任务"。Claude Code 里的主代理(primary agent)保留全局视野,负责理解你的总目标、拆解任务、分派给合适的子代理、再收集结果做决策。子代理(subagent)则在一个隔离的上下文里专注干一件事,干完把结果摘要交回来。
1.2 子代理机制是怎么运转的
Claude Code 的 Agents 体系里,有两类子代理。第一类是内置的通用子代理,比如专门负责代码搜索、文件读取、网页抓取、命令执行的角色,它们在日常操作里会被主代理自动调用。第二类是你自己定义的项目级 Agent,放在项目目录的.claude/agents/下,每个 Agent 就是一份带 YAML 头部信息的 Markdown 文件,定义了它的名字、职责描述、可调用的工具和模型。
调度的核心逻辑并不神秘:主代理拿到你的指令后,会先判断当前任务是否匹配某个 Agent 的description描述;如果匹配,并且它认为这个任务适合隔离处理,就会通过Task工具把这个子任务连同必要上下文一起交出去。子代理在执行过程中是"单线程专注"的,看不见主对话里的历史,也不受其他子代理干扰。多个互不依赖的子代理甚至可以并行启动,各查各的、各写各的,最后把结果汇总回主代理手里做集成判断。
这种两段式结构很像真实团队里的汇报机制:子代理不需要知道整个公司的商业机密,只需要知道自己那一亩三分地的任务、输入和产出标准就够了。上下文隔离听着像是技术限制,实际上省掉了大量互相干扰的噪声——这恰恰是任务准确率提升的关键。
1.3 任务委托对应的现实分工模型
用现实职场来类比,你的主代理就是那个"什么都要懂一点"的项目经理,子代理是各领域的专家。项目经理的职责不是把代码全部自己写完,而是拆解需求、评估工作量、把设计文档甩给后端、把页面需求甩给前端、让测试人员去跑回归、最后把大家的产出拼起来看整体效果。
这个类比帮我想通了一个关键问题:项目经理最怕的不是专家能力弱,而是任务边界模糊。你让前端专家去改数据库表结构,让后端去调 CSS,结果就是大家都在猜、都在返工。所以委托的本质是"把正确的事交给正确的人",而在 Agent 语境里,"正确的人"由description描述和tools权限一起定义,"正确的事"则由你在任务描述里给的上下文和验收标准定义。
理解了这个模型,再看 Claude Code 的多代理协作就很清楚了。它不是一个让你"喊一句就全自动完成"的魔法,而是一个需要你亲手设计任务边界、定义验收标准、控制权限范围的工作流工具。把这个基础打牢,后面所有配置和实操才有意义。
2. 场景设计与任务拆解:哪些活适合交给子代理
2.1 适合委托的三种典型任务形态
不是所有任务都适合拆出去。我的经验是,适合委托的任务通常能归进下面这三种形态。
第一种是可独立验证的探查型任务。比如"在整个代码库里找出所有调用旧版sendEmail函数的位置,并列出调用方的文件和行号""搜索项目里所有硬编码的数据库连接串""读一遍payment_service.py并总结它的错误处理逻辑"。这类任务输入输出非常明确、不依赖外部状态,子代理可以拿着文件路径自己去找,找完汇报结果就行。我经常同时开两三个这种探查型子代理,一个查 API 路由、一个查数据库模型、一个查前端调用链,效率比我自己慢慢grep高出一大截。
第二种是专一职责的实现型任务。像"根据docs/contract.md里的字段定义,实现order_export.py的导出逻辑""给src/components/Chart.tsx写一个空状态样式""用 Vitest 给utils/format.ts写完整单测"——这类任务范围收敛、有清晰的代码文件作为边界,子代理可以在隔离上下文里全力实现,不会跑偏去改无关代码。
第三种是按模板批量处理的机械化任务。"把locales/zh-CN.json里所有缺失的 key 按英文文案补到locales/en-US.json""给项目里所有*.stories.tsx文件补上Meta前置注释"——重复性强、规则明确的任务,特别适合让子代理批量执行,省得主代理在对话里一遍遍重复相同指令。
2.2 任务边界划分的四条实操原则
拆任务时我踩了不少坑,后来总结出四条原则,基本能覆盖大多数情况。
第一,输入输出必须可描述。主代理在委托之前,要能在任务描述里说清楚"你从哪些文件开始、参考什么契约、最终产出什么格式的结果"。如果这个任务连你自己都描述不清楚输入输出,子代理只会更糊涂。我见过有人给子代理下"优化一下这个项目"这种命令,子代理回复了一篇泛泛而谈的建议书,等于没干。
第二,不依赖高频协同。两个子任务如果需要在执行过程中频繁同步状态——比如后端边改接口、前端边调接口、两边还要实时对齐字段——那就不适合拆开。拆出去的结果必然是两边各猜各的,最后对不上。真正的多代理协作是任务之间有明确契约,而不是任务之间有实时依赖。
第三,结果可验收。你或者主代理必须有一种方式判断子代理干得对不对,比如编译通过、测试通过、diff 符合预期、文件内容包含关键字段。不可验收的任务,委托出去之后你只会得到一封"我干完了"的假报告。
第四,权限边界清晰。给子代理配置tools时,先想清楚它需要哪些工具。探查型任务只给Read和Grep,实现型任务给Read、Write、Edit、Bash(Read-only),需要跑测试时再加执行权限。权限越窄,误操作空间越小。
2.3 粒度控制:别把子代理当成万能执行器
粒度问题是多代理协作里最容易犯的错,而且犯错了代价很高。任务拆得太粗,子代理面对一堆模糊目标,只能按照自己的"世界观"去猜,猜对了是你运气好,猜错了就是一轮又一轮的追问和返工。任务拆得太细,比如每三行代码修改就叫一次子代理,调度开销和上下文切换损耗可能比你自己直接做还大。
我个人的经验值是:一次委托对应一个能在十分钟到二十分钟内完成、并且产出一个可以直接检查的成果的任务。举例来说,"给InvoiceService补上税率计算逻辑并附带单测"是一档合理的任务;"重构整个订单模块并把前后端都改一遍"就太粗了;"把total = subtotal * 1.13改成total = subtotal * (1 + TAX_RATE)"这种又太细。
太粗的任务心里没底,太细的任务又烦人,所以我在实际操作中经常做一个"预拆"动作:先让主代理输出一个任务拆解清单,我把每个子任务在心里评估一遍"如果是我本人来做需要多久、产出是什么",超过二十分钟的继续拆,不足五分钟的就合并。这个习惯帮我省了大量跟 Agent 纠缠的时间。
3. 环境配置与自定义子代理实现
3.1 安装与基础环境准备
Claude Code 的安装方式有不少,最常用的一路是走 npm 全局安装。终端里执行npm install -g @anthropic-ai/claude-code,装完运行claude进入交互界面,首次使用需要完成账号登录或配置 API Key。除了命令行终端,官方也有桌面端,以及 VS Code 插件,这几个渠道底层打通的是同一套 Agent 机制,不影响后续多代理配置。如果你更习惯编辑器内开发,装个插件直接侧边栏里开会话也很方便。
关于模型接入多说一句:Claude Code 默认连 Anthropic 的服务,但如果你有特殊需要,比如想接 DeepSeek 或者其他兼容 Anhtropic 接口格式的模型服务,也可以通过设置ANTHROPIC_BASE_URL这类环境变量来指向兼容端点。这个思路适合想尝试不同模型的开发者,但要注意一点:Claude Code 的 Agent 工具链依赖模型自身的工具调用能力,不是所有模型都能完整、稳定地执行多步 Agent 流程。实际体验下来,专用模型配合专用工具框架才是最稳的,第三方接入更适合做调研和成本对比。
多代理相关的几个配置参数里,我特别提醒一个:子代理的并行数量和上下文策略在不同版本里有过调整,升级 Claude Code 后最好重新翻一下官方文档,不要拿旧版的经验直接套新版。我遇到过升级之后任务委托行为变了、排查半天才发现是版本差异的情况。
3.2 自定义 Agent 的配置结构
自定义 Agent 的核心落在.claude/agents/目录。每个 Agent 是一个 Markdown 文件,文件名无所谓,但文件开头的 YAML frontmatter 里有几个字段会直接决定调度行为,我用一个例子说明。
--- name: code-reviewer description: 负责代码审查,擅长发现潜在 bug、安全问题、逻辑漏洞和可维护性隐患。当用户提交新代码、要求审查某个模块或检查合并请求质量时使用本代理。 tools: Read, Grep, Glob, Bash(Read-only) model: sonnet ---这个name是子代理在对话中显示和调用的标识。description最关键——主代理就是靠读这段描述来判断当前任务是否该委托给这个 Agent。所以描述里一定要写清楚"什么情况下触发我",最好包含明确的关键词和场景词。tools决定子代理能调用哪些工具,控制它不会乱动手修改代码。model可以留空继承默认,也可以单独指定更快或更强的模型,实现分级调度。
frontmatter 下面是正文,就是子代理的系统提示词。你可以在这里面写清楚角色的目标、工作流程、输出格式、以及最重要的"不要做什么"。比如 code-reviewer 的正文我会写"你的任务是审查而非修复代码,不要主动修改任何文件,只需输出结构化审查报告"。
我在第一次配置时犯过一个典型错误:把description写得特别抽象,比如"一个帮助开发的助手",结果主代理几乎任何任务都会考虑它,反而干扰了调度判断。后来把description改成高度具体的触发描述,调度才变得精准。我这里再强调一次,触发词要具体到"什么场景"而不是"什么角色"。
3.3 用 Skills 给子代理追加专项技能
自定义 Agent 定义了"谁来干",Skills 则定义了"怎么干"。Claude Code 的 Skills 目录放在.claude/skills/下,每个 Skill 是一个包含SKILL.md的文件夹,头部同样带 YAML frontmatter,声明技能的名称和描述,正文则写清楚操作流程、代码模板、注意事项等。
比如我给项目配置了一个"生成单元测试"的 Skill,内容就是这套流程:先读源文件,识别需要覆盖的分支和边界条件,按照项目既有的测试风格生成测试文件,最后运行测试并汇报覆盖率变化。有了这个 Skill 之后,不管哪个子代理负责写测试,它都能按统一的流程执行,不会自己发明一套风格。
Agent 和 Skill 的组合方式是灵活多变的。你可以给一个"后端实现"Agent 挂上"生成接口文档"Skill,让它在写完接口后顺手产出文档;也可以给一个"文档维护"Agent 挂上多个 Skill,让它承担不同文档类型的生成。我的经验是:Agent 负责定义角色和权限边界,Skill 负责定义操作细节和项目规范。项目规范放进 Skill 里还有一个好处——团队其他同事拉取项目后自动获得同样的技能,不需要再口头交代。
3.4 委托指令的落地:Task、@ 提及与主代理调度
配置好自定义 Agent 后,实际委托有几种触发方式。
第一种是对话里直接@agent名 任务描述,比如@code-reviewer 请审查一下 feature/export 分支上 src/services/export.ts 的改动。这种方式显式指定了子代理,适合你心里已经清楚该让谁干活的情况。主代理收到这个指令后会把任务转交给对应 Agent,子代理拿到必要上下文后开始执行。
第二种是隐式调度。你不对着某个 Agent 说话,而是在主对话里提出一个总目标,主代理会根据自己的判断,把任务拆开、分派给不同 Agent。这要求你的自定义 Agent 描述写得足够清楚,主代理才能做出正确决策。我实际用下来,隐式调度更适合探索型任务,显式@提及更适合你已经明确了边界和归属的执行型任务。
第三种是Task工具。主代理在调用工具的时候会动态构造一个任务描述,附上需要的文件路径和上下文,交给你指定的子代理。这个工具可以嵌套调用,也就是说子代理自己也能再委托给其他子代理,但我不建议过度嵌套,层级越深、调度链路越长,出错概率越大,而且调试成本翻倍。
无论哪种触发方式,主代理最后都会收集子代理的结果摘要,再基于全局上下文做整合判断。所以在实际操作中,你更多的精力应该放在"任务描述"本身的质量上——描述越精确,结果越可靠。
4. 多代理协作实战:一次完整任务的委托过程复盘
4.1 项目背景与总任务拆解
纸上谈兵说再多,不如完整走一遍流程。我拿最近一个真实项目来复盘:一个内部使用的订单管理系统,用 TypeScript 写的后端 Node.js 服务和前端 React 应用,代码在同一个仓库里跑。需求就一句话——"添加订单导出功能,支持按日期范围筛选,并补好测试和文档"。
这句话如果直接丢给单会话去干,结果就是我开头说过的那种混乱状态。所以我把总任务拆成四块:后端接口实现、前端页面与下载交互、自动化测试、README 和 API 文档更新。前三个可以并行,文档可以在接口完全定稿后再写,避免文档跟着代码反复改。
拆完的委托清单长这样:
backend-agent:在src/routes/下新增/api/orders/export接口,按查询参数startDate和endDate筛选订单,导出 CSV 格式文件。frontend-agent:在订单列表页新增"导出"按钮,点击后调用后端接口并处理文件下载,需要做加载状态和错误提示。tester-agent:为后端导出接口编写集成测试,mock 订单数据覆盖正常导出、空结果、日期格式错误三个场景。docs-agent:更新 README 中的功能列表,新增 API 文档段落,说明接口参数和返回格式。
4.2 三个子代理的并行执行与结果回收
实际执行时,我先在 Claude Code 里显式调用了三个实现型子代理:@backend-agent、@frontend-agent、@tester-agent,把各自的输入上下文给足——后端拿到订单数据模型的字段定义、前端拿到按钮应该插入的位置和 API 地址格式、测试拿到接口的预期行为描述。
三个子代理并行跑起来之后,主对话的负载立刻降下来了。我不用再看一堆中间过程输出,只要等待结果摘要回收。子代理们各自在隔离上下文里写代码、跑工具,也不会互相污染。比如前端子代理在改组件样式时,完全不会碰到后端子代理正在调整路由代码的这种问题。
最后三份结果差不多同时回收:后端接口实现完成、前端按钮和下载逻辑就位、测试文件写好了但测试还没跑。这里有个关键操作——我让主代理先汇总三方的产出,用 Git diff 快速检查一遍改动范围,确认每个子代理都没越界改动不属于自己职责的文件。责任心是有了,但我的检查步骤不能省。
4.3 从失败中修正:委托边界调整的两次迭代
这次实战不是一次成功的。第一轮委托结束后,我跑到前端页面一测下载,发现导出的 CSV 里日期格式跟后端序列化格式不一致——前端期望YYYY-MM-DD,后端给的是 ISO 格式。问题不在模型笨,而在我拆任务时没把"日期格式"这个契约写进任何一方的任务描述里,后端子代理按自己的理解实现,前端子代理也按自己的理解解析,两边自然对不上。
第二轮修正就很简单了:我先让backend-agent把接口输出字段中的date改成YYYY-MM-DD格式,并在任务描述里明确写上"前端会按该格式解析,不允许其他格式";然后让前端子代理重新跑一遍下载流程做验证。这次修正只花了十几分钟,而如果是在单会话里干,我恐怕要翻遍上下文找到底哪一步约定丢了。
我印象最深的教训是:多代理协作的失败,大多数时候不是模型执行能力不足,而是任务描述里缺失了契约信息。后来我养成了一个习惯,每个委托任务描述里都加一句"输入格式是什么、输出格式是什么、两边靠什么契约对齐",这个习惯把跨代理协作的失败率压下来一大半。
补完测试之后,我还做了一次整体验收:让tester-agent运行全部测试,让docs-agent根据最终代码状态更新 README,最后自己手动跑了一遍导出流程确认功能可用。整个过程耗时比单会话串行做快了差不多一半,而且每个环节的结果都可独立检查,出了问题也定位得快。
5. 常见问题与排查技巧实录
5.1 委托不生效:description 字段没写好
有段时间我的自定义 Agent 几乎不会被主代理主动调起来,查了半天,问题全在description上。最开始我写的是"负责后端开发的助手",这个描述太宽泛了,主代理判断什么任务都想塞给它,反而导致选择困难,最后干脆自己干了。后来我把描述改成"当需要新增后端 API 路由、修改数据库模型字段定义、编写服务层业务逻辑时使用",主代理立刻就能精准匹配了。
如果你也遇到委托不生效,先检查三件事:Agent 文件是否放在项目根目录的.claude/agents/下而不是子目录里;描述里是否包含当前任务相关的场景关键词;以及新会话有没有加载最新的 Agent 列表。改完配置建议重开一个会话,让主代理重新读一遍项目配置。
5.2 上下文隔离与结果回收问题
上下文隔离是子代理最大的优点,但也带来一个反作用——主代理拿到的通常只是摘要,细节会丢失。我遇到过子代理"自信满满"地报告"测试全部通过",但我一查日志发现它根本没运行测试,只是做了个静态检查就下了结论。
解决方案是明确要求子代理把关键产出写进文件或者把关键 diff 贴回来。我的做法是在 Agent 的正文提示词里加一句:"输出结果时,必须提供具体文件的 diff 摘要或执行日志中的关键输出,禁止只汇报结论。"这样主代理才能拿到可验证的中间产物,而不是一个不可信的口头汇报。另外,如果某次协作需要完整保留子代理的上下文而不想被摘要截断,可以考虑让它把完整结果写入一个临时文件,主代理需要时再读取。
5.3 模型适配与费用控制经验
多代理协作会显著消耗更多的 token,因为每个子代理都在独立的上下文里工作,这些上下文在任务结束后会被释放,但释放前的消耗是要付费的。如果你是 API 计费模式,又不做控制,月底账单会让人心疼。
我的费用控制策略是分级调度:探查型、总结型、搜索型任务用体积小、速度快的模型跑,因为这类任务不需要太强的推理能力;实现型、重构型、代码审查型任务才用最强模型。这个策略在自定义 Agent 时就可以落地,每个 Agent 的model字段单独指定,费用效率比统一用最强模型提升很多。
还有一个容易被忽略的点:并行子代理虽然省时间,但 token 消耗是同时发生的。如果项目预算紧张,可以限制并行的子代理数量,一次只放两个出去,而不是一股脑全开。多代理协作省下来的时间如果折算成开发成本,通常还是划算的,但你心里得有一本账。
5.4 多代理协作的快问快答速查表
| 问题表现 | 可能原因 | 解决方案 |
|---|---|---|
| 主代理从不调用自定义 Agent | description太宽泛模糊,主代理难以匹配 | 重写描述,用具体场景词和触发关键词 |
| Agent 改了职责之外的文件 | tools权限过宽 | 收紧tools,只保留 Read/Edit 等必要权限 |
| 子代理汇报"成功"但结果不可用 | 正文没有要求输出可验证的中间产物 | 在提示词中要求返回 diff、日志或写入文件 |
| 跨代理协作后字段/格式对不上 | 任务描述里缺少契约约定 | 给每个相关 Agent 写明输入输出格式 |
| 并行跑完 token 消耗暴增 | 并行数量太多、模型选择过重 | 限制并行数,按任务类型分配快慢模型 |
| 新配置的 Agent 在新会话里用不了 | Agent 文件放错目录或没重开会话 | 确认在项目根目录.claude/agents/下并重开 |
这个表里的每一条都是我实际踩过或者帮同事排查过的,你可以把它当成一份排查手册存在手边。
写在最后的实践心得
我实际用下来的体会是,让多代理协作真正变稳的核心,不是把任务描述写得多花哨、也不是把 Agent 配置得多复杂,而是你愿意在前置拆解上花多少时间。宁可多花十分钟把边界、契约和验收标准写清楚,也不要省这十分钟、后面花一个小时在返工里追悔。
还有一个我觉得特别有用的小技巧:每个子代理的任务描述里,开头第一句先写"不要做什么",再写"要做什么"。比如 "不要修改任何与导出功能无关的文件""不要在回复里粘贴完整源码,只返回 diff 摘要"。这个反向约束的效果出奇得好,因为模型在开放式任务里最容易出的问题不是能力不足,而是发散和越界,提前划好"禁区"比事后纠正高效得多。
多代理协作这套玩法后续还可以继续扩展,比如把 Agent 的配置做成团队共享的仓库模板,让所有同事拿到项目后自动获得一致的分工规范;或者把 Skills 文档化沉淀成项目资产,让新上手的人也能快速理解每个角色该干什么。我在项目里已经开始这么做了,效果比我预期得还要好。希望这份经验也能帮你把 Claude Code 从"单线程聊天工具"真正变成"能打硬仗的团队伙伴"。