别再盲目堆 Agent 了:Sub-Agent、Skills、Handoff、Router 到底怎么选?

发布时间:2026/7/21 9:02:45
别再盲目堆 Agent 了:Sub-Agent、Skills、Handoff、Router 到底怎么选? 你好我是悦创。欢迎来到 Claude Code 工程化实战的第三讲。从这一讲开始我们将进入本课程的第一个核心内容——子代理Sub-Agents。1. 为什么要有 Sub-Agents我们先从一个常见场景开启今天的内容。某天你让 Claude Code 帮你跑一个测试套件结果输出了 500 行日志然后你想让它分析一下代码结构又输出了 200 行接着你想让它改一个 bug……这时候你的对话上下文已经被各种“中间过程”塞满了真正重要的信息被淹没在茫茫的输出海洋里。其实究其根本。如果你觉得 Claude Code 越用越“健忘”并不是模型退化了而是你的对话上下文已经被一次次中间过程污染了。这正是子代理要解决的核心问题。你或许还会追问——别卖关子佳哥。到底子代理解决了什么核心问题更明确的答案是如何把“高噪声的执行过程”隔离出去只让真正有价值的结论留在主对话中。因为只有子代理才在系统层面天然拥有一个独立的上下文窗口。不是因为它“聪明”不是因为它“更强” 而是因为它是 Claude Code 里唯一一个结构上允许“执行完即丢弃”的东西。我们再进一步把问题说明清楚到底什么是“上下文污染”在前面的现象里上下文里充斥着这些内容。跑测试 → 500 行日志。搜索代码 → 200 行 grep。分析错误 → 一堆中间推理过程……这些信息有一个共同特征它们对“当下执行”是必要的但对“后续决策”是噪声。而 Claude Code 的主对话上下文是线性追加的不会自动过期默认“都当成重要记忆”。所以问题不是 Claude 突然不聪明了 而是它把临时执行数据当成了长期决策记忆。 这在工程上本来就一定会“炸”。那为什么偏偏是子代理能解决这个问题呢重点来了 ——不是 AI Agent 这个概念能解决问题而是 Sub-Agent 这种“运行模型”在起作用。子代理通过上下文隔离让专业的 Agent 做专业的事儿不是为了让 Claude 做得更多 而是为了让 Claude记得更少但记得对。PSOpenClaw 链接https://github.com/openclaw/openclaw下面我们会深入理解子代理的核心概念明白它为什么是 Claude Code 工程化使用中最重要的能力之一。理解了这些概念后面几讲的实战项目你才能得心应手。2. 什么是子代理我们可以用一句话定义它。子代理相当于一个“专职小助手”带着自己的规则、工具权限、上下文窗口去完成某一类任务然后把“结果摘要”带回来。你可以把它理解成把一个大脑拆成多个岗位角色每个岗位只做一件事并且有明确的权限边界。图中目录下设置了 3 个专门的子代理用于处理循环经济知识图谱项目。这三个代理形成了一个完整的工作流组织 PDF → 提取知识图谱 → 分析结果。不过这里还有另外一个问题就是有 Sub-Agent那肯定要先有主 AgentClaude Code 的主 Agent 在何处其实主 Agent 就是你当前操作的主对话。而主对话 vs 子代理就是老板和员工的关系。一家公司的老板主对话需要完成一个复杂的项目有两种工作方式。方式一事必躬亲亲自去调研市场输出 200 行分析、亲自写代码输出 500 行日志、亲自测试又是 300 行、亲自写文档……最后脑子里塞满了各种细节已经记不清最初的目标是什么了。方式二专人专岗安排一个市场专员去调研只需要他给你一份 1 页的报告安排一个测试工程师去跑测试只需要他告诉你结果是“通过”还是“有 3 个失败”安排一个技术文档专员去写文档……每个人带着明确的任务出去完成后只把结论带回来。子代理就是后一种方式。它让主对话保持清洁不被过程噪声污染。3. 子代理的核心价值子代理的工程价值本质上就是三件事隔离、约束、复用下面我们分别说说。隔离解决的是上下文污染问题——大量对当前执行有用、但对后续决策毫无价值的日志、搜索结果和中间推理不应该进入主对话的长期记忆子代理天然拥有独立上下文执行完即丢弃只把结论带回来让 Claude 记得更少、但记得对。这是子代理最重要的价值请看下面的示例。主对话的上下文 ┌─────────────────────────────────────────┐ │ 用户帮我分析一下这个 bug │ │ Claude好的让我看看... │ │[子代理去执行产生500行日志]│ │[子代理返回发现3个相关文件]│ │ Claude我发现问题在这三个文件... │ └─────────────────────────────────────────┘ 子代理的上下文独立的执行完就释放 ┌─────────────────────────────────────────┐ │ 任务查找 bug 相关文件 │ │[搜索输出500行日志]│ │[分析过程...]│ │ 结论3 个相关文件 │ └─────────────────────────────────────────┘主对话只看到子代理所返回的结论不需要承载 500 行的搜索过程。这意味着你的对话不会因为一次大搜索就把 token 配额用光重要的讨论内容不会被中间输出淹没Claude 在后续对话中能更好地“记住”关键信息。约束解决的是行为不可控问题——通过工具权限边界把“我希望你别这么做”变成“你物理上做不到”让代码审查只能读、修 bug 才能写角色职责不再依赖提示词自觉。子代理可以有精确的工具权限控制。# 只读型子代理代码审查tools: Read, Grep, Glob# 它只能看不能改任何东西# 开发型子代理bug 修复tools: Read, Write, Edit, Bash# 它可以读写文件和执行命令# 研究型子代理技术调研tools: Read, WebFetch, WebSearch# 它可以读本地文件和搜索网络为什么这很重要比如你让 Claude 帮你审查代码你只希望它看不希望它动手改。如果没有权限边界Claude 可能在审查过程中顺手帮你“修”了一些它认为有问题的代码——这不是你想要的行为。有了子代理你就可以创建一个 code-reviewer 角色明确规定它只有Read, Grep, Glob权限。这样它再怎么想“插手”也改不了任何东西。复用解决的是经验无法沉淀的问题——当子代理被定义成文件、放进版本控制后好的使用方式就从一次性对话变成了可共享、可迭代的工程资产。子代理的配置保存在文件中有这样几个好处。版本控制放进 git团队共享。跨项目复用好用的配置可以复制到其他项目。渐进优化根据实际使用情况不断调整 prompt持续优化改善。.claude/agents/ ├── test-runner.md# 测试运行专员├── code-reviewer.md# 代码审查专员├── log-analyzer.md# 日志分析专员└── bug-fixer.md# Bug 修复专员这些配置文件就像公司里的“岗位说明书”每个岗位职责清晰、权限明确。这三点分别对应着三个经典的软件工程命题内存管理、安全边界、组织效率。这三点合在一起标志着 Claude Code 的使用方式从“对话技巧”正式跨入“工程系统”。4. 内置子代理开箱即用的“好员工”你可能已经在使用子代理只是没意识到而已。Claude Code 内置了一系列子代理以后也许会有更多当你问 Claude——“给我解释解释这个 Github 代码库”时在不知不觉间Claude Code 就会自动调用内置子代理。下面简单介绍其中的三个。4.1 Explore 子代理Explore 子代理负责“翻项目、找位置”专注快速只读搜索把成百上千行 grep 和分析过程吞进去只告诉你结论在哪里。┌─────────────────────────────────────────────────────────┐ │ Explore探索者 │ ├─────────────────────────────────────────────────────────┤ │ 特点快速、只读 │ │ 用途搜索和分析代码库 │ │ 模式quick / medium / very thorough 三档 │ │ 工具Read, Grep, Glob不能写 │ └─────────────────────────────────────────────────────────┘当你问 Claude“这个项目的认证逻辑在哪里”时它会自动派出 Explore 子代理去搜索而不是在主对话中一行行地执行 grep 命令。4.2 Plan 子代理Plan 子代理负责“动手前先想清楚”在真正修改代码之前收集上下文、梳理依赖、生成实施路径避免一上来就盲目修改。┌─────────────────────────────────────────────────────────┐ │ Plan规划者 │ ├─────────────────────────────────────────────────────────┤ │ 特点规划模式专用 │ │ 用途在制定实施计划前收集项目上下文 │ │ 限制子代理不能再生成子代理防止无限嵌套 │ └─────────────────────────────────────────────────────────┘当你让 Claude 进入规划模式时它会用 Plan 子代理来收集信息设计实施方案。4.3 General-purpose 子代理General-purpose 子代理则是“能探索、能修改、能推进”的全能型员工适合需要多步骤协作的复杂任务。┌─────────────────────────────────────────────────────────┐ │ General-purpose通用型 │ ├─────────────────────────────────────────────────────────┤ │ 特点全能型处理复杂多步骤任务 │ │ 用途同时需要探索和修改的任务 │ │ 工具完整工具集 │ └─────────────────────────────────────────────────────────┘当任务比较复杂需要多种能力配合时就可以使用这个通用型子代理。这些子代理的共同点只有一个把高噪声过程留在子代理里让主对话只保留决策信息。5. 什么时候该用子代理需要提醒你的是并不是所有任务都值得动用子代理。子代理的价值不在于“能不能用”而在于“该不该用”。一个最直观的判断标准是主对话到底需不需要承载执行过程本身。第一类非常适合用子代理的是高噪声输出的任务。这类任务的共同特点是执行过程中会产生大量中间信息但主对话真正关心的往往只有一个结论。例如跑一次测试会输出几百行日志但你只想知道通过还是失败扫描日志和错误栈时真正有价值的可能只是一两条关键错误在整个代码库里做搜索最终只需要知道相关文件在哪里生成一份长报告主对话只需要摘要。这些场景中执行过程本身就是噪声用子代理把过程隔离起来只把结论带回来是最自然、也最干净的做法。第二类适合用子代理的是角色边界必须非常明确的任务。有些事情你只希望 Claude “看”而不希望它“动手”有些操作只能在特定目录、特定范围内发生还有一些敏感操作本身就需要和其他任务隔离开来。如果没有子代理这些约束只能靠提示词和使用者的心理预期维持。而一旦通过子代理定义工具权限边界就从不稳定的“希望如此”变成了明确的“系统级约束”。没有写权限就无法修改文件没有执行权限就无法运行命令。正因为边界被落实为能力边界而不是行为约定子代理才成为解决安全性和可控性问题的可靠手段。第三类适合用子代理的是可以并行展开的研究型任务。当你需要同时调研认证逻辑、数据库设计和 API 接口或者对比几种技术方案、从多个视角分析同一个问题时这些探索之间往往是相互独立的。与其在主对话里来回切换不如让多个子代理各自去完成自己的探索再把结果汇总回来。子代理在这里的价值不只是隔离上下文更是天然的并行加速器。第四类适合用子代理的是可以拆成清晰阶段的流水线式任务。比如先定位代码位置再做代码审查然后进行修改最后跑测试验证。Explore找位置 ↓ Reviewer指出问题 ↓ Fixer修复 ↓ Test-runner验证这类任务的关键在于每一个阶段的目标、权限和输出都是明确的。用子代理把每一段责任固定下来不但让流程更清晰也让每一步的上下文更加干净。这不是为了复杂化流程而是为了避免不同阶段的信息互相污染。当然也有一些情况并不适合使用子代理。如果任务需要频繁来回确认需求、不断调整方向那子代理这种“派出去干活再回来汇报”的模式反而会拖慢节奏如果任务的各个阶段高度耦合每一步都强依赖上一阶段的详细过程那强行隔离上下文只会增加认知负担还有非常简单的小任务启动子代理本身就有开销直接在主对话中完成反而更高效。6. 一条关键约束子代理不能生成子代理请注意一条很容易被忽略但影响深远的架构限制——子代理不能再嵌套调用子代理。也就是说你的 code-reviewer 子代理不能在执行过程中再派出一个 security-scanner 子代理。这意味着什么所有编排必须由主对话完成如果你需要“先审查再修复”必须由主对话依次调用两个子代理而不是让第一个子代理去调用第二个流水线的“调度中心”只有一个就是主对话本身后续第 6 讲会深入讨论这一点如果需要在子代理内复用知识用 skills 字段预加载而非再嵌套一个子代理后面配置详解中我们会讲到。理解这条约束你就不会在设计复杂工作流时走弯路。7. 子代理配置文件详解好讲到这里相信你已经对为什么我们需要子代理有了清晰的理解。下面直接进入实操环节看看如何创建子代理的配置文件。首先我们看看子代理的配置文件格式可以参考我的 Github Repo 中的 03-SubAgents 各个项目中的子代理示例。子代理使用Markdown YAML frontmatter格式--- name: code-reviewer description: Review codeforsecurity issues and best practices. Use after code changes. tools: Read, Grep, Glob model: sonnet --- 你是一个代码审查专家。 当被调用时1. 首先理解代码变更的范围2. 检查安全问题3. 检查代码规范4. 提供改进建议 输出格式## 审查结果- 安全问题[列表]- 规范问题[列表]- 建议[列表]frontmatter 部分---之间定义子代理的元数据和配置下方的 Markdown 正文就是子代理的系统提示词system prompt。子代理只会收到这段系统提示词和基本环境信息如工作目录不会继承主对话的完整系统提示词。上述文件中出现的以及未出现的 frontmatter 字段详解如下。其中name和description是必填字段其余均为可选下面对几个关键字段做重点说明。7.1 description 的设计艺术description字段决定了 Claude何时自动调用你的子代理——这是配置中最重要的设计决策。# 写的太模糊Claude 不知道什么时候该用它description: A code reviewer# 好的 description说明做什么 什么时候用description: Review code changesforquality, security vulnerabilities, and best practices. Use proactively after code is modified or when user asksforcode review.优点说明了做什么审查代码质量、安全、规范和什么时候用代码修改后或用户请求时。“Proactively” 这个关键词会鼓励 Claude 在合适的时机主动委派任务。7.2 tools vs disallowedTools白名单与黑名单控制子代理能使用哪些工具有两种方式# 方式一白名单 (tools) — 只能用这些# 适合需要严格限制的场景如只读审查tools: Read, Grep, Glob# 方式二黑名单 (disallowedTools) — “继承所有但排除这些”# 适合需要大部分工具但排除少数危险工具的场景disallowedTools: Write, Edit两者的选择取决于你想要的表达方式如果子代理只需要少数几个工具用白名单更清晰如果子代理需要大部分工具但排除个别用黑名单更简洁。不要同时使用两者——选一种即可。工具权限应遵循最小权限原则——只开放必要的工具能用 Read 完成的任务就不要给 Edit。以下是根据用途划分的典型工具组合只读型审计/检查 研究型信息收集 开发型读写改 ├── Read ├── Read ├── Read ├── Grep ├── Grep ├── Write └── Glob ├── Glob ├── Edit ├── WebFetch ├── Bash └── WebSearch ├── Glob └── Grep7.3 model模型选择与默认值7.4 permissionMode权限模式permissionMode控制子代理在执行过程中遇到需要权限的操作时如何处理。子代理会继承主对话的权限上下文但可以通过此字段覆盖行为举个例子如果你希望子代理能跑git diff但绝不能修改文件可以这样配置--- name: code-reviewer tools: Read, Grep, Glob, Bash permissionMode: plan# 强制只读模式即使有 Bash 也无法写入---这比单纯依赖 prompt 约束更可靠——permissionMode: plan是系统级的只读保障。7.5 skills为子代理预加载知识skills字段允许你在子代理启动时把指定 Skill 的完整内容注入到子代理的上下文中。这意味着子代理不需要在执行过程中发现和加载 Skill——知识已经在它的脑子里了。--- name: impact-analyzer description: Analyze impact scope of code changes on the full call chain. tools: Read, Grep, Glob, Bash skills: - chain-knowledge# 链路拓扑和 SLA 约束- recent-incidents# 近期事故记录---子代理不会自动继承主对话中可用的 Skill。如果你希望子代理拥有某个 Skill 的知识必须在这里显式列出。这个机制在后续讲解中会结合实战案例深入展开。7.6 hooks子代理专属的生命周期 Hook子代理可以在自己的 frontmatter 中定义 Hook——这些 Hook只在该子代理运行期间生效子代理结束后自动清理。--- name: db-reader description: Execute read-only database queries. tools: Bash hooks: PreToolUse: - matcher:Bashhooks: - type:commandcommand:./scripts/validate-readonly-query.sh---上面的例子中db-reader虽然拥有 Bash 工具但每次执行 Bash 命令前都会被 Hook 拦截验证——只有 SELECT 查询能通过INSERT/UPDATE/DELETE 等写操作会被阻止。这比不给 Bash 工具更灵活允许读操作又比无约束的 Bash 更安全。Hook 的详细机制我们会在后续 Hook 专题课程中展开。这里先建立概念子代理不仅可以控制有哪些工具还可以控制工具能做什么操作。8. 子代理的存放位置与优先级子代理可以被设置为不同的作用域。当多个作用域存在同名子代理时高优先级的会覆盖低优先级的。子代理可以被设置为项目级或用户级项目级仅当前项目可用存放位置如下所示适合项目特有的角色比如针对特定框架的测试运行器your-project/ └── .claude/ └── agents/ ├── test-runner.md └── code-reviewer.md用户级所有项目可用子代理适合通用角色比如日志分析器、通用代码审查器。~/.claude/ └── agents/ ├── general-reviewer.md └── log-analyzer.md9. 创建子代理的三种方式弄清了子代理配置文件的格式和位置就可以创建子代理了。有三种创建方式我们分别来看看。方式一交互式创建推荐新手使用。在 Claude Code 中输入/agents按照向导操作步骤1输入 /agents 步骤2选择Create new agent步骤3选择存放位置User-level 或 Project-level 步骤4选择Generate with Claude并描述功能 步骤5选择需要的工具 步骤6选择模型 步骤7保存这种方式简单直观Claude 会帮你生成初始的 prompt。方式二手写配置文件直接创建.claude/agents/your-agent.md文件。其优势是更精细的控制方便版本管理可以从其他项目复制。方式三CLI 参数临时创建通过--agents参数可以在启动 Claude Code 时传入 JSON 格式的子代理定义。这种方式创建的子代理仅在当前会话中存在不会保存到磁盘。这种方式特别适合 CI/CD 自动化时在流水线中临时创建任务专用的子代理。10. 子代理的运行模式子代理不只是“派出去等回来”这么简单。了解它的运行模式能让你更高效地使用。子代理可以在前台或后台运行。Claude 会根据任务自动选择前台或后台。你也可以手动控制。对 Claude 说 “run this in the background”正在运行的前台子代理可以按 CtrlB 切换到后台启动前Claude Code 会预先请求子代理可能需要的所有权限——因为后台运行时无法弹出交互式确认。如果后台子代理因权限不足而失败你可以恢复它到前台重试。每个子代理执行完成后Claude 会自动收到它的agent ID。如果你需要在之前的子代理基础上继续工作可以让 Claude 恢复Resume它用 code-reviewer 子代理审查认证模块[子代理完成]继续刚才的审查再看一下授权逻辑[Claude 恢复之前的子代理保留完整上下文]恢复的子代理会保留所有之前的对话历史——它从上次停下的地方继续而不是重新开始。这对于需要多轮迭代的长任务非常有用。11. 本讲小结子代理的核心工程化能力归结起来是四件事。隔离让主对话保持清洁避免执行噪声污染上下文。约束通过工具权限把角色边界变成系统规则。复用把一次好用的经验沉淀为可版本化的配置。并行让原本串行的复杂任务可以同时推进。在配置层面真正重要的字段也只有几个name用来标识角色description决定何时被调用也是最关键的设计点tools划定权限边界model则是在性能与成本之间做权衡。至于什么时候该用子代理可以用一句话判断当任务存在高噪声输出、需要明确权限边界、可以并行推进或能够拆成清晰阶段时用子代理当任务需要频繁来回讨论和即时调整时就不要用。记住上面的几句话你就理解了子代理的全部精髓。12. 思考题如果要设计一个“数据库查询分析器”子代理你会给它配置哪些工具为什么在团队协作中子代理配置应该放在项目级还是用户级各有什么优缺点回顾本讲介绍的permissionMode字段。如果你要创建一个“自动化修复”子代理允许它自主修改文件而不需要每次都弹窗确认你会选择哪种权限模式这样做的风险是什么你会配合哪些其他字段来降低风险13. 下一讲预告下一讲我们将进入实战环节创建一个只读型代码审查子代理。你将亲手配置一个只能“看”不能“改”的安全审计角色体验权限边界的工程价值。欢迎你在留言区和我交流讨论。如果这一讲对你有启发别忘了分享给身边更多朋友。