结构与路由:skill 怎么切、怎么路由、原则怎么写
结构与路由:skill 怎么切、怎么路由、原则怎么写
给 coding agent 的执行参考。每节结构:为什么 → 做法 → 判据 → 边界。
这一篇管三件事:分篇依据(按处境还是按主题)、主文件预算(怎么裁)、句子写法(怎么让 agent 照做)。
0. 目录
- 处境切分 vs 主题切分
- 分篇的三个测试
- 主文件预算与裁剪顺序
- 什么必须留在主文件
- 路由表写法
- 术语表
- 原则的三段式
- 句法:给默认、解释 why、不用全大写
- 多步流程清单化与验证闸门
- 错误信息即自我纠正工具
- 资产:参考文件 / 脚本 / 模板
- 官方硬约束速查
- 反模式
- 反例速查表
1. 处境切分 vs 主题切分
按处境切:参考文件的分篇依据是「agent 在什么处境下需要它」,且这些处境互斥。典型处境:正在设计 X / 正在写这类文本 / 正在查这类缺陷 / 项目用的是某个特定技术栈。
按主题切:分篇依据是「这批知识属于哪个学科」。典型形态:「方法论篇」「流程篇」「原则篇」。
为什么处境切分赢:主题切分产生的结构里,每篇都被多个处境同时需要,路由表立刻退化成「详见参考」。而路由表退化成「详见参考」等于没有路由——agent 不会意识到该去读。
亲历:六篇 reference 全部按处境切(设计体验 / 写文本 / 设计机制 / 造空间 / 查缺陷 / 特定技术栈),六个处境互斥,路由表能给出六条一对一映射。
判据:路由表每行的「触发条件」两两之间不重叠——同一个处境不会命中两行。
2. 分篇的三个测试
定分篇方案时逐条过:
- 处境互斥测试:能不能说出「agent 处于 A 处境时绝不会需要 B 篇」?说不出来就合并。
- 独立可读测试:只读这一篇,不读其他篇,能不能动手?不能说明它依赖了太多前置。
- 路由唯一测试:每篇能不能被一条自然的用户语言描述出来(「如果你在写用户可见文案,读 text-and-props.md」)?不能说明它按主题切了。
分篇数量:少于 4 篇通常说明分篇依据不对(可能按主题切了);多于 8 篇通常说明在切子主题而不是切处境,而且每篇的独立可读测试会失败。
判据:每个参考文件 > 300 行时,开头放目录;每个参考文件能被单条触发条件命中。
3. 主文件预算与裁剪顺序
预算:硬上限 500 行,社区警戒线 400。超了不是删到刚好,是按下面的顺序删。
逐条过判据:「没有这条,agent 会不会做错?」不会就删。注意这条判据是双向的——它既删冗余,也删「读起来很完整但改变不了行为」的装饰段。
裁剪顺序(先删前面这些):
- 反常识但没有判据的补充说明——它没改变行为。
- 派生结论——能由主文的推导读出来的。
- 具体实例——下沉到 reference,主文只留「详见」。
- 同义重述——同一个意思出现两次时,留判据更可执行的那次。
不裁(即使超预算):判据、通则正文、高价值坑(见第 4 节)。
判据:正文里每一条都能回答「没有它,agent 会不会做错」。答不出就删掉或下沉。
4. 什么必须留在主文件
高价值坑留主文件,因为 agent 是在遇到情况之前读正文的。
判别法:设想一个此刻正遭遇该情况的 agent。它读的是正文。如果这条坑在 reference 里,它不会意识到该去读——因为触发它去读 reference 的那个念头,本身就要靠这条坑。
亲历留在主文件的条目(已去掉领域名词):反复反馈是优先级信号;反复缺陷修类不修点;找不到根因时如实说;散比大致命;断言要断言玩家可见结果;断言跟着设计走;不可破的例外和真 bug 长得一样。
对照:推导与反例该下沉。agent 遇到情况时需要的是「该做什么」,不需要「为什么这么定」——除非它开始怀疑这条原则,那时候它会主动去读 reference。
判据:主文件里的每条坑都能回答「一个正遭遇它的 agent 会怎么读到它」。答案是「它得先知道有 reference」的,移上去。
5. 路由表写法
每条引用自带触发条件。 用用户的语言写条件,不用内部术语。
| 写法 | 判断 |
|---|---|
| 「详见参考」 | 无效——agent 不知道什么时候该读 |
「详见 evals.md」 |
仍是无效——按主题命名,条件在正文里 |
「在写或改评测集;设计触发率查询;给输出 case 写断言 → references/evals.md」 |
有效——处境在左,文件在右 |
四条纪律:
- 触发条件用互斥的处境短语,不是关键词堆砌。
- 每行只有一个文件——一对一,不合并。
- 条件写 2–4 个具体动作或情境(覆盖邻近情况),不是抽象名词。
- 路由表本身在主文件里,它就是分发层。
判据:随机抽一行,把触发条件念给没读过这个 skill 的人听,他能判断自己该不该去读。
6. 术语表
为什么:一个已知的紧凑词替代一句展开描述;重复解释同义词是模型噪声。
放什么:
- 本 skill 反复用、且不是通用词的(标「单例,降权」「skill lift」这类)。
- 自造词(必须标「自建框架」,见
from-transcripts.md第 6 节)。 - 常见误用词(两个词在项目里指了同一个东西,读者必须知道用哪个)。
不放什么:模型已经知道的通用词。解释「幂等」对 agent 是纯浪费。
判据:术语表里每项都能回答「这个词在本次工作之前就存在吗,或它是不是被明确标注的自造词」。答不出的删掉。
7. 原则的三段式
每条原则写三段:原则 / 推导依据 / 判据。
| 段 | 内容 | 反例 |
|---|---|---|
| 原则 | 一句话,祈使句,不含项目名词 | — |
| 推导依据 | 因为 X 会导致 Y | 「因为这样更好」 |
| 判据 | 能写成断言,或能人工过一遍 | 「符合最佳实践」 |
判据段是全篇最不能省的一段:它决定这条原则是「会改变行为的规则」还是「没人会照做的愿望」。
判据的两种形式:
- 机械可查:grep 退出码、枚举计数、字段齐全、
max(x)的值不出现某个字段。 - 人工过一遍:一个能在两三分钟内得出是/否的问题。
优先写机械可查的——它能进评测集的 good 级断言。人工判据标 weak_manual。
判据:正文每条原则都有判据;每条判据要么能被写成脚本,要么能被一个人在三分钟内回答。
8. 句法:给默认、解释 why、不用全大写
给默认,不给菜单。 写清推荐路径与例外条件。列三五个选项让 agent 自己选,等于没约束——它会选最常见的那个,而最常见的那个在你的项目里通常是错的。
菜单式:「可以用 A 抽取,也可以用 B 抽取,也可以手工 C。」 默认式:「用 A 抽取。B 在素材来源异构时更好;C 只用于素材少于千行且 A 的开销不划算时。」
解释 why,不用全大写。 写 ALWAYS / NEVER 是黄旗:它把一条有理由的规则降级成一条需要外部权威的规则,模型对它的遵守率反而更低。
菜单式:「MUST 给每条原则写判据。」 带理由式:「给每条原则写判据,因为没有判据的原则是没人会照做的愿望(这类条目在实际交付里占大多数)。」
祈使句。 动词开头,无主语,无「请」。
不解释模型已经知道的。 解释会占预算,且隐含「你可能不知道」,降低整份文档的可信度。
不写泛泛的最佳实践。「妥善处理错误」「保持代码整洁」这类是官方点名的失败模式——它们没有可执行内容。
判据:正文里没有出现成串的 MUST / NEVER / CRITICAL;没有一条不带例外条件的并列选项列表。
9. 多步流程清单化与验证闸门
多步写成可勾选清单,每步以可验证动作结尾。
- [ ] 20 条触发查询写完(10 正 10 近似负)
- [ ] 每条至少跑 3 次
- [ ] 断言本身被审查过一遍
每步的完成标准要满足覆盖力测试:如果 agent 只做步骤里写明的事,结果是否可接受?可接受说明步骤有漏洞——它能跳过。
验证闸门:多步流程之间要有硬闸门。最好的闸门是顺序要求——先建评测再写文档,是靠顺序强制的,靠「请先建评测」不是。
判据:正文里每个清单项都有可机械检查的完成条件;流程里存在至少一个顺序闸门。
10. 错误信息即自我纠正工具
一条好的错误信息让 agent 下一轮自己就能纠正;一条差的错误信息让它再问一次。
| 差的 | 好的 |
|---|---|
| 「格式错误」 | 「每行必须是 `原话 |
| 「测试失败了」 | 「case o03 的断言 2 两种配置下都 fail,说明 skill 里缺了这条内容」 |
| 「触发率太低」 | 「10 条负例里 n04 n07 被触发——它们共享『写入正式文档』这个概念,检查 description 是否需要收窄边界」 |
写法:错误信息要指出错在哪一行 / 哪个位置 / 下一步做什么,而不是复述规则。
判据:文档里出现的每条错误提示都带一个具体位置(行号、字段名、case id)。
11. 资产:参考文件 / 脚本 / 模板
默认路径:能机械执行的一律进 scripts/,文档格式模板进 assets/,只有需要判断力的才进 references/。
判别法:如果每次跑评测都要手写同一个校验脚本,它就该进 scripts/。
参考文件 > 300 行:开头放目录。
参考文件一层深:不做 references/sub/x.md 的链式引用。链式引用会让路由表的判断负担指数上升——agent 判断一次要不要读 reference 已经够难了。
判据:目录里没有第二层子目录;每篇 reference 有目录或 < 300 行。
12. 官方硬约束速查
| 项 | 约束 |
|---|---|
name |
必须等于目录名;小写字母、数字、连字符;1–64 字符 |
description |
1–1024 字符;祈使式(Use this skill when...);聚焦用户意图;宁可 pushy |
| 主文件 | < 500 行(警戒线 400) |
| 参考文件 | 一层深,不链式;> 300 行加目录 |
| 正文判据 | 逐条过「没有这条,agent 会不会做错」 |
| 语气 | 给默认不给菜单;解释 why 而非全大写 MUST/NEVER |
| description 判据 | 需要用「and」解释时,那是两个 skill |
| 内容判据 | 优先「程序」而非「声明」——教如何处理一类问题,不是某个实例该产出什么 |
description 的最后一条是最锋利的那条:如果你发现自己在用「以及……」把两件事连起来,拆成两个 skill 比写一个宽 description 更好。
13. 反模式
| 症状 | 后果 | 治疗 |
|---|---|---|
| 全能 skill | description 匹配不准,触发率两头都差 | 按单一职责拆 |
| 文档即代码 | 主文件超预算,淹没判据 | 脚本进 scripts/ |
| 历史堆积 | 「以前要 X,现在要 Y」 | 只写当前规范,历史删掉 |
| 假设上下文 | 「像之前那样处理」 | 每个指令自包含或带引用 |
| 过度防御 | 浪费预算,且降低严肃度 | 只写真实发生过的误操作 |
| 主题切分参考文件 | 路由表退化成「详见参考」 | 按处境重切 |
14. 反例速查表
| 反例 | 为什么错 | 正确做法 |
|---|---|---|
| 「详见参考」 | agent 不知道何时该读 | 写「如果 X 则读 y.md」 |
| 路由表按文件名分类 | 读者不知道何时适用 | 按处境写条件 |
| 主题切分的 reference | 多处境同时需要,无法路由 | 按互斥处境重切 |
references/evals/ 二层 |
路由判断负担指数上升 | 一层深 |
| 参考文件 800 行无目录 | agent 读不完 | > 300 行加目录 |
| 高价值坑下沉 reference | 正遭遇该情况的 agent 读不到 | 留主文件 |
| 「MUST 给每条原则写判据」 | 无理由的强制降低遵守率 | 解释 why:没有判据的原则是愿望 |
| 「可以用 A 也可以用 B 也可以 C」 | agent 会选最常见的那个 | 给默认 + 例外条件 |
| 「请认真检查输出」 | 空语句 | 换成可机械检查的完成条件 |
| 「妥善处理错误」 | 泛泛最佳实践,官方点名 | 换成可执行步骤 |
| 「像之前那样处理」 | 假设上下文 | 自包含或带引用 |