把项目子智能体写成 .cursor/agents/*.md。父智能体读 description 决定要不要把一段工作委派出去;委派之后子智能体有自己的上下文,适合「改完再另眼验收」这种不想和实现过程搅在一起的事。只读角色写 readonly: true,沿用当前对话的模型写 model: inherit,description 里写清调用时机。
三种情况下会打开这一页:想让「改完再验收」由另一个角色做,别让实现过程污染验收判断 → 照「示例:两个只读角色」抄一份 .md;这个角色从没被叫到,或者本该只读的改了文件 → 到「常见错误」的现象表里对一行,多数是 description 没写调用时机,或漏了 readonly: true;从 Claude Code 或 TraeCode 搬过来 → 先逐行核「子智能体在三处」。
两处容易写错:把数据范围、密钥这类约束只写在子智能体文件里,父智能体自己动手时读不到;把 Claude Code 的 tools: 白名单照搬过来——Cursor 限制权限用的是 readonly: true,不认 tools:。
删掉这份 .md,父智能体自己动手改代码时会漏掉哪一条?
真的漏掉一条,说明它写错了位置:全局约束归 AGENTS.md,子智能体文件只在被委派时才进上下文。这里只写「怎么验收」。
子智能体不是每次都会被叫到,父智能体按 description 决定。所以在 description 里除了写「做什么」,还要写清「在什么时点用」——例如「在改完查询、上传或检索之后使用」。真正的全局约束(数据范围、密钥、当前阶段范围)只写 AGENTS.md 一处。
readonly: truemodel: inheritinherit 表示跟当前对话用同一个模型。readonly: true,description 写清「改完 X 之后使用」,正文只写要报告什么、不写改代码。
tools: Read, Grep, Glob;让验收角色默认能写文件;把「什么时候用」从 description 里省掉。
什么时候不用子智能体:这件事父智能体自己做就行、也不需要另一份独立上下文,就不拆角色——多一个角色只是多一个要先被叫到才生效的文件。需要的是「独立上下文 + 独立权限」时再建。
路径规律一致,区别集中在「怎么限制它只能读」这一个字段上。搬工具时逐行核这张表。
| 项 | Claude Code | Cursor | TraeCode |
|---|---|---|---|
| 项目位置 | .claude/agents/*.md | .cursor/agents/*.md | .trae/agents/*.md |
| 个人位置 | ~/.claude/agents/ | —— | ~/.trae-cn/agents/ |
| 限制权限 | tools: Read, Grep, Glob(不写 Write / Edit / Bash) | readonly: true | tools: Read, Grep, Glob 加 disallowedTools: Write, Edit, Bash |
| 模型 | —— | model: inherit 沿用当前对话的模型 | 不写 model 时用对话里当前选的模型 |
| 名称约束 | —— | —— | name 只能用字母、数字、连字符,不超过 50 字符;name 与 description 必填 |
| 怎么被叫到 | 由 description 决定;对话里也可输入 @ 点名 | 由 description 决定 | 由 description 决定;也可在提示里直接说「使用 verifier 检查这次改动」 |
搬工具时最容易漏改的就是「限制权限」这一行:把 tools: 留在 Cursor 文件里,它不会被当作只读开关,验收角色还能写文件。
两个角色分工不同:verifier 用两个账号实际看一次数据范围,query-reviewer 只看这次改动的 SQL 有没有绑定会话的 scope_id。让它们都在改完之后被叫,都只报告、不改代码。
readonly: true 让这个角色不能改文件。model: inherit 沿用当前对话的模型。描述里写清调用时机:查询、上传或检索改完之后。
--- name: verifier description: 验收数据范围。在改完查询、上传或检索之后使用。只读,不改文件。 model: inherit readonly: true --- 用两个所属范围的账号各看一次。 当前所属范围的数据能读到。 其他所属范围的数据读不到,且与记录不存在无法从响应区分。 没有命中时返回无依据,不出现材料中没有的句子。 只报告看到的请求、SQL 或接口结果,不改代码。
第二个只读角色,只看静态的 SQL 写法。和 verifier 的运行时验收互补。
--- name: query-reviewer description: 检查新增或修改的 SQL 是否绑定会话中的 scope_id。在改完查询之后使用。只读,不改文件。 model: inherit readonly: true --- 逐条列出这次改动涉及的 SQL 语句。 指出每条是否用 `WHERE scope_id = ?` 绑定会话中的 scope_id。 没绑定的,给出文件与行号,不改代码。 不判断业务逻辑对不对,只判断绑定这一件事。
两个文件都不写数据范围本身——那一条写在 AGENTS.md 里。某个角色需要动手改文件(例如补测试)时,不要给它 readonly: true,同时要在合并请求里写清它改的范围由谁评审。
「写了但没起作用」是子智能体最常见的一类问题,从现象反查。
| 现象 | 原因 | 修法 |
|---|---|---|
数据范围只有 verifier.md 里有,父智能体改代码时仍然写错 | 子智能体的正文只有被委派时才进上下文,父智能体自己动手时读不到 | 数据范围、密钥、当前阶段范围写进 AGENTS.md;子智能体只写「怎么验收」 |
| 本该只读的子智能体改动了文件 | 没有设 readonly: true | 在前置元数据加 readonly: true |
| 验收角色该被叫的时候没被叫,父智能体直接宣布改完 | description 只写了角色是什么,没写调用时机 | 补上「在改完查询、上传或检索之后使用」这类触发的时点 |
把 Claude Code 的 tools: Read, Grep, Glob 写进 Cursor 子智能体,验收角色仍能写文件 | Cursor 限制权限用的是 readonly: true,不认 tools: 这种写法 | 删掉 tools:,改成 readonly: true |
| TraeCode 里子智能体加载不出来,提示名称有问题 | name 只能用字母、数字、连字符且不超过 50 字符;name 与 description 必填 | 把 name 改成符合字符集与长度要求的值,并确认 description 没缺 |