目录概要
- 把"员工"这个类比讲到底
- Subagent 跟 Command / Skill 的本质分野
- 16 字段 frontmatter:人事档案里写了什么
memory字段------v2.1.33 加的,最被低估的设计isolation: worktree是什么妖术initialPrompt、background和mcpServers------被忽略的三个能力- 5 个官方内置 agent 的用途对照
- Subagent 不能调用 Subagent------这条规则的代价
- 写 subagent 的三种典型风格
- 踩过的坑
1. 把"员工"这个类比讲到底
前两篇讲 Command 是"按钮"、Skill 是"工具"。按钮没脑子、工具没人格,按下去或者拿起来就完事。Subagent 不一样------Subagent 是会思考、带记忆、有权限边界、能独立拿工具干活的员工。
但把 Subagent 只当"能自己干活的脚本"理解是不够的。员工跟自动化脚本的真正区别是:
| 维度 | 自动化脚本 | 员工 |
|---|---|---|
| 输入 | 严格参数列表 | 模糊目标描述 |
| 权限 | 调用者的 | 岗位自己的 |
| 记忆 | 无(每次从头) | 岗位 + 个人 |
| 判断 | 确定性 | 在规则内自主决策 |
| 上下文 | 纯数据 | 工作历史 + 公司规则 |
Subagent 的 16 个 frontmatter 字段,大半都是在模仿一家公司对员工的管理机制------工具白名单是"你能用哪些工具"、memory 是"你的工作笔记"、maxTurns 是"你这个任务最多推进几轮再汇报"、isolation 是"给你单独开个工位"。
理解了这层之后,Subagent 的字段表就不是一堆参数,而是一份人事档案。这篇按人事档案的视角展开。
2. Subagent 跟 Command / Skill 的本质分野
第 02 篇的对比表放这里再贴一次------但这次我们专门看 Subagent 那一列:
| 维度 | Command | Skill | Subagent |
|---|---|---|---|
| 心智模型 | 按钮 | 工具 | 员工 |
| 运行上下文 | 主对话内联 | 主对话内联 | 独立子上下文 |
| 跨会话记忆 | 无 | 无 | 有(memory 字段) |
| 预加载其他扩展 | 无 | 无 | 有(skills 字段) |
能被 / 触发 |
是 | 是 | 否(不出现在 / 菜单) |
| 能自动触发 | 否 | 是 | 是(description 匹配) |
四个"有 "和一个"否"放一起------这些就是 Subagent 比前两者复杂两倍的理由。
具体来说:
这张图里有三个关键点:
- 派遣不是 import------Subagent 启动是 "hire a contractor for a job",不是"call a function"。主对话只看到派遣和结果两端。
- 隔离是默认的------中间的读 50 个文件、跑 10 次 grep、调 5 个 API 全部不进主对话。
- 状态是长期的------memory 字段让员工下次上岗还记得上次的事。
2.1 先造一个最小能跑的员工
如果只看字段表,很容易变成背配置。先放一个小到不能再小的 agent,感受一下它到底怎么落地:
markdown
<!-- .claude/agents/mini-reviewer.md -->
---
name: mini-reviewer
description: Review small diffs for obvious correctness issues.
tools: Read, Grep, Glob, Bash(git diff *)
memory: project
---
You review small code changes.
Before starting, check your memory for project-specific review patterns.
After finishing, update your memory with any reusable finding.
Return only:
1. Findings
2. Residual risk
怎么调用?
text
请用 mini-reviewer subagent 看一下我当前 git diff。
@agent-mini-reviewer review the current git diff
第一种是自然语言,Claude 会判断要不要派。第二种是 @agent-<name>,更像是你直接点名这个员工上岗。跑完之后,可以去 .claude/agent-memory/mini-reviewer/ 看它有没有写 MEMORY.md。这一步很重要,不然 memory 只是配置里好看,实际没形成工作习惯。
3. 16 字段 frontmatter:人事档案里写了什么
Subagent 的 frontmatter 比 Command/Skill 多 3 个字段------16 个。完整样本:
yaml
---
name: release-notes-agent # 员工工号(必填,小写加连字符)
description: Use this agent PROACTIVELY when ... # 什么情况下派遣(必填)
tools: Read, Write, Edit, Bash # 工具白名单(默认继承一切)
disallowedTools: Bash(rm *) # 黑名单(从继承/白名单里扣)
model: sonnet # 员工脑子:haiku/sonnet/opus/inherit
permissionMode: acceptEdits # 权限策略
maxTurns: 5 # 最多几轮自主推进
skills: # 预加载 skills 到 system prompt
- git-log-reader
mcpServers: # 这员工能连哪些外部服务
- playwright
hooks: # 员工级的生命周期 hook
PreToolUse: [...]
memory: project # 记忆作用域:user/project/local
background: false # 是否始终后台运行
effort: high # 干活用力程度
isolation: worktree # 给单独工位(git worktree)
initialPrompt: "Always start by..." # 入职自动说的第一句话
color: green # 终端显示颜色
---
16 字段按"管什么"分组:
前三组(身份/能力/行为)大多数字段跟 Command / Skill 语义一致,这里不重复。我们挑 最能把 Subagent 和 Command / Skill 拉开距离的 5 个展开:
memoryisolationinitialPromptbackgroundmcpServers
这 5 个字段组合起来,才是"员工"跟"工具"的根本差别。
4. memory 字段------v2.1.33 加的,最被低估的设计
memory 是 v2.1.33(2026 年 2 月)加的新字段。没这个字段之前,每次派遣 subagent 都是"白板上岗"------员工永远是新员工。
4.1 三种作用域
yaml
memory: user # 全个人跨项目
memory: project # 项目级,checked in,团队共享
memory: local # 项目级,git 忽略,个人用
三种作用域的物理位置跟 Claude Code 的 settings 层级完全对应:
| Scope | 磁盘路径 | Git | 共享 | 典型用途 |
|---|---|---|---|---|
user |
~/.claude/agent-memory/<name>/ |
否 | 否 | 跨项目的员工经验(我的 code-reviewer 在哪家都用同一套习惯) |
project |
.claude/agent-memory/<name>/ |
是 | 是 | 项目级团队共享知识(团队 review 规则) |
local |
.claude/agent-memory-local/<name>/ |
否(gitignored) | 否 | 项目里的个人 sidenote |
4.2 内部目录结构
javascript
~/.claude/agent-memory/code-reviewer/
├── MEMORY.md ← 首 200 行进 agent 启动时的 system prompt
├── react-patterns.md ← 按主题分拆的细节,用到才读
└── security-checklist.md
跟 Skill 的渐进式揭露是同一个思路------MEMORY.md 是索引页,主题文件按需读。如果 MEMORY.md 超过 200 行,agent 会主动把内容搬到子文件保持索引干净。
4.3 跟其他"memory"系统的关系
Claude Code 里名字叫 memory 的东西有四个,容易混:
| 系统 | 写入者 | 读取者 | 作用域 |
|---|---|---|---|
| CLAUDE.md | 你(手动) | 主 Claude + 所有 agent | 项目 |
| Auto-memory | 主 Claude(自动) | 只有主 Claude | 项目 × 用户 |
/memory 命令 |
你(编辑器) | 只有主 Claude | 项目 × 用户 |
| Agent memory | agent 自己 | 只有那个 agent | 可选 user/project/local |
这是一套分层记忆架构------CLAUDE.md 是"公司手册",auto-memory 是"主 Claude 的工作笔记",agent memory 是"某个岗位自己的笔记"。四套互不干扰,各读各的。
4.4 让 agent 真的用 memory
memory 字段给了存储,也会把 MEMORY.md 的前 200 行塞进 agent 启动上下文。但 它不会自动把每次工作都总结进去------必须在 agent 正文里显式指示。一个标准做法的 agent 正文结构:
markdown
## Your Task
1. **Collect**: Follow the `git-log-reader` skill instructions to gather commits between tags
2. **Classify**: Categorize commits using Conventional Commits semantics
3. **Memory**: Update your agent memory with the release metadata for future version comparisons
调用时还可以显式提醒:
arduino
> 生成 v2.4.0 的 release notes,参考你之前记录的 v2.3.x 分类习惯
agent 收到这个会先读自己的 MEMORY.md(有历史记录的笔记),再决定怎么回答。
一个常见误会:memory 不会自动总结。你不告诉 agent "更新你的 memory",它通常不会主动把经验沉淀下来。这点跟 auto-memory(主 Claude 会自动攒)不一样。
5. isolation: worktree 是什么妖术
yaml
---
name: dependency-upgrader
description: Upgrade and test a single dependency. Use PROACTIVELY when user asks to bump a package version.
isolation: worktree
tools: Read, Write, Edit, Bash(npm *), Bash(git *)
---
加了 isolation: worktree 之后,这个 agent 启动时 Claude Code 会:
- 自动
git worktree add一个临时分支工作区 - agent 在这个工作区里改文件、跑测试
- agent 跑完:
- 有改动 → 保留 worktree,告诉主对话路径和分支
- 无改动 → 自动清理
工作目录 /project] --> Hire[派遣 agent] Hire --> WT[git worktree add /project/.cc-wt/abc123] WT --> Run[agent 在 .cc-wt/abc123 执行] Run --> Test{有改动?} Test -->|有| Keep[保留工作区
返回路径 + 分支] Test -->|无| Clean[自动清理] Keep --> Main Clean --> Main style WT fill:#ff9 style Keep fill:#cfc style Clean fill:#fcc
5.1 为什么好
两件事同时成立:
- agent 的改动物理上不影响主工作目录------你的 IDE 没看到变化
- 真的 checkout 到分支------agent 不是在 sandbox 里编辑虚拟文件,它在跑真实的 git 分支
这比"直接在主目录改"安全------看到结果不满意不用 git reset,删 worktree 就行。也比 docker/container 隔离更轻------就是 git 自己的能力。
5.2 最好用的场景
| 场景 | 为什么 worktree 是对的 |
|---|---|
| 依赖升级 + 跑测试 | 升级过程污染 node_modules、lockfile;失败时主目录干净 |
| 批量 refactor 试验 | 一次改 100 个文件,结果不合适就整体丢弃 |
| 跨 PR 并行任务 | 两个 agent 各自 worktree,互不冲突 |
| 长运行迁移脚本 | agent 跑一晚上,主目录里你正常干别的 |
5.3 限制
- 不适合 "needs to see actual current index" 的任务(例如
git diff看未暂存改动) - 小项目没必要------worktree 的创建/销毁有 overhead
- 不能嵌套------worktree 里启动的 subagent 不会再开新 worktree
6. initialPrompt、background 和 mcpServers------被忽略的三个能力
6.1 initialPrompt
yaml
---
name: oncall-responder
description: Handle incoming pages with runbook lookup
initialPrompt: |
Before anything else:
1. Check your memory for similar past incidents.
2. Read `.claude/runbooks/` for the relevant runbook.
3. Start with impact assessment before remediation.
---
initialPrompt 最容易被误解。
它不是"每次被 Agent tool 派遣时都抢在用户输入前跑一遍"。更准确地说:当这个 agent 作为 main session agent 运行时(比如 claude --agent oncall-responder,或者在 settings 里配置 "agent": "oncall-responder"),initialPrompt 会被自动提交成第一轮 user message,并且会拼在用户自己的 prompt 前面。
所以它更像"这个员工今天作为主值班人上岗时,先做的开场动作"。
这跟 agent 的 system prompt(文件正文)区别在哪?
- System prompt:agent 的"人设" + "规则",普通 subagent 派遣也会稳定生效
- initialPrompt :agent 作为 main session agent 启动后的"第一个动作",是可变状态机的初始化
用场景:
- 员工上岗自动先"读一遍最近的团队 slack 总结"
- 每次 session 开始自动"load 昨天的 progress log"
- 调试类 agent 先"确认环境状态再动手"
这个字段特别容易被忽略 ,但也别滥用。普通一次性 subagent 的关键初始化,最好仍然写进 agent 正文或派遣 prompt 里;initialPrompt 更适合值班、驻场、长期 session 这种场景。
6.2 background: true
yaml
---
name: nightly-metric-collector
description: Pull nightly metrics and save to CSV
background: true
---
background: true 把 agent 变成后台任务------从派遣起它就不阻塞主对话,agent 跑完的结果进 /tasks 列表。
适合:
- 长时间跑的数据拉取
- 定时周期性任务(配合
/schedule) - 大批量文件处理
不适合:
- 需要和用户实时交互的任务
- 任务结果主对话立刻要用
- 临时需要追问权限或补充信息的任务(后台 subagent 缺权限时,很多交互会直接失败或被拒绝)
6.3 mcpServers
mcpServers 是把外部系统配给某个岗位,而不是把所有 server 都扔给所有人。
yaml
---
name: sentry-investigator
description: Investigate production exceptions from Sentry.
mcpServers:
- sentry-prod
tools: Read, Grep, Glob
---
这背后的思路很简单:code-reviewer 不需要连生产 Sentry,dependency-upgrader 也不需要连 Jira。真正需要外联的是某几个岗位,就把 MCP server 挂到那几个岗位上。这样 system prompt 里的 tool schema 少一点,权限面也小一点。
MCP 这一块第 10 篇会专门拆。这里先记住一句:agent 级 mcpServers 是岗位权限,不是项目默认权限。
7. 5 个官方内置 agent 的用途对照
Claude Code 自带 5 个 agent,很多人只知道 general-purpose 一个。其他 4 个是专职员工,用好省很多 token:
| # | Agent | Model | 工具 | 什么时候派它 |
|---|---|---|---|---|
| 1 | general-purpose |
inherit | 全部 | 复杂多步任务(默认) |
| 2 | Explore |
haiku | 只读(无 Write/Edit) | 快速搜码 / 找文件 / 回答仓库结构问题 |
| 3 | Plan |
inherit | 只读 | plan mode 里做前期 research 和设计 |
| 4 | statusline-setup |
sonnet | Read, Edit | 帮你配置 statusline |
| 5 | claude-code-guide |
haiku | Glob/Grep/Read/WebFetch/WebSearch | 回答关于 Claude Code、Agent SDK、Claude API 本身的问题 |
7.1 Explore 是最被低估的一个
你问 Claude "这个仓库里 user auth 相关的代码在哪?"------主 Claude 会自己跑十几个 Grep,填满上下文,然后给你答案。
换成:
markdown
> 用 Explore agent 告诉我 user auth 代码在哪
Explore 是 haiku + 只读,启动快、便宜、只返回结论。主对话里只进"auth 相关代码在:src/auth/*"这一句,不是十几个 Grep 的 token。
一个实用经验------做仓库探索时永远显式指派 Explore。这是最容易省 token 的一个习惯。
7.2 Plan agent 跟 plan mode 的关系
/plan 进 plan mode 时,Claude Code 内部派遣的就是 Plan agent。你用 /plan 之后看到的"思考过程"是 Plan agent 的输出,主 Claude 只拿到最终方案。
这是为什么 plan mode 比"我自己问 Claude 想想方案"更干净------隔离。
8. Subagent 不能调用 Subagent------这条规则的代价
这是项目 CLAUDE.md 里最该写一遍、但大家容易忽略的警告:
Subagents cannot invoke other subagents via bash commands. Use the Agent tool (renamed from Task in v2.1.63;
Task(...)still works as an alias):
iniAgent(subagent_type="agent-name", description="...", prompt="...", model="haiku")
这条规则的关键是两个"不能"和一个"可以":
- ❌ 不能 用
Bash("claude --agent my-agent ...")调 agent - ❌ 不能 在 subagent 正文里用
/agents切换 - ✅ 可以 用
Agent工具(或旧名Task工具)调起另一个 subagent
为什么定这条规则?
因为 subagent 已经是独立上下文------再嵌一层 subagent 需要 orchestrator 自己维护调用栈。目前设计是让 Agent 工具专门处理这种派遣,保证返回值能正确回流上层。
8.1 实际中的表现
写 agent 指令时要注意用词:
markdown
# ❌ 错误写法(容易被理解成 bash 调用)
Then launch the validation-agent to verify the output.
# ✅ 正确写法
Then use the Agent tool with subagent_type "validation-agent" to verify the output.
上一句里 "launch" 这个词让 Claude 有 50% 概率写成 Bash("claude --agent validation-agent ...")------然后就错了。明确写 "use the Agent tool" 能避免这个歧义。
8.2 重命名历史:Task → Agent
v2.1.63 之前工具叫 Task,之后重命名为 Agent。旧名保留作 alias,两种都能用。很多存量 command/agent 文档里还写着旧名:
markdown
### Step 2: Gather commits
Use the Task tool to invoke the release-notes agent:
遇到新老文档混用不要困惑。但新写代码时建议用 Agent------更准确。
9. 写 subagent 的三种典型风格
跟 Command 的三种形态类似,Subagent 也有三种典型风格:
9.1 风格一:专家型员工(知识密集)
yaml
---
name: code-reviewer
description: Use PROACTIVELY to review code for quality, security, and conventions.
tools: Read, Grep, Glob, Bash(git *)
model: sonnet
memory: user
---
You are a senior code reviewer with 15 years of experience...
## Review Dimensions
- Correctness
- Security
- Performance
- Readability
- Testability
## How you work
1. Read your MEMORY.md for patterns you've seen before
2. Review the diff
3. Update MEMORY.md with new patterns
特点:纯只读 + 记忆驱动。依靠 memory 跨会话积累经验。review 得越多越老练。
9.2 风格二:执行型员工(工具密集)
03 篇里的 release-notes-agent 就是这种:
yaml
---
name: release-notes-agent
description: Use PROACTIVELY when you need to compile release notes between two git tags
tools: Bash(git *), Read, Write, Edit
model: sonnet
maxTurns: 5
permissionMode: acceptEdits
memory: project
skills:
- git-log-reader
---
特点:明确的工作流 + 预加载 skill + 有限 turns。一次派遣做一件事。agent 正文短(body 30 行左右足够),细节都在 skill 里。
9.3 风格三:驻场型员工(initialPrompt + background)
yaml
---
name: metrics-watcher
description: Continuously watch service metrics and flag anomalies
background: true
initialPrompt: |
Start by reading your memory for the baseline from yesterday.
Load current metrics from Grafana.
Diff them. Flag anything >20% deviation.
Report every 15 minutes or on anomaly.
memory: user
tools: WebFetch, Read, Write
---
特点:长期驻场 + 周期行为。进程起来就干活,主对话基本不管它。
10. 踩过的坑
坑 1:description 里不写 PROACTIVELY
这个是 Subagent 最常见的坑。description 里没有 PROACTIVELY 关键字,Claude 主动派遣的概率会明显下降------你经常得自己说 "用 xxx-agent 去干这件事"。
PROACTIVELY 更像一个强提示,不是布尔开关。写了不保证 100% 会用,不写也不是绝对不会用;但它确实能把这个 agent 从"手动档"往"自动档"推一截。
坑 2:tools 写成单词拼接
yaml
# 错
tools: Read Write Edit
# 对
tools: Read, Write, Edit
# 或
tools:
- Read
- Write
- Edit
YAML 不容空格分隔。踩了会报解析错,但错误信息不明显。
坑 3:skills 字段填了用户触发的 skill
yaml
# 危险
skills:
- release-notes-formatter # 这是用户可触发的直接 skill
这样写不是报错,而是:skill 的全文被灌进 agent system prompt------浪费 token,并且用户用不用得到这个 skill 就看 agent 记不记得。
预加载只填 user-invocable: false 的 skill(明确作为私人手册设计的)。
坑 4:maxTurns: 3 太小
复杂任务 3 turns 经常不够------agent 还没发现问题就被强制停了。
建议:
- 简单拉取/格式化:3-5
- 多步 research:10-20
- 长运行或 refactor:50+ 或不设限
坑 5:memory 设成 project 但 agent 不写
上面讲过------memory 存储是自动的,但写入要 agent 自己动手。正文里必须显式 "Update your memory with ..."。
坑 6:agent 正文里说 "launch the other agent"
Subagent 不能调 Subagent 用 bash,必须用 Agent 工具。"launch" 这个词容易让模型以为是 bash 启动------第 8 节详述。
坑 7:isolation: worktree 用在小项目上
几 KB 的项目加 worktree 就是"高射炮打蚊子"------worktree 创建/销毁的 overhead 比整个任务还大。几百 MB 以上的项目才值得。
复盘一下
Subagent 的 16 字段比 Command/Skill 多那 5 个------memory、isolation、initialPrompt、background、mcpServers------恰好是把"工具"升级为"员工"的那 5 个能力:
memory让员工能跨会话积累isolation让员工有独立工位initialPrompt让员工入职自动化background让员工长期驻场mcpServers让员工独立外联
剩下的字段(tools/model/effort/maxTurns/permissionMode/hooks)大多跟 Command/Skill 共享语义。记熟了前 5 个,其余字段就是微调。
写到这儿,Command / Skill / Subagent 三个核心扩展点拆完了。但仔细看你会发现每一篇都反复提到一个东西------hooks。每个扩展都有 hooks 字段、每个扩展都能挂自己的生命周期钩子、on-demand hooks 和 PreToolUse 埋点都在这里。下一篇把 hooks 单独拎出来讲------27 个 hook 事件、同步 vs 异步、matcher 的精确控制、跨平台声音通知的实现。