前两周我接手一个老模块的拆分改造,主会话一口气干三件事:拆代码、写测试、做代码审查。刚开始还好,大概聊到第五六轮就开始出问题了——它反复去翻前面已经看过的文件,又一次次确认同一个路径,上下文越滚越大,改到一半甚至忘了自己拆到哪一行。我后来把任务全部抽出来,丢给 C 工具里新加的 SubAgent 去并行做,整体体验完全不一样。SubAgent 说白了就是主会话能按需派发出去的专用小代理,每个都有独立上下文和明确任务边界,干完活再把结论交回主线。这篇文章把我实际试出来的配置方式、踩过的坑以及几条典型工作流都整理出来,适合所有被超长会话和串行执行折磨过的人。
1. SubAgent 到底是什么,为什么值得用
1.1 一个真实的翻车现场
先说那个让我下定决心研究 SubAgent 的项目。某个内部系统里有个历史遗留模块,一个文件两千多行,里面还混着路由、数据库查询、业务状态机和一部分渲染逻辑。我当时让主 Agent 直接拆分,它的工作方式是把整个文件读进上下文,然后开始规划怎么拆。但问题是,拆完 A 段,它又要回头再读一遍这个文件确认上下文;拆到 B 段,又要确认依赖关系。会话进行到一半,上下文里的无关内容越来越多,它开始表现得很奇怪——上一轮刚确认过的函数签名,下一轮又去文件里 grep 一遍。
于是 token 消耗像流水一样,而且每轮回复的等待时间也越来越长。最难受的是,它偶尔会在一份“已经废弃的实现”上给出改动建议,等我盯着屏幕发现不对,它已经改完了。后来我想明白了:这不是模型能力不行,而是任务结构出了问题。一个大脑同时管所有子任务,还要全程记住每一个细节,必然顾此失彼。这个问题的解法不是让主 Agent 更聪明,而是让主 Agent 学会“派活”。
1.2 它解决的不只是“快”
SubAgent 的核心机制,是在主会话之外创建多个一次性小代理。主 Agent 自己保持轻量,只负责理解全局目标、拆解任务、汇总结果和做最终决策。真正读文件、搜代码、写草稿、生成报告这些活,交给 SubAgent 去干。
每个 SubAgent 拥有独立的上下文窗口,这意味着它在处理任务时不需要知道主会话之前聊了多久。它把任务范围内的文件读一遍,基于自己的指令完成分析,最后输出一段结构化结论。主 Agent 只接收这个结论,不会把 SubAgent 读过的大段代码全部塞回自己的上下文。
这就像项目里来了一个很资深的同事,你把“整理一下某模块的调用关系”这种需求丢给他,他交回一份完整的文档,而你不需要记住他排查过程中看过的五十个文件。多个这样的“同事”还能同时开工,因为彼此的思考过程相互隔离。
我试下来,它解决的核心矛盾是“长会话状态污染”。只要主会话不长到爆炸,主 Agent 的判断力就一直在线。所谓“快”,只是上下文隔离带来的副产品。
1.3 和普通 Agent 模式的核心差异
很多刚接触的人分不清普通 Agent 模式和 SubAgent 的区别。我整理了一个对比表格,方便你直观理解。
| 维度 | 主 Agent 模式 | SubAgent |
|---|---|---|
| 上下文窗口 | 全会话共享,越聊越大 | 每个任务独立,任务结束即释放 |
| 工具权限 | 一般拥有全部可用工具 | 可以在定义时限定只读或指定目录 |
| 并发能力 | 串行处理,只能一步一步来 | 可以根据工具支持,多个同时运行 |
| 输出粒度 | 完整对话,包含大量过程信息 | 只回传结论或结构化报告 |
| 典型任务 | 全局架构设计、最终决策、落地改动 | 代码审查、测试生成、文件探索、局部重构 |
| 成本特性 | 上下文膨胀导致费用攀升 | 单个任务成本可控,适合重复执行 |
这个对比告诉我一个判断标准:凡是“输入输出边界清晰、验收标准能写清楚”的任务,都适合扔给 SubAgent;凡是需要把握全局一致性、涉及多个模块架构调整的决策,必须留在主 Agent 手里。如果你把一个跨二十个文件的架构重构任务直接甩给 SubAgent,它很可能只盯着一个角落猛干,最后还是要你返工。
2. 开启 SubAgent 前需要做的事
2.1 检查版本与入口
SubAgent 功能不同版本的入口差异比较大,我手上这个正式版是在设置面板的 Agent 相关选项里多了一个“子代理”配置区,同时在项目根目录里可以通过配置文件来定义自己的 SubAgent。
建议你先做两个检查:第一,确认自己用的版本支持 Agent 模式;第二,在设置里找到 Agent 面板,看看有没有“SubAgent / 子代理 / Worker”这类栏目。不同版本可能叫法不同,但思路都是同一个——主 Agent 之外的轻量任务执行体。
配置方面通常有两种做法。一种是图形界面里直接点“新建 Agent”,然后填名称、描述和提示词。另一种是在项目目录里维护一组 Markdown 文件,每个文件对应一个 SubAgent。我倾向用文件方式,因为可以放进版本管理,团队其他人拉下来就能用,而且修改记录一目了然。
如果找不到入口,大概率是版本问题。不建议为此折腾,去找一下当前版本的更新说明,一般都会写新增了什么。
2.2 定义你的第一个 SubAgent
我建议新手从“代码审查”这个场景开始练手,因为它是只读操作,风险最小。我用的一个最小示例长这样:
--- name: code-reviewer description: 对整个项目或指定目录做静态审查,输出分级问题清单。适合在提交前自查、验收代码时调用。 model: balanced tools: - fs:read - fs:grep - fs:list instructions: | 你是一个团队里的资深代码审查员。 任务边界: - 只做检查,不要直接修改任何文件。 - 优先检查:逻辑正确性、边界条件、异常处理、命名清晰度。 - 禁止对业务功能做主观猜测,必须以代码里的实际实现为准。 输出格式: 使用 Markdown 表格输出,列包括: 严重级别(P0/P1/P2)、文件位置、问题说明、修改建议。 如果没发现问题,输出“未发现明确问题”。这个文件放在项目根目录下的agents文件夹里,文件名就是 SubAgent 的名字。字段含义我逐个说一下:
name:内部标识,最好用短横线连接的小写英文,方便在主会话里引用。description:给主 Agent 看的说明,描述这个 SubAgent 适合干什么、什么时候应该被唤起。这里的文字决定了主 Agent 能不能在合适的时机主动调用它。model:指定运行这个 SubAgent 时用的模型档位。我常用balanced,兼顾效果和速度。tools:工具白名单。只做分析就给读和搜的权限,绝不放开写权限。instructions:最关键的部分,所有任务指令都写在这里。
写完保存后,在主会话里直接说“让 code-reviewer 扫一遍 src/core 目录”,主 Agent 就会根据描述自动匹配并派发任务。
2.3 命名、描述、指令书写的三条经验
第一次写 SubAgent 定义的时候,我犯了几个很蠢的错,后来总结成三条经验。
第一,命名用“动词+对象”,别起那种只有自己看得懂的名字。比如split-module、test-writer、doc-generator,一眼就知道这个 Agent 是干嘛的。我之前起过一个叫alpha的,结果自己过两天都忘了它是干什么用的,主 Agent 匹配的时候更是抓瞎。
第二,description里要写清楚“触发场景”。不要写“一个代码助手”这种废话,而要写“当需要批量生成单元测试、或需要为某个模块补充测试覆盖时,调用 test-writer”。描述写得越具体,主 Agent 越能在正确的时候想到用它。
第三,instructions里必须同时写“要做什么”和“不要做什么”。比如审查类 Agent,一定要写“禁止直接修改文件”;重构类 Agent,要写“禁止改动公共 API 签名”。SubAgent 的执行边界就是靠这些硬约束划定出来的。
还有一个小技巧:在指令末尾要求 SubAgent 以固定格式输出,比如“必须输出 Markdown 表格”或“必须包含文件路径和行号”。主 Agent 拿回来的是结构化结果,后续处理效率会高很多。
3. 常用工作流实操:从重构到代码审查
3.1 场景一:大规模重构
重构是最能体现 SubAgent 价值的一个场景,也是最容易翻车的场景。我现在的做法分五步。
第一步,主 Agent 先做代码地图梳理,搞清楚要拆的模块有哪些入口、依赖了哪些外部文件。这一步不能偷懒,全局认知必须留在主线。第二步,制定拆分策略。第三步,派发多个 SubAgent 并行干活,每个负责拆一个子模块。比如我有三个子模块要拆,就定义三个任务描述,让split-module各跑一份。每个 SubAgent 的 instructions 里要写清楚:目标目录、要拆的内容边界、输出格式。第四步,SubAgent 只负责产出拆分方案和新代码草稿,不直接对原文件落地。第五步,主 Agent 汇总所有结果,检查接口一致性,再统一执行最终修改。
我试过一次真实拆分,三个 SubAgent 同时跑,主会话基本没膨胀。主 Agent 全程只做两件事:看结果、做决策。对比之前一个 Agent 从头忙到尾的做法,改错文件的概率明显下降。
这里有一个关键心得:拆分子任务时,必须保证每个 SubAgent 负责的文件集合互不重叠。一旦两个 Agent 同时盯上同一个文件,后面大概率要处理冲突,反而不如串行。
3.2 场景二:自动化代码审查
代码审查是我最推荐的 SubAgent 入门场景,没有之一。因为它只读不写,出不了大乱子。
我给reviewer定义了非常严格的输出格式,要求它把问题按严重级别分级。实际跑下来,它能在几十秒内扫完一个模块,输出一个问题表格。主 Agent 拿到表之后,只挑 P0 和 P1 级别的问题继续追问即可,P2 的命名问题可以攒批一起处理。
这里要特别提醒:不要让 SubAgent 直接修它发现的问题。比如它发现某个函数处理不了空指针,如果它自己动手改,很可能只改了这一处,却没检查其他调用方。正确做法是让它只输出问题和建议,由主 Agent 或人来决定要不要改、在哪里改。我见过有人图省事把修复权限全部放开,结果 SubAgent 按自己的理解改了三个文件,把公共函数的返回类型都动没了,编译直接挂掉。
审查类的 Agent 我还喜欢加一条指令:“如果没有明确把握的问题,不要硬编”。因为它不是人,不会承认自己没看懂,反而可能把正常代码当问题报出来。加了这条之后,误报率低很多。
3.3 场景三:测试用例批量生成
写测试是重复性极高的劳动,非常适合交给 SubAgent,但有一点必须强调:测试 Agent 只能读被测代码和已有测试风格,不能修改生产代码。我的test-writer指令里明确写了三条:只读src与tests两个目录;按现有测试框架的写法生成用例;输出用例代码而不是直接写入文件。
实际操作中,我会先让它读一个模块入口和现有测试文件,然后输出一批测试用例。主 Agent 拿到之后先做一次快速审查,再写入测试文件运行。如果跑挂了,就把报错信息扔回给 SubAgent 让它修正,而不是重新生成全部用例。
这样做的效率比我手工写高很多,但我要提醒一句:SubAgent 生成的测试容易“只测自己会写的”。比如一个函数有三个分支,它可能只覆盖一两个。所以主 Agent 在接收测试用例时,最好额外追问一句“这些用例覆盖了所有分支吗,有没有遗漏的条件判断”。别完全信任它自带的覆盖报告,还是要抽一眼。
3.4 场景四:多文件探索与文档生成
SubAgent 还有一个被低估的用途:快速探索代码库并生成文档。比如一个接口模块,我需要一份调用说明,过去得自己逐个文件看。现在我给doc-generator派任务,让它读某个目录下的所有入口文件,输出接口清单:函数名、参数、返回值、调用示例、依赖关系。
它返回的文档格式结构清晰,可以直接放进项目 wiki。我只需要让主 Agent 抽查几个函数签名是否属实,不用从头到尾逐行核对。
这个场景特别适合处理那种“遗留代码没人敢碰”的模块。让 SubAgent 先出一份地图,人再决定从哪下手。使用过程中我学到一个教训:文档 Agent 默认会基于自己的“推测”补全调用示例。如果代码里没有示例,它会编一个看似合理的出来。所以指令里一定要写“所有例子必须来自代码中的实际调用,不得自己构造”。凡是从代码里找不到的调用链,要么如实标注未知,要么输出为空。
4. 上下文、成本与并发控制
4.1 为什么能省 token
很多人以为 SubAgent 就是多开了几个会话,总成本肯定更高。实际上,在长任务场景下它反而更省。原因在于上下文是关键开销,而 SubAgent 能大幅压缩主会话的 token 占用。
拿一个拆模块的任务来说。传统做法里,主 Agent 为了不断修改同一个文件,需要反复把该文件的内容留存在上下文中。如果一个文件 1000 行,那它在上下文里可能占几千甚至上万 token,而且从头到尾一直占着。改造二十个文件,就是二十份文件的持续占用。SubAgent 做法完全不同:每个 SubAgent 只读取分配给它的那部分文件,跑完任务后,上下文直接释放。最终回传给主 Agent 的,只有一份结果摘要,可能几百 token。
省 token 的本质,是用“小而专的一次性上下文”取代“大而全的持续上下文”。我对同一个重构任务做过对比。旧方式主会话跑了约一万多 token 的核心对话,加上反复重读文件,总消耗很快冲上去;新方式三个 SubAgent 并行,主会话几乎没增加多少新的上下文。至于总价格,取决于你给 SubAgent 配的模型档位,但普遍比之前硬顶长会话便宜。
我个人的体感是:短任务、单文件改动,没必要用 SubAgent;只要任务涉及多文件、长链路,SubAgent 就是省钱利器。
4.2 并发和模型档位怎么设
这里给出一个建议配置:主 Agent 用最高档模型,负责规划和决策;SubAgent 用balanced或更轻的档位,负责执行具体任务。我很少让 SubAgent 用最高档模型,因为它们的任务相对单一,用中等档位性价比最好。
并发数量上,我的建议比较保守:新手阶段一次不要超过两个,等熟悉了再上到三四个。原因有三个:第一,同一时刻多个写操作容易冲突;第二,并发越多,主 Agent 汇总结果时的上下文压力越大;第三,如果工作区里还有人在改代码,并行写操作会让 git 状态变得很乱。
关于每个 SubAgent 的上下文上限,我也建议按需设置。纯文件探索类的,给个小窗口就够;代码审查类的,稍微大一点。没必要让每个 SubAgent 都撑满窗口,那样成本跟长会话没什么区别。
| 建议设置项 | 推荐配置 |
|---|---|
| 主 Agent 模型 | 最高档,负责架构决策 |
| SubAgent 模型 | balanced 或轻量档 |
| 首次使用并发数 | 1 到 2 |
| 熟练后并发数 | 3 到 4,看任务边界 |
| SubAgent 上下文 | 按任务大小设置,够用即可 |
4.3 实测数据对比
我自己拿一个 Demo 项目测过一次:一个两千行的老模块,拆成三个独立子模块。旧方式让主 Agent 全程做,从规划到执行一共耗时大约一刻钟,中间还因为上下文太长回退过一次,token 消耗很高。新方式下,我派了三个 SubAgent 并行拆,每个只读自己那部分文件,大概五分钟左右就全部返回了。主 Agent 再用几分钟统一审查和应用改动,总时间不到十分钟,token 消耗省了大概三四成。
不同项目和不同模型档位差异会很大,我不建议把这个结果当成绝对指标。但有一点是可以放心的:任务拆得越干净,SubAgent 的收益越明显。如果任务之间强耦合,硬拆只会增加沟通成本,节省就不明显了。
5. 常见问题与排查指南
5.1 两个 SubAgent 同时改一个文件
这是我踩过最大的坑。当时我同时派了两个 SubAgent 去优化同一个模块,一个改接口,一个改内部实现。前者把函数签名改掉了,后者还在按旧签名写实现,回来之后代码直接编译失败。
排查方法很简单:看 SubAgent 的调用日志和 git diff,基本一眼能定位到是哪个 Agent 动了哪些文件。不过更重要的是预防。我现在会在任务拆解时就约定好:每个 SubAgent 的写权限限定在特定目录;如果两个 Agent 不可避免要碰同一个文件,就让它们先返回改动计划,由主 Agent 统一整合后再落地。或者更干脆一点,写操作类任务串行执行,只读类任务才并行。
5.2 结果被截断
SubAgent 的输出长度也有限制。有一次我让它分析一个模块的所有可能异常路径,它写到一半内容就断了,看起来像是逻辑说到一半就停止了。原因是结果超过输出上限,而不是它不想答。
解决方法有两种。一种是缩短任务范围,让它只分析某一个函数,而不是整个模块;另一种是让 SubAgent 把完整报告写入一个临时文件,然后只返回文件路径。我后来常用后者,尤其是在文档生成和审查场景。具体做法是在 instructions 里写一句:“如果输出内容较长,将完整内容写入.workspace/reports/xxx.md,然后在回复中只返回文件路径和关键结论。”这比硬撑输出上限稳定得多。记得把临时目录加进 .gitignore,别把一堆内部报告提交到仓库里。
5.3 工作区权限与乱探索
SubAgent 默认能访问项目目录里的文件,但它有时会“自作主张”去看无关目录。比如让它审查src/core,它却把tests和docs也翻了一遍,既浪费时间,还可能输出不相关的内容。
所以定义 Agent 时,我建议在指令里明确“只能访问哪些路径,不要碰哪些路径”。特别要提醒的是,不要让 SubAgent 去读环境变量文件、密钥文件这类的敏感配置。不光是安全问题,读了这些文件后它还可能把里面的值拼进代码里,造成隐患。工具白名单里把fs:list和fs:read的范围收窄,能有效避免这类乱跑。
5.4 找不到 Agent / 命令不生效
有时候你在会话里喊 SubAgent 的名字,它却不响应,或者直接说找不到。可能是这些原因:
- 配置文件没放在正确目录,它不是自动识别的。
- front matter 字段写错了,比如
instruction拼错成instruction,少了 s。 - 主 Agent 的上下文里还没有索引到新文件。可以直接提醒它“读一下 agents 目录下有哪些 agent”,或者重新开一个会话再试。
- 描述里的关键词太泛,主 Agent 没法把当前任务和这个 SubAgent 关联起来。多写几个触发词,像“测试”“覆盖率”“单元测试”这种,匹配率会高很多。
我在排这类问题时,习惯先看一眼 Agent 定义文件有没有被正确识别,再在主会话里用一句话复述它的描述:“当任务涉及 XX 时,你应该调用 XX agent”。通常这一句就能让它回到正确轨道。
6. 我的几点补充经验
用了这段时间,我最深的体会是:SubAgent 不是越多越好,关键是任务拆解的质量。拆得好,效率翻倍;拆得稀烂,并发越多越乱。我给自己定了一条规矩:核心架构决策和最终的结果整合,永远留在主会话里;脏活、累活、重复活,才去派 SubAgent。
另一个经验是,新功能上来之后别急着全盘采用。我建议从两个固定场景开始跑:代码审查和测试生成。这两个都是只读或低风险场景,跑顺手了,再逐步扩展到重构、文档生成、跨模块探索。等你对“指令该怎么写、边界该怎么定”有了感觉,自然就知道哪些任务适合并行、哪些任务必须串行。
最后分享一个压箱底的小技巧:给写操作相关的 SubAgent 都加一个“先计划,后执行”的开关。也就是在指令里要求它先输出详细改动方案和涉及的文件列表,交给主 Agent 审一遍,主 Agent 明确说“可以执行”,它才动手写代码。一次额外确认,能挡掉大半灾难性改动。我试过跳过这步直接放开写权限,结果 SubAgent 把整个模块按自己的想法重构了,风格倒是挺统一,但不是我要的方向。从那以后,我对所有写操作类 SubAgent,一律保留这道人工闸门。