给 AI 代理写技能而不是写文档

近百技能的沉淀与治理

Posted by walikrence on September 8, 2026

背景脱敏:一个多仓库的游戏项目,日常开发大量由 AI 编码代理执行。项目里沉淀了 89 个技能目录,每个一份 SKILL.md,合计约 1.76 万行,名称加描述共 22922 字符。它们从早期 IDE 的规则文件迁移而来,经历过一轮从 137 个砍到 83 个的治理。本文讲技能和文档的本质区别、怎么写才会被触发、怎么强制走流程,以及治理时的几条判据。

技能不是文档:触发式与被动查阅

文档是给人查的:人知道自己不会,去翻。技能是给代理触发的:代理不知道自己不会,得靠描述命中当前任务,把规程加载进上下文。两者的失败模式完全不同。文档写得再好,代理不翻就等于不存在;技能写得再全,描述不命中就等于不存在。

所以技能的第一性问题是描述怎么写。项目里的写法规范是:描述只写「何时使用」,不写「技能做什么」。以「当…时使用」或「Use when…」开头,列具体症状、情境和用户会说的原话,第三人称,中英双语便于匹配,建议 350 字符以内、上限 700。

「不写做什么」这条有实测依据。一个执行计划的技能,描述曾写成「按任务派发子代理,任务间做 code review」,代理照着描述做了一次 review 就收工,尽管技能正文的流程图明确要求两次(规格合规和代码质量各一次)。描述改成只写触发条件「Use when executing implementation plans with independent tasks」后,代理读了正文,两次 review 都做了。描述概括流程,就等于给代理造了一条跳过正文的捷径。

描述还有个总预算。所有技能的名称加描述会拼成一份清单注入每次会话,超过预算清单被截断,尾部技能失去触发能力。7 月 16 日实测 137 个技能的描述共 36555 字符,超了预算,清单被截。同一天还发现 13 个 SKILL.md 带 UTF-8 BOM,frontmatter 解析失败,清单里描述显示为 ---,自动触发彻底失效,其中包括强制入口「标准开发工作流」。检测只要一行:head -c 3 | od -An -tx1 输出 efbbbf。这两件事后来都进了一个门禁脚本 check_skills.py:BOM、frontmatter、单条描述 ≤ 700、总量 ≤ 36k,写进技能部署清单。现在的状态是 89 个技能、22922 字符、0 警告。

强制走流程:四阶段工作流

技能可以被触发,也可以被绕过。对代码改动,项目把「标准开发工作流」写成了规范文件里的强制入口:收到任何涉及代码改动的任务,第一步必须读这个技能,宣布「Phase N」,不可跳过、不可合理化跳过。

四阶段是 Understand → Plan → Implement → Verify。每阶段有 Gate:能不能一句话说清用户要什么;知不知道要改哪些文件;什么命令能证明改动正确。Phase 2.1 是「领域技能强制触发」表:任务含 UI 界面改动就必须先读 MCP 侦察技能并拿到预制体真实结构,含协议改动就必须先读协议集成和服务端开发技能。这张表的来由是 3 月 18 日一次事故:7 个已有文档覆盖的错误全部因为没读技能。Phase 4 拆成五步 BUILD / TEST / REVIEW / DOC-SYNC / DECLARE,按复杂度分档,极简档只做编译加一行声明,其余全做。

这就是技能互相引用的骨架:入口技能按阶段和任务类型把子技能串起来,子技能不需要各自争取被触发。

技能互推:两个 When NOT to Use 指向对方

互相引用也有反面。4 月 21 日新建一个整栈测试环境,全部验收通过,客户端远程选服列表里却看不到它。原因是「把环境登记到选服列表 JSON」这一步从未被任何自动化串联,而两个相关技能互相把对方写进 When NOT to Use:整栈环境技能说「选服列表见另一个技能」,选服列表技能说「整栈环境用另一个技能」。谁都以为对方会管,流程正中间漏了一段桥。

修法写进了复盘的经验表:两个技能互指 When NOT to Use 时,至少一方的 When to Use 必须明确说「XX 场景完成后必须回头到技能 B」。配套把整栈环境技能的检查清单加了一条「客户端选服可见性」,校验脚本从「必需集合不缺」改成双向对账。

从规则文件迁移到技能:一张替换表

技能体系最初来自另一款 IDE 的规则目录。3 月 27 日盘点时是 35 个规则文件加 68 个技能目录,规则文件里一张「后端技能表」10 项有 7 项在本仓没有对应目录,还有一个 Windows 下产生的乱码重名目录。7 月 16 日规则目录整体删除,全部并入技能。

迁移不是搬文件,是逐行替换。项目专门写了一个迁移清单技能,核心是一张关键词表:第三方插件的英文技能名替换为本项目中文名(brainstorming → 头脑风暴,systematic-debugging → 系统化调试),.mdc 后缀引用改为技能名,旧机器的绝对路径改为仓库根相对表述,另一个项目残留的类名和目录判定为死引用后整行删除,gh 命令改为本项目的合并请求脚本。每条标了危害分级和处理方式,并配一个死链脚本校验清单里引用的路径是否存在。

治理:重复、过期、被绕过

近百个技能的治理,实际用到的判据有这几条。

重复不等于可合并。 7 月 4 日一次审计中,子代理判定「预制体 MCP 操作」是「UI 预制操作」的子集,实读发现前者独有一段自动绑定流程,且被另外两个技能引用,合并被降级。相反,大厅单体下四个常驻模块的布局技能内容同构,合并成一张表承载各模块差异,4 合 1。另一类「门禁加手册」分工要保留:英文名技能被 hook 硬引用、在操作预制体时弹提示,中文名技能是配套手册,正文写明前者是「自动加载的强制规范」。

过期看引用是否真实存在。 另一个项目残留的技能引用了本项目不存在的 UI 基类、目录和第三方列表组件,全仓 grep 零命中,判死。这一轮删了 20 个,包括英文模板、空壳占位、脚本全缺的。

被绕过要回到入口。 4 月 24 日「复盘一下」触发词命中、技能正文却没被读,代理输出了一份形似复盘的口头分析。修法不是改技能,是在规范文件里把「触发复盘关键词必须先读技能文件」写成红线。技能能否触发是描述的事,触发后是否遵守是规范文件的事。

另有两件值得一提。子代理调度也写成了技能:验证隔离用独立的验证者子代理消除「自己验自己」,并行实施和只读调研各有模式。以及需求侧的一条流水线:把策划文档和设计稿编译成结构化 spec.yaml,作为下游开发技能的唯一输入。

数据

  • 现存技能 89 个、约 1.76 万行、名称加描述 22922 字符、门禁 0 警告。
  • 3 月 27 日盘点 35 规则加 68 技能,后端技能表 10 项缺 7 项。
  • 7 月 16 日治理 137 → 103 → 83,13 个技能因 BOM 失去触发能力,描述总量 36555 字符超预算。
  • 「7 个已有文档覆盖的错误全部因为没读技能」直接催生了领域技能强制触发表。

教训

  • 描述只写何时用,不写做什么。 概括流程的描述会成为跳过正文的捷径。
  • 技能清单有预算。 描述肥了尾部技能失效,BOM 一个字节让技能整个失效,两者都要上门禁。
  • 强制入口写进规范文件,不写进技能。 技能负责被触发,规范文件负责触发后不被绕过。
  • When NOT to Use 必须有回程。 两个技能互相推开,中间就是没人管的空白。
  • 合并前实读,别信「子集」判断。 子代理的重复判定常不准,被引用关系和独有段落才是判据。