如果你还只是把 Claude Code 当做一个能聊天的命令行窗口那我建议你停下来看看 Subagent。我最早也是这样单线程聊得挺顺但代码库一大会话就开始犯迷糊。主模型要同时记住前面的需求、读过的文件、做过的修改上下文被各种细节占满最后返回的东西要么太泛要么干脆跑偏。后来我把 Subagent 配置起来才算是真正打开这个工具的价值。Subagent 说白了就是在 Claude Code 里定义一批可以随时调用的“专员”。每个专员有自己的角色说明、工具权限和输出风格你需要的时候把它派出去它自己读文件、查代码、改代码处理完把结果交回来。它特别适合这几类人已经在用 Claude Code 但觉得单线程不够用的人想给团队沉淀一套自动化代码检查能力的人以及面对几万行老代码需要批量梳理的人。这篇文章不聊空理论直接讲清楚怎么配置、三个能直接跑通的场景以及我踩过的一些坑。1. 为什么单代理不够用Subagent 到底解决了什么1.1 单线程对话的上下文困境一个 Claude Code 会话本质上是一段持续上下文。主代理要同时记住你最开始的需求、前面讨论过的方案、看过的文件内容、已经做出的改动。对于一个中型项目来说把所有相关文件都塞进一个会话里既不现实也没必要但单代理很难克制住自己不看。结果就是它在几十个文件里反复横跳把大量上下文浪费在路径和文件内容上真正留给推理的空间反而被压缩。你的需求一旦复杂它就显得“很笨”。这很像一个餐馆只有一个厨师既要点菜、配菜又要炒菜还要兼顾收银。看起来省了人力实际上每个环节都做不透。Subagent 的思路就是请一队人主代理当店长负责接单和统筹子代理是各个岗位的厨师每人只管自己的锅。每个子代理拥有独立的上下文窗口它在自己的世界里读文件、跑命令、生成结果主会话只保留最终的关键结论。这样即使子代理读了一堆大文件主会话也不会被塞满后续的推理质量自然更稳。1.2 Subagent 的定位不是脚本是“专员”有人以为 Subagent 就是一段预设好的提示词其实不是。它背后仍然是完整的模型推理过程它有自己的 system prompt、工具列表和模型档位甚至可以为不同子代理选择不同的模型配置。它不是一个简单 if-then 脚本更像是一个可以随时入驻团队的“虚拟组员”。举个例子我在配置文件里定义过一个代码审查专员它的职责是扫描指定目录并只输出风险清单。每次我想让代码过一遍审查不需要重复交代“你要注意异常处理和输出格式”只用在主对话里说一句“让审查专员看看这个模块”。它自己会使用读取、搜索、执行命令这些工具然后按我预先定义的模板返回结果。这就是复用性和一致性的价值主代理不用每次重新学习一套流程只需要负责派活和汇总。2. 动手前的准备工作环境与声明方式2.1 最小可运行环境先确认你已经装好了 Claude Code 的命令行工具并且完成了基本登录。这个工具迭代速度不慢不同版本对 Subagent 的配置格式支持可能略有不同所以最好先跑版本命令确认当前版本再对照官方文档来写配置。如果版本太旧配置格式不兼容最典型的表现就是你明明定义了子代理但在主对话里怎么都调用不出来。接着在项目根目录下创建.claude/agents/目录。以后每个子代理放一个配置文件。注意这个目录属于项目级配置不是全局配置所以建议直接纳入版本库管理。团队协作时每个人都用同一套子代理定义比各改各的配置要省心得多。我第一次用的时候没建这个目录结果写好的子代理完全不生效排查了很久才发现 Claude Code 根本不认别的位置。2.2 配置文件的字段拆解一个子代理配置通常是一段带前置元信息的文本。下面是我常用版本的一个示例--- name: code-reviewer description: 当需要对指定文件或目录进行代码审查时使用重点关注异常分支和资源泄漏 tools: Read, Grep, Glob, Bash model: fast --- 你是一名代码审查工程师。请只返回审查结论不要粘贴整个文件。 输出格式 风险级别 | 文件位置 | 问题描述 | 建议修复每个字段都有它的讲究。name是调用时的名字一般用短横线风格。description是重中之重因为主代理是靠它来决定“什么时候应该派这个子代理”。如果 description 写得过于宽泛主代理可能觉得这个任务自己也能处理就不会去调用子代理如果写得太窄它又会错过正确时机。所以我会在 description 里带上“当用户提到‘审查’‘检查代码’时必须调用本子代理”这种触发条件。tools是允许子代理调用的工具列表这里建议克制一些。Read、Grep、Glob 已经可以覆盖大部分代码浏览场景Bash 是可选的。把不用的工具塞给子代理相当于给一个新人全公司门禁卡随时可能出现意料之外的改动。model能单独指定模型档位不一定所有子代理都用最高档。简单格式化任务用低档模型复杂审查用高档模型成本和速度都会更好。最后面的正文就是 system prompt定义这个专员的“行为守则”。值得注意的是不要在配置里粘整个项目结构那会浪费大量上下文正确的做法是只描述职责和输出约定。3. 三个可以直接照抄的全流程实操场景3.1 场景A代码审查专员假设你刚改完一个订单模块想快速过一遍代码质量。在主对话里直接这样输入code-reviewer 请审查 src/order/create.js重点关注异常分支和事务边界。主代理会找到code-reviewer子代理把文件路径和关注点交给它。子代理在独立上下文里读取文件、搜索相关引用、必要时执行命令查看逻辑然后按预设模板返回审查结果。我实际用下来它比单代理审查更聚焦不会把不相关的历史代码也翻出来回答内容也更结构化。你完全可以要求它返回一张表格比如“高风险三处、中风险两处”然后让主代理继续追问“高风险的问题怎么修”。这种工作流很自然审查结论可以立刻变成修复指令。唯一要注意的是主会话里一定要给明确的文件路径和审查目标。如果只说“看看订单模块”子代理很容易自己猜猜中的概率并不高最后给出的结果也不一定落在你真正关心的代码上。3.2 场景B跨模块接口重构这个场景更贴近日常。我遇到过一次接口签名变更底层函数从getUserById改名为getUserProfile但返回值保持不变而调用方遍布几十个文件。手动改容易漏全交给主代理又担心它上下文不够于是我用了一个专门做重构的子代理。它的 system prompt 里明确要求先用 Grep 找到所有调用点再逐个文件替换并且每次修改前先输出改动计划不直接动原文件。在主对话里给指令refactor-agent 把 src/api.js 里的 getUserById 改名为 getUserProfile返回值保持不变并同步更新所有调用方。它会自己搜索调用点生成改动清单然后逐文件修改。因为我在配置里限制了“先输出 diff不要直接写文件”所以我可以先确认一遍改动方案等没有明显风险后再让它正式执行。这一步防呆设计非常重要。自动重构遇到动态属性名、字符串拼接、解构赋值这些特殊场景很容易踩雷diff 提供了一个人工把关的机会能省下大量回滚时间。3.3 场景C测试生成与执行闭环另一个很好用的场景是测试。我定义过一个测试生成专员专门负责从已有函数出发生成单元测试约定输出标准测试框架的代码还会覆盖正常值、空值、负数、超大数这些边界条件。然后我再定义第二个专员负责运行刚才生成的测试文件并返回失败日志。这两个子代理不能直接通信所以主代理要当中间人传递信息。实际操作是这样。先派测试生成专员test-gen 为 src/util/calculator.js 的 calculateTotal 函数生成测试覆盖正常、空值、负数、超大金额四种场景。它返回一段测试文件代码我再把这段代码交给测试运行专员test-runner 运行刚才生成的测试文件汇报失败项。这个流程虽然有多个来回但每一步都有中间产物出了问题可以定位到具体环节。如果你想一步到位也可以让一个子代理同时完成生成和运行但那样一旦出错排错成本会比拆开高很多。我宁可在流程上多一步也不愿意面对“不知道是哪一步出了问题”的排查现场。4. 多 Subagent 的编排与上下文管理4.1 并行派发与任务树Subagent 真正的威力来自并行而不是简单替换单代理。一个大型任务可以拆成任务树主代理当树干负责拆解目标、分配任务、汇总结果子代理当树枝各自完成一个模块。如果某个子代理内部还需要更细的分工它还可以在它自己的上下文里继续派发嵌套任务这样就是多级流水线。举个例子。一次全仓库梳理我同时派出去三个子代理一个负责 API 接口审查一个负责数据库操作审查一个负责前端状态管理审查。它们在自己的上下文里并行跑再把结论汇总回主对话。最后主代理生成一个总报告告诉我“最严重的问题是数据库连接泄漏集中在两个文件里”。三个任务并行跑总耗时从一个多小时缩减到十几分钟。如果不做拆分单代理串联跑这三个任务时间成本完全不一样。4.2 上下文管理和“信源污染”并行虽然欢快但上下文管理一旦跟不上很快会翻车。所有子代理返回的内容最终都会进入主对话如果子代理不懂克制把整个文件全部粘回来主上下文会被快速灌满后面的对话会越来越迟钝。我的解决办法是在每个子代理的 system prompt 里都写一句“只返回结论、证据位置和必要的小段代码不要粘贴整个文件”。另一个容易被忽略的问题是“信源污染”。当多个子代理同时都要写同一个临时文件、或同时改同一个文件时会出现互相覆盖的问题。这就像两个人同时编辑同一个文档谁后保存谁赢但内容已经乱了。解决方法有两种一种是把每个子代理的工作范围限定在不重叠的文件集合里另一种是让子代理先返回 diff再由主代理统一应用。并发场景下这两条准则能避免绝大多数冲突。5. 高频问题与排查技巧实录5.1 一张表兜住八成报错现象可能原因排查 / 解决子代理没被调用主代理自己答完了description 写得太笼统主代理没识别到在 description 里写清“用户提到某任务时必须调用本子代理”子代理找不到文件工作目录和预期不一致或相对路径错误统一在项目根目录启动提示词里给出明确路径子代理只能读不能写tools 列表里没有写入类工具补上对应写权限并再次确认配置生效子代理返回超长主对话被撑爆没在 system prompt 里约束输出长度要求只返回摘要、结论和必要代码片段子代理开始胡言乱语模型档位太低或任务太宽换更强的模型或者把任务拆得更小多个子代理互相覆盖改动并发写同一个文件改为先输出 diff再由主代理统一应用这张表覆盖了我遇到的大部分问题。第一行其实是新手最容易卡住的地方。主代理是语言模型它通过 description 来判断要不要派活。如果 description 只写“代码审查”主代理很可能觉得“这个我也会”于是自己上手但如果在 description 里写清“当用户说‘用审查专员’或‘检查安全隐患’时必须调用本子代理”触发率就会提高很多。这个问题本质上是“路由问题”把触发条件写得越明确主代理的派活权限就越精准。5.2 三个真正闹心的问题详解第一个是路径问题。子代理说找不到文件但同一路径在主对话里明明存在。排查之后发现问题出在工作目录如果在一个子目录里启动了 Claude Code相对路径是相对于启动目录而不是项目根目录。解决方案是统一在项目根目录启动或者在提示词里写绝对路径。但绝对路径不利于团队共享所以最好还是约定启动位置并把这个约定写进团队文档。第二个是工具权限。有个子代理配置里没有声明写工具它分析完以后告诉我“已修复文件”但实际上文件完全没动。它以为自己调用了写工具但系统层面直接拦截了。那一次我检查了半小时最后发现是 tools 字段漏了写权限。所以凡是需要修改文件的子代理tools 里必须显式加上对应权限否则它只是在空谈修复方案文件不会有任何变化。第三个是输出污染。子代理返回一个几百行的 JSON主代理为了理解这个 JSON 又消耗了大量上下文后面的对话越聊越迟钝。后来我改成让子代理先返回 Markdown 表格主代理如果有需要再继续追问详细内容。输出格式直接决定主代理后续的推理质量有时候你以为信息越全越好实际上噪声越大重点越模糊。6. 让 Subagent 真正好用的几条经验6.1 设计 System Prompt 的五个原则我用了好几周之后总结出五条原则。第一是身份明确一个子代理只做一件事不要既审查又重构又生成测试否则主代理反而不知道什么时候该派它。第二是输入边界清楚告诉子代理“你只需要关注某个目录不要扫描其他地方”能有效减少不必要的搜索和判断。第三是工具箱克制不用的工具坚决不给宁可后续再加权限也不要一开始就给全。第四是输出格式固定每个子代理返回的结构保持一致方便主代理自动解析和汇总。第五是退出条件清晰告诉子代理“完成什么状态就算任务结束”不然它会一直分析下去。每次新建一个子代理我都会拿这三个问题自检主代理能在五秒内看懂这个 description 吗子代理真正需要的最小工具集是什么返回结果会被主代理怎么使用三个问题都有答案配置一般不会差。我还会先用一个小样例试跑一次确认子代理输出的格式正确、内容稳定再放心把它用在正式任务里。这个习惯帮我省掉了大量返工时间。6.2 模型档位、并发控制与版本管理模型档位不是越高越好。审查类、重构类任务需要较强的推理能力可以配高档模型而简单的格式调整、批量改名用低档模型就够成本和响应速度都有优势。我一开始让所有子代理共用同一个模型后来发现一批低难度任务明显可以被更快完成换挡之后整体效率提升很明显。这个优化不需要改逻辑只调整 model 字段就能见效。并发方面同时派两三个子代理是安全的但一次派七八个很容易触发限流或者出现部分子代理返回质量下降。我的经验是需要并行的任务最多控制在五个以内并根据返回情况动态增补。另外Subagent 的配置文件要纳入版本库管理和代码放在一起。这样团队所有成员的调用行为一致就算某天某人改了配置其他人也能从版本记录里看到改动内容。如果每个人本地一套配置协作起来会非常痛苦。最后说一点最实在的体会。Subagent 上手很快但真正拉开差距的是你愿不愿意把任务拆得足够干净。我第一次用的时候恨不得把整个项目的问题一次性交给一个子代理处理结果返回的东西根本没法看。后来老老实实把每个子代理的职责边界、输入输出格式定清楚一次只处理一件事效果反而好得多。如果你也准备开始用不妨先从“代码审查”这个场景试起定义一个小而美的专员跑通一次再慢慢加场景。配置这种事宁可多花十分钟设计也不要图省事一次性堆到底。