DeepDojo.AI发布 2026-11-12English

Claude Code 自定义只读审查子代理

Claude CodeAI 编程

每次让子代理审查代码,你都要把同一段话再说一遍:只读,不要改文件;每条发现给出文件和行号;别为了凑数罗列风格偏好;没发现问题也要说明查了哪些范围。说到第五次,你开始想,能不能把这些要求固定下来,变成一个随叫随到的审查角色。

Claude Code 支持这样做:在 .claude/agents/ 里放一个 Markdown 文件,开头用 frontmatter 限定它的工具、模型和权限,正文写它的工作方法。难点不在格式,而在边界。几个常见的误会:

  • 不写 tools,以为它只会读,实际上继承了主会话的全部工具;
  • 写了 permissionMode: plan,主会话一切到 acceptEdits,它就跟着变了;
  • 打开持久记忆,只读角色悄悄多了写文件的能力。

所以定义一个可靠的角色,要做到两件事:frontmatter 用最少的工具和合适的模型限定能力,正文写清输入、方法、证据和交付格式。每加一项能力,都回头核对工具和权限。下面用一个 code-reviewer 从头走一遍。

01 什么时候值得定义一个角色

一次调查,临时子代理就可以。等你反复需要同一种审查,每次还要重说角色、工具和结果格式时,再把这些稳定要求保存成自定义代理。例如固定标准的认证审查、失败分析、只读数据库查询或截图验收,反复出现后可以定义角色。

项目代理放在 .claude/agents/,它适合当前仓库,并可以提交到 Git 供团队共同维护。个人跨项目代理放在 ~/.claude/agents/。

遇到同名代理,大致按这个来源顺序选择:

Managed → --agents 临时定义 → 项目 → 用户 → 插件

项目内从当前目录往仓库根目录找,较近目录的同名定义优先。frontmatter 的 name 决定代理身份。名称要在范围内保持唯一:Claude Code 的子代理文档说明,同一个 .claude/agents/ 目录下两个文件声明了同一个名字时,只会加载其中一个,按文件系统的读取顺序而不是有文档说明的优先级来选。可用 /doctor 检查。

02 一个只读审查代理的完整定义

以只读审查为例,先想它要取得什么材料。这里由主会话提供 diff 文本或差异文件,代理再用读取工具查相关实现和测试。把这个输入约定和角色限制写进带 YAML frontmatter 的 Markdown 文件:

---
name: code-reviewer
description: 审查已经修改的代码,定位正确性、安全性和回归风险。完成代码改动后主动使用。
tools: Read, Grep, Glob
model: sonnet
permissionMode: plan
maxTurns: 12
color: blue
---

你是一名只读代码审查者。不要修改任何文件。

开始后先确认审查范围和主会话提供的 diff,再读取相关实现和测试。
若没有差异材料,报告缺少输入,不把未审查内容当作已经通过。只报告有证据的问题,
不要为了增加数量罗列纯风格偏好。

每条发现必须包含:
1. 严重程度;
2. 文件和行号;
3. 触发条件与实际影响;
4. 判断依据;
5. 最小修改建议。

如果没有发现问题,明确说明已检查的范围,并列出仍未验证的风险。

frontmatter 限定能力,正文说明方法、证据和结果。直接编辑 .claude/agents/ 或让 Claude 按明确要求创建文件。Claude Code 会监视已有的代理目录,修改几秒内生效;会话启动时目录还不存在、你新建了第一个代理文件时,需要重启才能加载。

03 逐个字段看能力边界

几个字段分开看:

字段控制什么
name唯一标识,用小写字母和连字符
description告诉主会话什么时候委派
tools可用工具
model模型别名、完整 ID,或用 inherit 继承
permissionMode希望使用的模式;可能被主会话覆盖,工具仍需收紧
maxTurns最多执行多少轮,到达上限时返回标记为未完成的结果
color列表里的区分颜色,不改变能力

必填的只有 name、description。不写 tools,就会继承主会话工具。按职责列出最少需要的工具,更容易看清它能做什么。Claude Code 最佳实践把这个做法说得很清楚:给 .claude/agents/ 里的自定义子代理只配 tools: Read, Grep, Glob,它就成了一个不能编辑任何东西的审查者,而且这个限制由 Claude Code 强制执行,不是在提示词里请求它遵守。

tools 明确列出允许能力;disallowedTools 从继承能力中移除少数工具,例如 Edit、Write。两项都写时,先去掉禁用工具,再按白名单选。官方还提醒,disallowedTools 里写带参数的条目,比如 Bash(git push *),照样会移除整个工具。

只读角色先排除 Edit、Write。需要 Bash,就再用权限、沙箱或 Hook 限制实际命令。仅写 permissionMode: plan 还不够:子代理文档说明,主会话处于 auto、acceptEdits 或 bypassPermissions 时,子代理会跟随主会话的模式,忽略你写的值。各权限模式的区别见Claude Code 六种权限模式怎么选。

描述要同时写清任务类型、触发时机和边界,主会话才能在正确场景委派:

description: 审查已经修改的认证与授权代码,检查正确性、安全性和回归风险。完成相关代码改动后主动使用;不负责直接修改文件。

正文补齐输入、必读材料、判断顺序、限制、结果结构和无发现时的报告要求。“资深专家,请仔细工作”没有这些执行信息,无法弥补缺失的主会话背景。

04 按任务选模型,按需预加载 Skill

模型应按任务复杂度和所需能力选择:

任务模型思路
文件定位、简单提取、格式检查优先考虑 Haiku
常规审查、调试和代码理解优先考虑 Sonnet
高风险架构判断、复杂根因分析需要时使用 Opus
与主会话强相关且不确定使用 inherit

选模型时,先确认它有能力完成任务,再比较速度和成本。能力不足、反复返工,也是在花钱。简单提取用轻量模型很合适,复杂判断就按实际要求选择。

skills 可以在代理启动时预加载专业知识:

skills:
  - api-conventions
  - security-review

预加载会把 Skill 全文加入代理的起始上下文,官方特别注明注入的是完整内容,不只是描述。只加入当前任务需要的方法,避免无关资料占用空间和注意力。

05 三种调用方式

按控制范围选择入口:

需求调用方式与边界
日常委派说“用 code-reviewer 审查认证改动”;主会话仍有选择权
确保指定代理运行在输入框用 @ 选择,如 @"code-reviewer (agent)"
整段会话使用同一角色启动 claude --agent code-reviewer,将其系统提示、工具和模型作为主线程身份

日常委派时,交给它的消息仍要自包含,写法见怎样给子代理交代任务、核对结论。

06 打开持久记忆以后

新建普通子代理,不会自动带上上次的对话;明确恢复已有实例,才接着用它的历史。想跨会话积累项目模式、调试经验或架构决定,可以设 memory 的保存范围:

memory: project

三种范围分别是:

范围位置适用内容
user~/.claude/agent-memory/<代理名>/跨项目通用的个人经验
project.claude/agent-memory/<代理名>/项目专有且可以与团队共享的知识
local.claude/agent-memory-local/<代理名>/项目专有但不应提交的个人记录

开启后,代理的系统提示里会带上记忆目录里 MEMORY.md 的前 200 行或 25KB,先达到哪个限制就停。入口保持短索引,细节按主题放其他文件。

下次仍会影响判断的稳定约束、重复故障和已验证路径,可以保存。整份测试输出、临时分支状态和猜测,留在这次任务里。经验要注明版本、范围与复核位置。旧版“退出漏吊销 token”不能记成持续存在的缺陷,代码变化后及时更新。

开启 memory 会为维护笔记增加读写工具。官方文档写明,开启记忆后 Read、Write、Edit 会自动启用,好让子代理管理自己的记忆文件。原先的只读角色因此获得了写入能力,需要重新检查工具和权限;只允许维护记忆时,把写入范围限定在记忆目录。

开头那段每次都要重说的要求,现在都写进了 code-reviewer.md:工具只有三个读取工具,正文写清了证据和交付格式。以后每给它加一项能力,比如记忆、Bash 或新的 Skill,都回头看一眼它还是不是那个只读审查者。