Claude Code Subagents实战:把AI拆成专家团队解决角色串味 用AI写业务代码这件事做到一定阶段都会遇到同一个瓶颈一个通用 Agent 很聪明但你在十个项目里反复切换场景时它常常会“串味”。代码评审让它写测试写测试时它又忍不住顺手重构代码看起来全会实际上哪一步都差点火候。Claude Code 里的 Subagents 就是冲着这个问题来的它本质上是把“一个人同时干五个工种的杂活”改成“五个专家各干各的”也就是 AI 角色工程化。这个机制不仅能让大模型输出的稳定性上一个台阶还在上下文管理和成本控制上有实实在在的收益。这篇文章我会从机制原理讲到目录结构从提示词写法讲到多角色协作最后附上我自己实测中踩过的坑。1. 为什么要把 AI 拆成“团队”Subagents 解决的核心问题1.1 单 Agent 模式的三堵墙绝大多数人刚开始用 Claude Code 时都会把它当成一个什么都会的通用助理。你在对话里让它“帮我写接口”它写了让它“帮我看看这个报错”它看了让它“评审一下刚才这段代码”它也能评。问题就出在这个“也能评”上。第一堵墙是上下文污染。主对话里混着需求讨论、代码修改、报错分析、闲聊式确认几十轮之后模型记住的是前二十轮的内容忘了你最开始明确强调的项目约束。你以为它还在按最初的标准干活实际上它的注意力早被最近的无关内容稀释了。最典型的症状就是你在聊完一个完全不相关的需求之后让它继续写业务代码它忽然开始沿用前面那个对话里的风格甚至崩出别的项目的术语。第二堵墙是指令互相干扰。一个对话里同时存在“要严谨”“要有创意”“少写注释”“注释要详细”这类互相打架的要求时模型只能是各退半步最后产出一个怎么都不满意的中间状态。这不是模型不够聪明而是没有一个人能在同一时刻既是审计员又是创意设计师。角色工程化的思路就是把这些互相冲突的指令拆到不同 Agent 的独立上下文里让每个 Agent 只面对一套自洽的规则。第三堵墙是成本不可控。所有任务都跑在同一个高能力模型上浪费非常夸张。查一个字典式的简单问题、批量整理几个文件、做一次规则固定的格式校验这些任务完全不需要每次都调用最强模型。你不会让公司架构师去打印文件也不该让旗舰模型去反复执行模板化的琐碎操作。1.2 Subagents 的运作方式Claude Code 里的 Subagents 不是“插在主对话里的指令标签”它是一套独立运行、独立上下文的委托机制。主 Agent 接到你的需求后会根据子代理的 description 判断应该把任务派给谁然后通过内部的任务调用机制把子代理“派出去”。子代理在自己独立的上下文窗口里干活只看到任务描述、它自己读取的文件内容、它自己的工具执行结果主对话的历史不会灌进来其他子代理的产出也不会在它这里“串味”。这带来三个直接好处。第一个是隔离性角色提示词之间不会互相干扰给你写 PostgreSQL 专用 SQL 的角色没有必要知道另一个角色要求“所有输出必须用中文”。第二个是专注性子代理被创建出来的每一秒钟都在执行单一任务不存在“聊着聊着忘了目标”的问题。第三个是资源可控性你可以给不同的子代理分配不同的模型档位重活让 sonnet 干轻活让 haiku 跑预算心里有数。我打个比方不带任何贬义地说它非常像你在公司里开外包团队主 Agent 是项目经理只负责拆解任务、分给合适的人每个 Subagent 是外包团队里的专项负责人只对自己手里的交付物负责。项目经理不需要懂每个专项的细节专项负责人也不需要对客户需求全局负责各管一段交接界面就是任务描述和返回结果。1.3 哪些场景最值得先落地不是所有任务都需要 Subagents一开始就堆十个角色反而会把自己绕晕。根据我试用几个月的经验收益最明显的场景几乎都长着同一副面孔任务边界清晰、可重复执行、输出结果可以被规则化描述。场景典型任务为什么适合子代理代码评审提交前检查代码风格、安全性、边界条件规则固定、标准清晰避免主对话里的上下文污染错误排查分析日志、定位崩溃原因只读取指定日志文件不会被无关对话干扰测试生成为模块生成单元测试和边界用例输出格式容易模板化且不需要了解业务全局文档维护根据代码变更更新 README 和接口文档独立上下文里只有模块代码不容易写飞数据迁移数据库表结构调整与脚本生成SQL 规则固定、风险高需要专项角色反复检查发布检查发布前检查配置、环境变量、变更清单是重复性极强的清单式工作最适合角色固化反过来那些高度依赖全局上下文、需要跨模块综合决策的任务比如“帮我把整个应用的架构重新设计一下”不推荐丢给子代理。这类任务需要站在全局视角反复权衡主 Agent 的长程记忆反而更合适。2. 动手之前的设计角色划分与目录结构2.1 角色边界怎么切很多人第一次接触 Subagents第一反应是把所有常用指令都做成角色“来个帮我写前端页面的”“来个帮我写后端接口的”。这种做法表面上是分工实际上是把大而全的 Agent 拆成了大而全的碎片每个角色管的事还是太宽触发时照样容易跑偏。我自己的经验是角色边界应该沿着“一个角色负责一种完整交付物”来切而不是按技术栈切。比如“前端工程师”这种角色就不如“React 表单页面构建专家”好用因为“前端工程师”这四个字背后包含的逻辑太多了模型接到任务后还是需要自己判断前因后果。“React 表单页面构建专家”则目标单一拿到需求就产出符合表单规范的页面和校验逻辑。还要考虑两个角色之间是不是会有任务重叠。如果“测试用例生成专家”和“代码质量评审专家”你都想做那大概率会出现同一条代码被两个角色同时处理的情况产出反而不如一个角色按“先评代码再生成测试”的顺序干活来得干净。我的建议是先列出你真实工作中高频重复的五件事从这五件事里挑出边界最清晰的三个做成角色而不是先想角色再凑任务。2.2 目录结构与命名规则Claude Code 扫描子代理配置时有几套固定位置。个人级别的配置放在用户目录下的.claude/agents/目录它对所有项目生效项目级别的配置放在项目根目录的.claude/agents/目录它只对这个项目里的对话生效。两边定义同名角色时项目级会覆盖个人级这是符合直觉的“就近优先”规则。每个子代理对应一个 Markdown 文件文件名的格式直接影响你后续的使用体验。我常用的规则是全部小写用连字符连接名字要能一眼看出职责至少要让未来的自己看名字时不需要点开文件猜它是干什么的。code-reviewer.md比review.md好log-triage-expert.md比logger.md好。命名上的另一个坑是跟现有命令或内置功能撞名。比如你建一个叫help的子代理那大概率会跟 Claude Code 已有的帮助命令在触发时互相打架。我的习惯是前后都加一个明确的前缀比如dev-review-code、dev-parse-logs把“这是自定义角色”这个信息直接写进名字里。2.3 和 CLAUDE.md 分工全局记忆 vs 按需专家不少人会有个疑惑有了 CLAUDE.md我为什么还要 SubagentsCLAUDE.md 的主要用途是给主 Agent 提供整个项目的基础背景比如技术栈、目录结构、代码风格约定、启动命令这些是每次对话都应该被记住的信息属于“全局记忆”。Subagents 的定位完全不同它是“按需加载的专项能力”。你不需要每次对话都想起它它应该在你遇到对应任务时被主 Agent 自动“点兵点将”地叫出来。全局记忆是地基角色是房间里的专业设备两者解决的不是同一个问题。更关键的区别在于 CLAAUDE.md 里的内容会给每一个后续消息造成持续的 token 消耗你写进去的每句话都在每一次请求的上下文里待着子代理的提示词只有在它被调用时才会加载不用的时候完全不占资源。如果你的 CLAUDE.md 已经膨胀到超过几千行那就该反思一下哪些内容其实可以做成一个只在特定任务里加载的子代理。3. 一个子代理是怎么写出来的字段、提示词与工具权限3.1 frontmatter 四个核心字段的写法和意图子代理文件最上面是一段 YAML 格式的 frontmatter用来声明这个角色的元信息。四个字段我需要逐个说明因为它们每一个都在影响“主 Agent 该不该用你”这个判断。--- name: log-triage-expert description: 当用户需要分析日志、排查异常、定位崩溃原因、分诊堆栈报错时使用。日常业务问答不要触发。 tools: Read, Grep, Glob model: sonnet ---第一个是name角色的唯一标识。你需要保证它在同一目录里不重复而且尽量不用特殊字符。它不仅是内部 ID也是你将来手动 调用时的入口。第二个是description这是整个文件里最重要的字段。它不是给人类看的是给主 Agent 看的“角色使用说明书”。主 Agent 要根据这段文字判断当前用户的请求属于哪个角色的职责范围。写得不好有两种典型结果一是太宽泛比如“处理日志”主 Agent 觉得什么异常都可以派给它导致角色被滥用二是太狭窄比如“只在电商订单系统的 ABC 日志文件出现 JAVA_EXCEPTION 时使用”那大概率它永远没机会被触发。好的写法是“满足什么特征的问题场景需要用我 什么情况下不要用我”的组合。第三个是tools这个字段决定了角色能使用哪些工具。Claude Code 的常用工具包括命令执行、文件读写、在工程里搜索、读文件和引用外部代码等。子代理如果没有声明任何工具那么它只能基于传入的文本做分析和输出这作为纯推理角色也可以但多数实操任务是需要工具支持的。需要特别提醒的是不要不加思考地全量授权角色的工具权限应该遵循最小化原则。第四个是model给这个角色指派模型档位。不同版本对可用模型代号的叫法会有差异以你当前版本的可用值准。如果这个字段不加子代理会继承主对话当前使用的模型加上之后它就能按照任务复杂度被分配不同档位的模型这也是把成本精细化的手段。3.2 正文提示词的结构化写法frontmatter 下方的大段正文就是这个角色的系统提示词它决定了角色被激活之后“怎么想”和“怎么做”。我强烈推荐把正文分成四段式来写这会极大减少产出质量不稳定的情况。第一段角色定义。用一两句话说明这个角色是什么、服务对象是谁比如“你是一名日志分析与异常定位专家服务对象是负责业务后台维护的开发者”。不要写太长太长意味着模型核心记忆里塞了太多修饰词。第二段工作流程。这是我觉得最不能省的部分。如果只告诉模型“你是日志专家”它可能会按自己臆想的方式去抽丝剥茧如果你给出“先读取日志文件 - 按时间排序并统计错误分布 - 对 TOP 3 错误追查调用栈 - 归纳根因 - 给出修复建议”这五步它就知道自己是来执行流程的不是来自由发挥的。很多人觉得模型不够强、不够听话其实很多时候是人没给它一个需要按顺序执行的步骤清单。第三段质量要求与红线。明确写出哪些事情绝对不能做比如“不要臆测日志中没有出现的错误”“不要在没有定位到根因时直接给出重构方案”。红线指令在业务场景里非常关键模型是概率生成你划出的红线能明显压低它乱发挥的概率。第四段输出格式。这个也容易被人忽略。我自己的体验是制定了严格输出模板的角色交付结果的稳定性远高于“你自由发挥”的角色。如果你希望它输出一份排查报告就给它规定标题层级、字段名称、每个字段要填什么内容甚至给它一个可以直接复制粘贴的 Markdown 骨架。3.3 工具与模型选型最小权限和成本平衡我给子代理配置工具权限时有一条铁律这个角色只需要什么就给什么绝不写“全部”。给日志分析专家 Read、Grep、Glob 就够了它不需要能改文件更不需要能执行任意命令。你把它设置成只能读、只能搜它就不会在排查过程中突然“手贱”帮你改掉一行代码。模型选型的逻辑也是同理。需要深度的任务比如代码审查、架构设计、疑难 bug 根因分析适合用最强档位的模型重复性高、规则明确的任务比如生成模板化测试用例、整理错误代码、分类日志用较轻量档位的模型不但跑得快成本也低得多。我见过一个比较实用的分配策略是这样的把“代码评审专家”放到最强档位因为评审本身就是吃推理深度的活把“测试用例生成专家”放到中间档位它需要理解业务逻辑但不需要过度发散把“日志格式转换专家”这类纯规则活放到最轻档位它只需要机械执行格式转换用强模型纯属浪费。三个角色都跑在同一个项目里主对话统一走中等档位整体 token 花费反而比以前只用强模型单线程跑所有任务更低。4. 从零写一个“日志分析专家”完整实操实录4.1 场景定义与文件准备为了让你对“从想法到文件再到实际调用”有一个完整的体感我拿身边最常遇到的一个实际场景来全程走一遍。场景是这样项目里有个业务后台每天产生大量日志开发者经常在群里收到一条“线上有报错”的信息然后要自己登服务器翻日志找原因。传统做法是手动 grep、手动看堆栈费时且容易漏。我打算用 Subagents 做一个专职的日志分诊角色。这个角色应该具备的能力接收一段需求比如“帮我查一下订单接口为啥报错”自己定位日志文件路径通过搜索和读取来分析错误频率和堆栈最后输出一份结构化排查报告。基于这个目标我先在项目根目录建好目录mkdir -p .claude/agents然后把角色文件建进去。这个目录放在项目里意味着这个角色只对当前项目生效对团队协作也友好配置跟着项目走别人克隆下来就能直接用。4.2 完整配置示例与参数说明下面是我实际在用的一个精简版本它足以让你跑通全部流程。--- name: log-triage-expert description: 当用户提到日志报错、线上异常、崩溃定位、堆栈分析、错误分诊时使用。日常业务功能开发、普通代码编写请求不要触发。 tools: Read, Grep, Glob model: sonnet --- 你是一名日志分析与异常定位专家服务对象是负责业务后台维护的开发者。你的任务是对给定场景的日志进行分诊找出错误根因并输出可执行的修复建议。 工作流程 1. 如果用户没有给出日志路径先用 Glob 或 Grep 定位项目下最近的日志文件。 2. 按时间顺序读取日志统计错误类型与出现频率。 3. 选出出现频率最高或影响最大的一类错误读取对应位置的完整调用栈。 4. 结合代码仓库中的相关文件定位错误可能出现的代码位置。 5. 输出排查报告不臆测日志中未出现的信息。 质量要求 - 必须基于日志中实际出现的内容不能编造错误类型。 - 没有拿到根因时如实说明“尚未定位到明确根因”不要给出模糊猜测。 - 修改建议必须标注置信度并给出验证方式。 输出格式 ## 错误概览 - 时间范围 - 错误总数 - TOP 错误类型 ## TOP 1 错误分析 - 错误类型 - 出现次数 - 首次出现 - 调用栈关键段 - 可能原因 - 建议修复 - 置信度 ## 其他待观察 - 列出需要进一步关注的低频异常。这份文件说明了几件事description 写清了触发条件和反例正文里的工作流程把角色从“自由分析”变成了“按流程执行”输出格式从一开始就规定了交付物长什么样。模型拿到这个系统提示词后它的自由度被压缩在合理的范围内产出的报告质量非常稳定。4.3 真实会话中的调用与结果验收文件保存后新开一次 Claude Code 对话什么都不用配置角色就自动可以被识别。我在实际使用中有两种触发路径。一种是自动触发直接在主对话里输入“帮我看下今天订单接口的报错日志分诊一下原因”主 Agent 读完 description 后认为这属于日志分诊专家的工作范围于是自动把任务派出去。如果你发现它没有自动触发可以主动在主对话里输入log-triage-expert 帮我分析今天的日志这是手动点名路径。角色被调起来之后它会自己去项目里找日志文件、读取、分析最终输出一份像下面这样的报告## 错误概览 - 时间范围2025-01-15 09:00 至 2025-01-15 18:00 - 错误总数23 - TOP 错误类型订单状态回调超时 ## TOP 1 错误分析 - 错误类型OrderCallbackTimeout - 出现次数12 - 首次出现09:31 - 调用栈关键段OrderService.handleCallback - HttpClient.post - ReadTimeout - 可能原因回调接口响应平均耗时 3.2s超过客户端 2s 超时阈值 - 建议修复调整超时时间或优化回调接口响应速度 - 置信度高理由为超时时间与响应耗时直接匹配这份报告是我以前手动翻日志至少要花十几分钟才能整理出来的内容现在从角色被触发到拿到完整报告整体耗时基本在半分钟内。我验收了两个维度一是事实准确性报告里的错误类型和时间段与日志原文能对上二是行动价值建议修复能直接转到开发侧去执行。两者都符合预期。5. 多角色协作嵌套、调度路由与工具扩展5.1 让子代理调用子代理单角色已经足够解决很多重复性任务但某些复杂业务天然需要多个角色接力。Claude Code 的子代理机制允许一个子代理在任务执行过程中再派出另一个子代理形成嵌套调用关系。举一个我实际搭过的例子一个“数据库迁移审查专家”接到任务后先自己读数据库表结构发现迁移脚本涉及订单、库存、商品三张表于是它分别派出“订单表专项检查员”“库存表专项检查员”“商品表专项检查员”各查各的表最后它回收三份子报告汇总成一份综合评估。这种结构很像技术团队里的“技术负责人拆活给下属再汇总下属反馈”逻辑完全一致。但嵌套调用有一个需要克制的地方层级越深信息损耗越大每次传递都是一次“转述”。我踩过的最深的坑是三到四层嵌套之后最顶层的角色已经搞不清最底层角色到底看到了什么。所以我给自己定了一条规矩业务任务里嵌套最多两层。第一层角色拆任务第二层角色执行具体动作再往上就过深了。5.2 用 description 做“调度路由表”当你拥有的角色越来越多主 Agent 如何判断当前请求该派给谁就变成了一个实际工程问题。我最后的结论是路由是否准确几乎完全取决于每个角色的 description 写得是否够精确。我在一个合作项目里同时维护了六个角色其中一个“竞品调研分析师”和“技术方案评审员”的 description 写得很模糊导致用户在讨论技术选型时主 Agent 经常把任务派给调研分析师而不是评审员。后来我把两个角色的 description 各自加上了明确的“使用时机”和“禁止使用时机”例如给评审员写“当用户需要评估方案优劣、架构风险、技术选型比较时使用竞品市场情报收集不要触发”给调研分析师写“当用户需要了解市场现状、竞品动态、行业趋势时使用普通的技术方案优劣讨论不要交给本角色”。修改之后自动路由准确率肉眼可见地上升。这件事给我的启发是不要只把 description 当成一个给模型看的静态标签而是把它当成调度中心的路由表来设计。每个角色的 description 要考虑全局明确写清自己的职责半径和别人的职责半径甚至可以直接写“如果请求符合 XX 角色描述不要调用我”这种反例过滤机制在处理相似任务时特别有效。5.3 接入 MCP 工具和 Hooks 的进阶玩法如果子代理只是会读文件、搜代码那它的能力边界还是太窄。更进一步的做法是给子代理接入外部的 MCP 工具服务让它能调数据库、发请求、操作第三方系统。比如我给“数据库巡检专家”接了一个数据库查询用的 MCP 工具它就能在拿到授权的前提下直接执行只读查询而不只是静态分析 SQL 脚本。接入时要注意工具的可见性控制。不能让一个角色直接看到所有 MCP 工具最佳实践是在子代理配置里限定它可用的工具集合只把巡检需要的数据库工具暴露给它。这个思路跟前面提到的最小权限原则完全一致隔离的不只是上下文还有工具边界。Hooks 机制则可以解决“什么时候触发”的问题。比如在每次代码提交前自动派一个“发布检查专家”跑变更检查在每次文件写入后自动派一个“文档同步专家”更新相关文档。这些自动化触发逻辑适合放在 Claude Code 的 Hooks 配置里让角色在特定事件发生时被自动唤醒而不是等你手动输入命令。组合理解下来一个成熟的多角色系统就是Hooks 负责“什么时候干”Subagents 负责“干什么”MCP 负责“用哪些工具干”三者各司其职。6. 常见问题与排查技巧实录6.1 角色怎么叫都不出来的排查这是最常见、也最容易让人怀疑配置失败的问题明明文件建在正确目录格式也没错但主 Agent 就是不自动触发角色。我排查这一类问题有固定的顺序。先确认目录和文件名有没有拼错注意 Claude Code 扫描的是.claude/agents/如果你建的是agents/或者.claude/agents.txt那就完全不会被看到。再检查 frontmatter 是不是完整的 YAML 格式。前几年我遇到过 frontmatter 里少了name字段导致整个文件被跳过的情况YAML 解析失败时角色不会报错而是悄悄不加载。如果目录和 frontmatter 都没问题那问题大概率在 description。你需要站在主 Agent 的视角模拟一遍用户说“帮我查一下日志”你的 description 里如果全是“处理日志、分析异常、定位根源”这类词主 Agent 会认为这是自己的活不需要叫子代理。反过来如果你在 description 里用的是主 Agent 明显做不到的词比如“对 100MB 级日志文件做批量分诊”它才会认真考虑派活。解决方法是把 description 的核心触发词写得跟用户实际口语贴近并明确写出“这类问题不要自己处理交给本角色”。6.2 输出风格完全不受控如果你发现角色是被触发了但返回的内容和你预期相差很大比如让它输出一份报告它给你写了一篇叙事文章那基本可以确定是正文提示词的问题。我在踩过几次坑之后总结了两个最常见的诱因。第一个是正文里只有角色定义没有输出格式。模型拿到“你是日志专家”之后它会按自己理解的“专家报告”来输出跟你心里的“专家报告”很可能完全不是一回事。解决办法就是在正文里把输出模板直接写死给一个可以照着填的骨架它就不会跑飞。第二个是正文里同时存在互相冲突的要求。如果你说“分析报告要简洁”又说“要尽量输出完整背景信息”模型就会在“简洁”和“完整”之间反复横跳。正确的做法是给它更具体的标准比如“报告总字数控制在 500 字以内字段包括以下 5 项”而不是形容词。6.3 上下文超限、权限不足与递归循环上下文超限是嵌套角色很容易踩的坑。主 Agent 会把任务描述传给子代理子代理任务执行完后返回的结果又会回到主 Agent 的上下文里。如果子代理在它自己的上下文里读了很多大文件再把大量内容传回主 Agent很快就会撑爆。我的处理经验是子代理报告结果时要遵守“结论优先、细节按需展开”的原则。提示词里明确要求它返回精简报告而不是原始日志全文原始内容只在需要时通过二次读取获取。这样主 Agent 端拿到的始终是压缩后的有效信息而不是整段原始文本。权限不足的问题通常表现为角色认为自己需要执行命令或修改文件但它被授权到工具列表里没有这一项。解决方法是先想清楚这个角色到底要不要做这个操作如果确实需要就补进 tools 字段如果不需要那说明角色试图做了不该做的事要在正文里加红线。递归循环则是子代理在流程中不断调用自己造成任务卡死。我在正文里会加一条硬性规则“如果你已经在执行本任务不要再触发同类型的子代理检查”这个规则虽然简单但非常有效。6.4 我踩过的一些抗坑清单最后把我实际维护 Subagents 三个月来踩到的所有坑压缩成一份清单供你直接对照排查。不要一开始就建十几个角色先集中精力把三个最常用的角色打磨到稳定再逐步扩展。description 里正面触发词和禁止触发词都要写只写触发词的配置在角色变多后会产生严重的路由混乱。Subagents 文件必须纳入版本管理我的团队在 Git 里专门维护 .claude/agents 目录配置变更可以回溯、代码审查也能看到。每次新项目开始之前先想清楚哪些角色是通用能力、哪些角色是这个项目特有的通用能力放到个人目录项目特有的放进项目目录。角色产出变差时首先检查是不是正文提示词太长导致关键要求被稀释精简到核心步骤和核心输出格式往往比继续加长效果更好。角色长时间没被触发不一定意味着没用可能是任务场景本身没出现过可以通过定期检查调用记录来发现自己到底在为哪些不存在的需求建角色。这套机制真正值钱的地方不是“多了一个能调用角色的命令”而是逼着你用工程化的方式去思考 AI 的使用边界。以前我写提示词是写给模型看的现在我是把角色的定义、调度规则、权限范围和输出规范当成一份需要长期维护的代码在管理。这种思维方式转换之后你不光能用好 Subagents再回头去看自己写过的其他提示词也会有种“以前全凭感觉现在终于有章法”的清爽感。