Subagents 完全拆解:description 字段、工具权限隔离与 Fork 的正确用法

Subagents 完全拆解:description 字段、工具权限隔离与 Fork 的正确用法

Claude Code Subagents 的调度权由 description 字段掌控——写法不对,自定义代理就不会被主动使用。本文完整拆解五个内置代理的分工与成本差异、description 字段的调度机制与写法对比、tools/disallowedTools 工具权限隔离的正确姿势、Fork 与普通 subagent 的本质区别,以及后台权限预授权、嵌套限制等常见坑,附三个可直接使用的生产级配置。

Claude Code 高级用法精读
2026/5/25 · 8:09
購読 1 件 · コンテンツ 5 件

リサーチノート

Claude Code 的 Subagents 系统初看像个进阶特性,用起来却发现:内置代理一直在跑,自定义代理也不难配——但让它按你想要的方式调度,才是真正的门槛所在。
本文完整拆解 Subagents 的工作机制,从 description 字段怎么写才能让 Claude 主动委托任务,到 tools/disallowedTools 如何做工具隔离,再到 Fork 模式与普通 subagent 的本质区别,以及最容易踩的几个坑。

为什么需要 Subagents

长会话里上下文窗口会积累大量「噪声」:4000 行 grep 输出、十几轮错误分支、反复读取的大文件——这些内容在任务完成后对主线推理毫无价值,却始终占着 token 配额1
Subagents 解决的是这个问题:把产生高噪声的子任务(代码库探索、跑测试、文档查询)委托给一个独立的代理,它在自己的上下文窗口里完成工作,结束后只把结论返回主会话。主会话看到的是摘要,不是过程。
这个机制的副产品同样有价值:子代理的任务范围窄、工具集少、系统提示更短,行为更稳定,成本更可控。Haiku 足够处理的搜索任务,不需要拉 Opus。2

内置代理:一直在跑,但你可能没注意

Claude Code 开箱自带五个子代理,大多数开发者只见过 Explore 和 Plan:
代理模型工具权限触发时机
ExploreHaiku只读Claude 需要搜索或分析代码库但不修改时
Plan继承主会话只读Plan 模式下的前置研究
general-purpose继承主会话全工具复杂多步任务、无法匹配专用代理时兜底
statusline-setupSonnet受限运行 /statusline
claude-code-guideHaiku受限询问 Claude Code 自身功能时
Explore 和 Plan 有一个特殊的设计决策:它们跳过 CLAUDE.md 和 git 状态。目的是让轻量探索保持低延迟、低成本——主会话拿到结果后仍然有完整的 CLAUDE.md 上下文。如果某条规则必须让 Explore 看到(比如「忽略 vendor/ 目录」),需要在委托任务时的 prompt 里重新声明。2
general-purpose 是所有内置代理里成本最高的:它继承主会话的模型,且会复制整份上下文启动。把一个只需要只读搜索的任务路由到 general-purpose,等于用 Opus 做了 Haiku 的活。
リンクプレビューを読み込んでいます…

description 字段:调度系统的唯一入口

自定义 subagent 配置文件的骨架如下:
---
name: code-reviewer

tools: Read, Grep, Glob
model: sonnet
---
You are a code reviewer. Analyze the code and provide specific, actionable feedback on quality, security, and best practices.
description 是调度层,YAML 正文是系统提示层。两者职责不同。
Claude 用 description 决定是否委托,不是用系统提示。当你的请求触发任务分配时,Claude 把任务描述和所有可用子代理的 description 做语义匹配,命中的代理获得委托。系统提示是子代理拿到任务后的行为规范,调度阶段根本读不到它。
description 写得差,子代理就不会被自动调用。社区里有两个写法技巧:
  • 加入 use proactivelyMUST BE USED,明确告知 Claude 应在什么条件下主动委托3
  • Use this agent when... 开头,描述触发场景而非代理能力
一个具体对比:
# 弱描述(不易触发自动委托)
Reviews code changes.

# 强描述(能稳定触发自动委托)
Expert code review specialist. Use proactively after writing or modifying any code.
Reviews for quality, security, and maintainability, then provides structured feedback by priority.
两者的差别不在系统提示层,在调度层。

工具权限隔离:不是「限制」,是「专注度」

Subagents 有两个字段控制工具访问:
# 白名单:只允许这些工具
tools: Read, Grep, Glob, Bash

# 黑名单:继承全部工具,排除这些
disallowedTools: Write, Edit
同时配置时,先应用 disallowedTools,再从剩余工具里解析 tools 白名单。某个工具同时出现在两个列表里,最终结果是被移除。2
两种写法对应不同使用场景:
  • 只读审计类(code-reviewer、security-auditor):用 tools 白名单,明确列出 Read, Grep, Glob,保证代理无法修改任何文件
  • 继承大部分工具但屏蔽特定操作:用 disallowedTools,避免重复罗列所有允许工具
tools 字段能覆盖的是「工具类型」的限制,对同一工具下的精细操作(比如「允许 SELECT 不允许 INSERT」)无能为力。这种场景需要配合 PreToolUse 钩子:
hooks:
  PreToolUse:
    - matcher: "Bash"
      hooks:
        - type: command
          command: "./scripts/validate-readonly-query.sh"
钩子脚本从 stdin 读取 JSON 格式的工具调用参数,检测到写操作时以 exit code 2 退出并返回错误信息——子代理看到的是一条错误消息,任务继续。
Claude Code subagent 上下文隔离示意:子代理在独立窗口运行,大量输出不污染主会话
Claude Code subagent 的 transcript 在独立上下文窗口中运行 4

Fork 模式:继承上下文的子代理

普通 subagent 每次都从空白上下文启动,Claude 需要把任务背景整理成一条委托 prompt 传给它。如果背景信息复杂,这条 prompt 写起来很重——而且子代理不知道主会话已经探索了哪些路径、排除了哪些方案。
Fork 模式(实验性,需 v2.1.117+,CLAUDE_CODE_FORK_SUBAGENT=1)解决这个场景:Fork 继承父会话完整的上下文和系统提示,首次请求直接复用父会话的提示缓存,成本低于新建子代理。2
对比项普通 subagentFork
初始上下文空白(只有委托 prompt)继承父会话完整对话历史
系统提示来自子代理定义文件与父会话相同
提示缓存需要从头构建复用父会话缓存,首次成本低
工具权限来自子代理定义与父会话相同
适用场景任务范围明确、背景可简洁描述任务需要全部对话历史才能继续
版本要求全版本v2.1.117+,实验性
Fork 通过 /fork <指令> 触发,或者开启 Fork 模式后自动替代 general-purpose。开启 Fork 模式后,所有子代理调用都会在后台并发运行。
Fork 不适合替代普通子代理的场景:任务目标明确、与主会话历史无关时,传一条完整的委托 prompt 给普通子代理,比复制整份上下文更便宜。Fork 的价值在于「省去整理背景的成本」,当背景本身不复杂时这个价值消失。

最容易踩的坑

后台子代理的权限预授权
子代理在后台运行时,遇到未授权的工具调用会自动拒绝(而不是暂停等待用户确认),但子代理本身继续执行。结果是任务在某个步骤默默失败,没有明显报错。
解决方法:在会话开始前先授权子代理需要的工具,或者把任务切到前台运行(Ctrl+B 反向操作:从前台切后台;前台运行则不要按 Ctrl+B)。
嵌套子代理不支持
子代理不能生成另一个子代理。需要多层委托时,只能从主会话链式调用——主会话先调用 A,A 完成后主会话再调用 B,B 的 prompt 里包含 A 的结果摘要。
或者用 Skills 的 context: fork 字段在子代理里注入另一套指令集——但这本质上是在同一个代理里加载不同的提示,不是真正的嵌套委托。
Explore 和 Plan 跳过 CLAUDE.md
如果 CLAUDE.md 里有「忽略 node_modules/」「代码风格遵守 ESLint」这类约束,Explore 代理在探索时不会读到这些规则。这通常不影响结果(主会话拿到 Explore 结果后会应用自己的 CLAUDE.md),但如果探索阶段本身需要感知这些约束(比如「只搜索符合项目约定的文件路径」),需要在委托 prompt 里显式重复这条规则。
isolation: worktree 的适用场景
前置元数据的 isolation: worktree 让子代理在一个独立的 git worktree 里运行——它的文件修改不会影响你的工作目录。适合「让子代理在隔离环境里跑修复实验,成功再合并」的场景,但多了 worktree 的创建和清理开销,不适合只读的探索任务。

几个可直接使用的配置

只读代码审查,合并前自动触发:
---
name: code-reviewer

tools: Read, Grep, Glob, Bash
model: sonnet
---
When invoked, run `git diff` to see recent changes.
Focus on modified files. Review for:
- Code clarity and naming
- Error handling completeness
- Security issues (exposed secrets, missing input validation)
- Test coverage adequacy

Provide feedback by priority: Critical (must fix) → Warning (should fix) → Suggestion.
调试专用,写权限但专注修复:
---
name: debugger

tools: Read, Edit, Bash, Grep, Glob
model: inherit
---
Workflow: capture error → identify reproduction steps → isolate failure location → implement minimal fix → verify.
For each issue: explain root cause, provide evidence, give specific fix, suggest prevention.
Fix the underlying issue, not the symptom.
SQL 只读校验,通过钩子实现比工具字段更精细的控制:
---
name: db-reader

tools: Bash
hooks:
  PreToolUse:
    - matcher: "Bash"
      hooks:
        - type: command
          command: "./scripts/validate-readonly-query.sh"
---
You have read-only database access. Execute SELECT queries only.
If asked to INSERT, UPDATE, or DELETE, explain you only have read access.
validate-readonly-query.sh 脚本的逻辑:从 stdin 读取 JSON,提取 tool_input.command,用正则检测写操作关键字,exit code 2 则拦截。

リンクプレビューを読み込んでいます…

小结

Subagents 的核心价值是上下文隔离,但让它真正发挥作用需要三层配置都到位:description 写清楚触发时机、tools 精确控制权限范围、钩子处理需要比工具级别更细的约束。
Fork 是普通子代理的补充,而不是替代——当子任务需要完整历史上下文时才有价值,背景简单时反而更贵。
子代理的数量不是越多越好:每个代理都要维护 description 的准确性,范围重叠的两个代理会让 Claude 的调度决策变得随机。宁可一个代理覆盖相关场景,也不要把一类任务拆成三个只有细微差别的代理。
12345

このコンテンツについて、さらに観点や背景を補足しましょう。

  • ログインするとコメントできます。