子代理系统是我在 Claude Code 里用起来最上瘾、也最容易被误用的功能。前几篇聊了基本命令、上下文管理这些“单兵作战”技巧,今天这篇专门聊它内置的子代理(subagent)系统——说白了,就是让你不再对着一个 AI 对话窗口重复解释同一件事,而是给这个 AI 配上一支可随时点名的“专家团队”。如果你已经能把主对话用得很顺,但总觉得每个任务都要重新交代背景、检查结果又不够独立,那这篇文章就是为你准备的。
子代理系统解决的是一个很朴素的问题:一个全能的对话式助手,在真实项目里往往不够用。不是它能力不行,而是它会受到主对话上下文、工具调用权限和任务目标的干扰。你让它一边改代码一边审代码,它很容易为了完成手头的改动,顺手放过了代码里的隐患。子代理的思路是拆出若干个专职角色,每个角色拥有独立的上下文、明确的任务边界和受限的工具权限,主代理只负责调度和汇总。
下面我就从原理、配置、实战到踩坑,完整拆一遍。
1. 子代理不是“插件”,而是一种全新的分工方式
1.1 从单线程对话到多角色协作
大多数人用 Claude Code 的习惯是:一个主对话从头用到尾,让它写代码、修 bug、解释逻辑、做代码审查,全部挤在同一个上下文窗口里。一开始没问题,但对话轮数一多,上下文里的信息就开始互相打架。前一秒你还让它按 A 方案实现,后一秒它可能顺着你的一句话把实现改成了 B 方案。你真正想要的“严格按当前文件风格写代码”这个指令,被淹没在大量无关的历史讨论里。
子代理系统改变了这种单线程结构。它允许你在项目里预定义若干“虚拟角色”,每个角色有自己的系统提示词、工具访问范围、模型选择。主代理遇到对应任务时,可以把任务整体打包交给子代理,等子代理返回结果后,主代理再继续完成后续工作。
我习惯把这种模式理解成一个项目组:主代理是项目经理,子代理是组里的专家。项目经理不需要自己画架构图、逐行审代码、查依赖漏洞,它只需要判断当前任务该交给谁,然后把完成结果整合进整个项目上下文。这样既降低了主代理的认知负担,也让每个专项任务可以在干净的环境里执行。
1.2 子代理与普通任务模式的本质区别
不少人第一次听说子代理时,会把“加一段系统提示词”和“配一个子代理”混为一谈。这是最需要澄清的地方。
普通任务模式下,你只是在一段完整对话里插入新的指令,所有历史上下文仍然存在。子代理则不同,它拥有独立的上下文。这个新上下文通常只包含“系统提示词 + 当前任务描述 + 主代理显式提供的内容”。父对话里的历史轮次,并不会自动流入子代理。也就是说,子代理看到的是一张相对干净的白纸,上面写好了角色定位、任务目标和交付格式。
另外,工具权限也是隔离的。主代理可以访问全部已启用的工具,子代理只能使用你在配置里明确允许的工具。比如一个代码审查子代理,我通常只给它 Read、Grep、Glob 这类只读工具,不允许它直接改文件。它要做的是指出问题,而不是顺手“修复”问题。很多评审动作失真的原因,就是子代理手里拿着写文件的能力,嘴上说“这里有 bug”,手上已经把它改掉了。
所以,子代理系统的价值不在于“多了一个 AI 模型”,而在于“多了一套上下文和权限隔离机制”。它让每个角色都能专注于自己的专业判断,不被其他任务干扰,也不越权做不该做的事。
1.3 为什么你需要一支“专家团队”
以我手上的几个中型项目为例,最明显的痛点有三类。
第一类是规范执行不一致。同一个项目里,有的模块用了简单的直接字符串拼接,有的模块用了模板字符串,代码风格像两个团队写的。让主代理统一处理,它改着改着就会漏。但如果有一个专门的“代码规范审查员”子代理,在每次合并前扫一遍,问题就能被固定流程拦住。
第二类是知识背景冲突。比如你让主代理同时处理“接口兼容”和“数据库迁移”两件事,它经常会把两者搅在一起。在子代理模式下,数据库变更审计交给一个子代理,接口兼容评审交给另一个,两个角色持有不同的专业提示词,结果会清晰得多。
第三类是上下文被无意义信息占用。一个依赖安全检查子代理只需要读 lockfile 和漏洞数据库,不需要知道你的业务模块叫什么、页面交互怎么设计。把它放在独立上下文里,能省下大量 token,也减少误判。
说白了,子代理的意义不是让 AI 更“聪明”,而是让 AI 在长链路工程任务里更可控、更可复用。
2. 调用链路由浅入深:一个任务如何被拆给“专家团队”
2.1 主代理的调度逻辑与上下文隔离
子代理的触发方式,从外部看非常简单:你可以在对话里输入/agent之类的命令,也可以通过自然语言让主代理“把这段代码交给 code-reviewer 子代理”。但内部发生的事,远比表面上看起来复杂。
当主代理决定调用某个子代理时,它会根据子代理的description字段来判断哪个角色匹配当前任务。这个描述不是给人看的,而是给主代理看的。主代理通过描述来决定“当前需求对应哪个专家”。如果描述写得含糊,主代理可能选错人,或者压根不调用。
匹配完成之后,主代理会构造一个子代理会话。这个会话的初始系统提示词是你定义的角色提示词,用户消息则是主代理对当前任务的转述。注意这里有个关键点:主代理不会把你整个对话历史一股脑塞给子代理,它只会挑它认为必要的文件内容、代码片段、需求描述传过去。所以子代理收到的信息是经过主代理“筛选”的。
这就解释了为什么你常常觉得“子代理不够了解项目”。不是它笨,而是它真的只拿到了主代理转交的那部分信息。如果你希望子代理了解某个背景,必须在任务描述里显式写清楚,或者让它自己去读项目里的文档。
2.2 子代理返回结果如何被主代理消化
子代理执行完毕,会返回一份结果。这份结果同样不是简简单单的一句话,而是包含任务结论、关键发现、可能存在的风险点、剩余待办事项等信息。主代理拿到这份结果后,会把它作为一段新的上下文内容,继续与你交互。
这里我特别想提醒一个实践细节:子代理返回结果的质量,直接决定主代理后续行为的准确性。如果你的子代理只回一句“代码有问题”,主代理也没办法精准处理。所以我在定义子代理时,一定会要求它在结果里给出“问题清单 + 文件路径 + 行号 + 修复建议”。这样主代理才能基于结构化结果做后续决策。
另外一个容易忽略的点是,主代理可以选择不把子代理的结果完整展示给你。它可能会做二次加工,比如用更简洁的语言转述、合并多个子代理的结果。这在多子代理协作时特别常见。从使用者角度看,你要理解:你看到的最终回复,可能已经经过主代理的“过滤和提炼”,不一定能完全还原子代理的原始输出。因此在调试子代理时,我会专门让子代理把完整输出写到某个 Markdown 文件里,方便事后复盘。
2.3 关键配置项:模型、工具、权限与描述
配置子代理时,有几个参数直接影响效果,这里逐个说。
模型选择。不同任务对模型能力的敏感度不同。架构评审、复杂代码推理,我用更强的模型;简单的依赖检查、文本格式校验,用更快更省的模型。如果在所有子代理上都用最强模型,成本会很快失控;但如果代码审查这种关键环节用了太弱的模型,又很容易漏报。
工具白名单。这是子代理安全性的核心。只读任务绝不给 Edit/Write 权限,需要执行命令的任务才给 Bash。我给子代理配置工具时,会遵循“最小够用”原则:能只读就只读,能限定目录就限定目录。
描述字段。description是主代理选择子代理的依据,所以它必须描述“什么情况下调用、擅长什么、不擅长什么”。比如一个代码审查子代理的描述可以写:“负责代码逻辑缺陷审查、安全漏洞初筛、风格规范检查。当你需要评估变更质量时使用。不负责修改代码。”这样主代理就不会在“帮我重构”这种任务里错误调用它。
权限与交互模式。有些子代理需要在上手前向你确认信息,有些则需要完全自主运行。我通常把需要人工确认的步骤写进系统提示词,让子代理在遇到歧义时主动提问,而不是用强制等待机制。
3. 亲手配置一个子代理:文件格式、角色提示词与注册验证
3.1 目录结构与文件格式
在 Claude Code 的项目级配置里,自定义子代理通常是放在项目根目录下的.claude/agents目录中,以 Markdown 文件形式存在。每个文件对应一个子代理,文件名就是子代理的 ID。推荐的做法是:先为这个子代理起一个简短、唯一的英文名,比如code-reviewer,然后创建同名文件。
一个最简单也最可靠的自定义子代理文件,结构大致如下:
--- name: code-reviewer description: 擅长代码审查,发现逻辑缺陷、安全隐患与风格问题。当需要评审代码改动时使用。不要用于代码重构。 tools: Read,Grep,Glob,Bash model: sonnet --- 你是一名资深的代码评审专家。你的任务是对主代理交给你的代码变更进行审查。 审查时遵循以下步骤: 1. 先用 Read 读取目标文件,理解上下文。 2. 用 Grep 查找相关调用关系,确认改动影响面。 3. 输出问题清单,格式为:文件路径 | 行号 | 问题类型 | 严重程度 | 修复建议。 约束: - 你只能读取代码,不能修改任何文件。 - 如果发现严重问题,直接给出复现步骤。 - 不要输出客套话,直接给结论。这个文件里,frontmatter(开头两个---之间的内容)是子代理的元信息,正文是角色提示词。实际字段可能因版本不同略有差异,但name、description、tools、model这几个是最核心的。
3.2 角色提示词的核心写法
子代理的角色提示词,比给主对话的提示词要更克制。它不是让你发挥文采,而是让你精准定义“输入、处理、输出”三个环节。
输入环节要写明子代理会收到什么。比如“你会收到一个或多个文件路径、一段需求描述、一份变更 diff”,这样子代理知道从哪里开始。
处理环节要写清方法与步骤。不要只写“你要认真审查”,而应该写“先读文件,再查调用链,再对照项目规范”。步骤化越明确,子代理输出的稳定性越高。
输出环节是最容易被忽视的。你必须规定输出格式,否则每个子代理都在自由发挥。我在配置里几乎都会要求子代理按固定结构输出,比如问题清单、风险评估、建议方案。这样主代理后续消化结果的成本会大幅下降。
另外,如果你的项目有自己的编码规范文档,可以把它放在指定路径,并在子代理提示词里写明“先读取 docs/coding-standard.md,再开始审查”。不过要注意,子代理提示词不应该包含过多项目细节,最好通过文件引用的方式让子代理按需读取,而不是全部贴在提示词里。
3.3 在会话中唤起与验证
配置好子代理之后,不是必须重启 Claude Code 才能生效。多数情况下,新定义的子代理能在下一次会话中直接被识别。我建议你做一个快速验证,而不是直接上生产任务。
验证方式很简单:先在一个小文件里故意埋两个明显的问题,然后要求主代理调用这个子代理去审查。看它是否被正确调用、是否使用了规定的工具、输出是否符合格式要求。
一个常见的配置错误是:子代理文件写好后,主代理始终不调用它。原因通常不是文件格式错了,而是description写得太窄或太宽。写得太窄,主代理不认为当前任务匹配;写得太宽,主代理很容易选错。正确的做法是把描述写成一个“调用条件清单”,让主代理一看就知道什么时候用、什么时候不用。
还有一个细节:子代理定义文件里的名称,和你在对话中口头说出的名称,最好保持一致。比如文件名叫code-reviewer,那么在对话里你说“交给 code-reviewer”,主代理会更稳定地匹配。否则它可能需要靠description去“猜”,一旦猜错,整个任务节奏就乱了。
4. 真实场景组合:我搭的“代码评审 + 架构审查 + 迁移审计”三人组
4.1 代码评审员:只动口不动手
我的第一个子代理是代码评审员,核心作用是在大改动合入主干之前做一轮机械而稳定的检查。它的工具权限控制在 Read、Grep、Glob、Bash 四类,禁止 Write、Edit、MultiEdit 等写文件工具。
它的系统提示词里写明:每次拿到改动文件后,先列出改动涉及的功能点,然后按“逻辑缺陷 / 安全隐患 / 风格问题 / 可维护性”四个维度输出清单。每一条问题后必须附上文件路径和行号。如果某个问题没有对应行号,就说明它只是泛泛而谈,没有真正看代码。
实际用下来,这个子代理最有价值的地方不是发现复杂 bug,而是处理那些“主代理容易视而不见”的低级问题。比如一个变量在条件分支里未定义就被使用,这类问题在长对话里经常被忽略,但在独立上下文中,子代理会严格按照逻辑执行检查,反而不容易漏。
不过要注意,这个子代理不能完全替代人审。它的知识截止和模型推理上限决定了它更适合做“第一道筛子”。我通常在它与人工评审之间设定一条线:子代理负责扫明显问题,人工负责判断设计合理性和业务正确性。
4.2 架构审查员:用痛点清单推动决策
第二个子代理是架构审查员。它不像代码评审员那样读每一行代码,而是专门评估一次较大改动的架构合理性。它的系统提示词强调:先理解现状,再分析改动引入的耦合、扩展性、异常处理缺口和分层问题,不纠结具体语法。
为了提高它的判断质量,我给它额外配置了一个项目级的架构文档路径。它在每次任务开始前会主动读取当前模块的架构说明,然后再结合代码调用关系给出结论。
这个子代理的产出不是“问题清单”,而是一份“决策建议书”。开头是结论概要,中间是支持结论的证据列表,最后是三个可选方案。我拿到之后,会根据实际情况做取舍。可以说,它更像是我的架构思考平替,用来在方案评审前先把明显问题暴露出来。
4.3 依赖审计员:把安全扫描沉淀为流程
第三个子代理是依赖审计员,主要负责检查项目的依赖文件是否存在已知漏洞、版本是否过老、是否存在锁文件不一致的问题。它的工具权限里包含 Read、Grep、Bash,没有写权限,所以它不能擅自升级依赖。
它的提示词里明确规定:先读取项目依赖清单和锁文件,再对比已知漏洞库信息,输出一个表格。表格的列包括“包名 / 当前版本 / 建议版本 / 风险等级 / 影响范围 / 修复方式”。如果有多个包存在风险,按风险等级排序,而不是按出现顺序。
这个子代理的价值在于把一次性的安全检查变成常规流程。以前我每隔一段时间手动跑一遍安全命令,再人工翻结果,现在只需要在对话里说一句“跑一遍依赖审计”,它就会走完整条链路。虽然它依赖外部工具返回的数据,但它把分析、汇总、建议这些步骤固化了下来,省掉了我大量重复劳动。
4.4 三个子代理的串联与分工
三个子代理单独用效果已经不错,但真正的价值在于串联。一个典型的串联流程是:我让主代理先把代码改动交给依赖审计员检查依赖安全,再交给代码评审员检查代码质量,最后把两份结果汇总后交给架构审查员评估整体影响。
在这个流程中,主代理并不是把所有结果原样丢给下一个子代理。它会提炼其中的关键信息,剔除重复内容,然后再转交。从执行效率上看,确实比我自己逐段复制粘贴要高得多。
不过串联调用也带来了新的问题:子代理之间的信息传递链路越长,信息失真就越明显。架构审查员拿到的可能是经过两层转述的结论,原始证据可能已经丢失。为了解决这个问题,我会让每一个子代理的最终结论里都保留可追溯的文件路径和行号,这样下一层子代理需要时可以去读原始文件,而不是依赖转述。
5. 用久了才会发现的四个坑
5.1 上下文断层:子代理看不到父对话的“共识”
最常见的问题,是子代理不了解主对话里已经达成的某些共识。你可能在主对话里和 Claude Code 讨论了半天,确定了“这个模块不允许引入新的全局状态”,然后你把一个子代理叫进来审查代码,它却完全不知道这条约定,开口就提出“把状态提升为全局变量”的建议。
这不是子代理笨,而是它的上下文里根本没有这段历史。解决办法是,在主代理转交任务时,把相关约定显式写进任务描述里。我也习惯在每个子代理提示词里加一句“如果没有明确的项目约定,先询问主代理,不要自行假设”。虽然这会增加一次交互,但比拿到一份跑偏的结果强得多。
5.2 描述不清晰的调用空转
子代理配置里的description是主代理选择角色的依据。如果描述写得太抽象,比如“负责代码相关的事情”,主代理会把很多不相干的任务都丢给它。结果就是子代理频繁被调用,却发现任务超出自己的能力范围,最后给你一堆“这不在我的职责内”的回复。
我调整过很多次描述,最有效的写法是包含“触发条件”和“不触发条件”。比如“当需要审查已修改代码时使用;不适用于从零编写新功能”。主代理的判断能力虽然不弱,但它在匹配子代理时是典型的快速匹配逻辑,描述越明确,调用准确率越高。
5.3 提示词过肥:什么都想管的专家最后管不好一件事
不少人在配置子代理时,会把所有能想到的规范全部写进系统提示词,希望子代理变成万能手。结果就是子代理每次都先花大量时间处理各种边缘规则,反而把核心任务挤到了后面。
我的原则是一个子代理只负责一个专业领域。代码审查子代理不要同时负责依赖安全;依赖审计子代理不要管代码风格;架构审查子代理不需要关注按钮位置。如果你真的需要很多规范,可以拆成多个子代理,让主代理分别调用,而不是在一个子代理里堆砌所有要求。
5.4 递归调用与资源消耗失控
子代理内部思路一旦奔放起来,可能会自己不断调用工具、反复读取文件,甚至形成一种类似递归的行为。尤其是你把 Bash 权限给了子代理,它可能会执行一条命令、看到结果、再执行下一条,循环往复。这在某些长任务里会显著拉高 token 消耗和耗时。
控制方法有三个。第一,给子代理的任务描述里标明输出规模上限,比如“最多输出 20 条问题”。第二,在提示词里要求子代理“读完必要文件后立即输出,不要穷举所有可能性”。第三,对工具权限做更严格的限制,把 Bash 权限从所有命令收敛到白名单命令。经过这几轮约束,子代理的耗时会变得可控,也更像一个“有分寸的专家”。
6. 子代理的边界:什么场景根本不该用
6.1 高频低难度任务
有些任务本身只需要一条命令或一个简单问题,比如“这个文件的行数是多少”“帮我重命名一个变量”。这种任务交给子代理,反而多了一步上下文创建和销毁的开销。主代理直接执行,无论是速度还是成本,都更划算。
子代理适合的是“需要独立判断、多步处理、结果需要结构化”的任务。低频高难度、有专业化流程的任务,才是它的主场。不要为了用而用,否则你得到的只是更贵的延迟。
6.2 强交互、弱流程任务
还有一些任务需要不断和你讨论才能明确方向,比如产品需求设计、交互流程规划。这种任务在子代理独立上下文里很难推进,因为子代理只能基于初始任务描述做判断,无法和你进行多轮讨论后再修正方向。至少目前,这类强交互任务用主对话更自然。
如果非要让子代理参与,我会把讨论过程放在主对话里,等方向明确了,再让子代理负责执行阶段。也就是说,子代理适合“决策之后的执行”,不适合“决策过程中的发散讨论”。
6.3 子代理与技能、工作流的配合边界
Claude Code 里还有技能、工作流、自定义命令等能力,它们与子代理有重叠,但不是一回事。技能往往封装的是固定的处理步骤,适合处理重复性流程;子代理则更偏向独立决策和判断。两者可以配合使用:子代理负责判断“该做什么”,技能负责“具体怎么做”。
我个人的习惯是:默认用主对话做自由探索,用子代理做专业判断,用技能做重复执行。三者各司其职,才是一个完整的 AI 辅助开发体系。如果只盯着子代理,把它当成万能工具,最后一定会碰到边界问题。
回到开头那个比喻。给 Claude Code 配“专家团队”,本质上是把一个全能的对话式助手,拆成一支各司其职的虚拟项目组。子代理系统的核心不是调用一次命令,而是设计一套可持续复用的角色体系。我在实战中最大的体会是,子代理配置不是写一次就结束的,它会随着项目规范、团队习惯和模型能力的变化持续演进。每过几周,我都会回头审视一遍现有子代理的描述、工具权限和输出格式,删掉不再需要的职责,补上新发现的检查点。你一开始不用追求“大而全”的团队,先从两三个最痛的角色开始,跑顺了再慢慢扩展。