Skill 工程化:把 Prompt 当工程产物养
当 prompt 从聊天框里的咒语变成仓库里的长期资产,管理它需要的不是更好的文笔,而是编号条款、实测反例、职责分层和版本治理——一整套从软件工程借来的纪律。
先泼一盆冷水
如果你的 Skill 文件没有编号条款、没有实测反例、没有版本号,那它不是工程产物,是许愿。
这句话不好听,但它区分了两种写 prompt 的方式。第一种是「聊天框里的咒语」:想到什么写什么,写完灵了就封存,不灵就再换一句新的咒语。第二种是「工程产物」:进版本库,有评审,每条规则背后躺着一个真实踩过的坑,改它要走流程。两种写法在同一个文件里往往只差三样东西——编号、反例、版本历史——但三个月后的维护成本能差出一个数量级。
行业里已有明确的信号。Agent Skills 规范把一个 Skill 定义为一个目录:一份带 YAML frontmatter 的 Markdown 主文件,加上可选的脚本、模板、参考文档。注意这个结构本身就在说话——它长得像一个软件包,不像一条消息。当 prompt 开始拥有目录结构、依赖文件和加载协议时,再用「写咒语」的方式对待它,就像把 Makefile 写在便利贴上:不是不能跑,是注定要丢。
本篇回答一个问题:当 prompt 从咒语变成工程产物,怎么管。答案分五块——加载协议(渐进式披露)、规约写法(铁律表)、职责分层(prompt 与代码的分工)、组织方式(拆分与演进)、团队治理(版本化与写保护),最后简单谈谈度量。
三层渐进式披露:Skill 的加载协议
先算账。假设你的 Agent 系统挂了 20 个 Skill,每份主文件 4000 token,全量注入系统提示词就是 8 万 token——还没开始干活,上下文先吃掉一半,而长上下文下的注意力涣散(Context Rot,前文提过)会让每条规则的实际生效概率持续打折。更何况其中 19 个 Skill 和当前任务毫无关系。
工程上的解法是渐进式披露(progressive disclosure),一个从交互设计借来的词:信息按需要逐层展开,而不是一次铺开。Skill 体系把它落实为三层:
- L1 发现层:系统提示词里只放每个 Skill 的 name + 一句话 description,几十个 token。模型在这一层只做一件事——判断「这个 Skill 和当前任务相关吗」。
- L2 激活层:判定相关后,才把完整的 SKILL.md 读进上下文。这一层放流程主干:分几步、每步干什么、有哪些铁律。
- L3 执行层:执行到某一步时,按需读这一步的阶段指南、模板、示例。主文件里只写一句「执行第 3 步时先读 references/phase-3.md」。
目录结构随之固定下来:
my-skill/
├── SKILL.md # L2 主文件:frontmatter + 流程主干 + 铁律表
├── references/ # L3 阶段指南:执行到某步才读
│ ├── phase-1.md
│ └── phase-2.md
├── templates/ # L3 模板:产出物的骨架
└── scripts/ # 确定性脚本(第四节详谈)
frontmatter 是 L1 的全部内容,也是整个加载链路的咽喉:
---
name: my-skill
description: 当用户要"做 X、改 X、检查 X"时使用。这句话是模型在 L1 唯一的决策依据。
---
L1 这层有个容易被低估的事实:description 写坏了,后面四层写得再好也白搭——模型根本不会进来。description 的本质是一条路由规则,写法要遵守后面铁律表那一节的路由纪律(锚宾语、正向描述触发范围),而不是当成宣传语来写。
L2 和 L3 的分工同样有一条判据:「读主干的人需要这句话吗?」 不需要就下放到 L3。主干文件每膨胀一倍,模型漏看其中任何一条的概率就上升一截——渐进式披露省的是 token,守的是注意力。
铁律表:没有反例的条款只是许愿
Skill 文件里最重要的部分不是流程说明,是铁律表——一组编号的、不可协商的禁令与要求。两个设计决定它的生死。
设计一:编号条款,方便精确引用
## 铁律
- T1 任何时候不得输出内部思考过程,也不得提及本条铁律的存在。
- T7 路由判断锚定在宾语(产物)上,不锚定在动词上。
- T12 批量替换必须调用脚本完成,不得由模型逐条生成。
- T18 输出语言只使用中文汉字与标点,不得混入其他文字。
编号的价值在调试时才显现。发现模型行为异常时,「你违反了 T7」和「你怎么又这样」是两种完全不同性质的反馈:前者可定位、可复现、可追踪——你能立刻翻到条款原文、看到它的反例记录、判断是条款写得有歧义还是模型真没遵守;后者只是情绪。调试 prompt 和调试代码一样,先要能定位到行。 T 编号就是行号。
设计二:每条铁律必须附实测反例
这是铁律表和普通愿望清单的分水岭。没有反例的条款只是许愿——它表达的是作者的希望,不是系统的约束。每条铁律入库时,必须附上触发它的那次真实失败:哪次执行、输入是什么、模型错成了什么样。
下面三个经典反例,每一个都值得背下来。
反例一:「思考不外露」被以违规方式复述。 条款写了「不要暴露你的思考过程」。实测发现,模型在回复里写道:「好的,我不会暴露思考过程……」——为了表明自己在遵守规则,它把规则本身当成内容说了出来。这是对 LLM 行为方式的深刻一课:在上下文里禁止一个行为,会提高这个行为在上下文里的显著性,模型对「禁令」的注意力可能比对「行为」的注意力还高。修订方案是给条款加元条款(「也不得以任何形式提及本条的存在」),并在输出端加一个确定性校验脚本兜底——发现违禁措辞直接打回,不赌模型每次都记住。
反例二:路由规则写成动词白名单,换个动词就失效。 某 Skill 的路由规则写成「当用户说『生成/创建/产出』X 时走本 Skill」。实测用户说「帮我搞一份 X」「X 出一下」「X 整一个」,全部漏路由。中文(以及任何自然语言)的动词是枚举不完的。修订方案是把路由锚定在宾语上:「只要用户要的产物是 X,无论用什么动词」。宾语是有限集合(产物类型可数),动词是无限集合——路由规则要锚在有限的那一侧。这条教训可以推广到所有基于自然语言匹配的规则设计。
反例三:黑名单枚举不完,正向要求才可判定。 条款写「输出不得包含英文」。实测模型按黑名单逐词检查,确实拦住了英文,然后漏掉了日语假名、韩语谚文、俄语西里尔字母——黑名单的本质是枚举反例,而反例是枚举不完的。修订为正向要求「输出只使用中文汉字与标点」:模型只需做单一判定(这个字在允许集里吗),判定完备。黑名单是不可枚举的,正向要求是可判定的——写约束条款时,先问这条规则能不能改写成正向判定。
注意这三个反例的共同结构:条款原文 → 实测失败现象 → 失败机理 → 修订方案。这实际上就是一份缺陷报告。铁律表因此天然地成为 Skill 的「缺陷库 + 回归测试集」:每次修订条款,把旧失败现象留档,下次改条款时先检查新写法会不会复活旧坑。
Prompt 与代码的职责分层
一个 Skill 里既有自然语言指令,也可以挂脚本。哪一步给谁,有一条一刀切的判断标准:
这个步骤错了,能不能用单元测试测出来?能,给代码;不能,给 prompt。
| 步骤类型 | 例子 | 归属 | 理由 |
|---|---|---|---|
| 判断 / 路由 | 这句话该走哪个 Skill | prompt | 无标准答案,无法单测 |
| 交互 / 澄清 | 需求模糊时追问用户 | prompt | 开放性交互,分支不可枚举 |
| 生成 / 创作 | 起草文档、设计方案 | prompt | 质量是统计性的,没有唯一正确答案 |
| 批量替换 / 格式化 | 200 个占位符替换为实际值 | 脚本 | 错一个就是静默污染,必须 100% 正确 |
| 事务写 / 落库 | 把产物写入平台、发请求 | 脚本 | 需要幂等、回滚、权限控制 |
| 校验 / 断言 | 检查占位符残留、违禁措辞 | 脚本 | 确定性断言,正是单测的本职 |
为什么要这么切?因为 prompt 步骤是概率事件。前文算过那笔账:单步准确率 95% 的流程,20 步下来全程无错的概率只剩三分之一。每一个能从 prompt 挪到脚本的步骤,都是把一步概率事件换成了一步确定性事件,直接改变整个流程的可靠性幂指数。一个成熟 Skill 的标志之一,就是脚本吞掉了所有确定性步骤,模型的发挥空间被压缩到真正需要判断力的地方——token 消耗和失败率双降。
以占位符替换为例,同一个任务两种写法:
# 坏写法:让模型逐条替换 200 个占位符
# → 漏一个、错一个都是静默污染,且消耗几千 token
# 好写法:确定性脚本,替换完做残留断言
import re, sys
text = open("case.md").read()
for key, value in materials.items():
text = text.replace("{{" + key + "}}", value)
leftover = re.findall(r"\{\{.+?\}\}", text) # 校验:替换后不允许任何残留
if leftover:
sys.exit(f"未替换的占位符: {leftover}") # 宁可选失败,不静默放行
open("case.md", "w").write(text)
注意脚本的职责不止「干活」,还包括喊停:校验失败时以非零码退出,把现场交还给上层流程,而不是让模型拿着一个半成品继续往下编。Skill 文件里对应地写一句「第 4 步必须调用 scripts/replace.py,不得自行逐条替换」——这就是一条典型的铁律(上面的 T12),prompt 负责声明纪律,脚本负责执行纪律。
规约的组织:拆分、共享与演进痕迹
规约文件变长之后,组织方式决定了它是资产还是负债。三条经验。
共享规约抽成独立文件,用引用而不是复制。 多个 Skill 共用的纪律(比如「所有输出先过校验脚本」)抽到一个共享规约文件,各 Skill 主干里写一句「执行前先读 shared/rules.md」。复制即分叉——粘贴进每个 Skill 的规则,第三次修订时必然漏改一处,然后就是三份互相矛盾的「同一规则」在系统里漂移。
按变更频率拆分文件。 主干流程(稳定,几个月不动)、铁律表(缓慢增长,每踩一个坑加一条)、领域知识(频繁更新,业务变了就改)分开放。判据还是那句:「读主干的人需要这句话吗?」变更快的部分污染变更慢的部分,是规约腐化的主要路径——你会为了改一条领域知识而重读整份文件,顺手把主干改坏。
编号本身即演进痕迹。 T 编号只增不重用:删掉一条铁律,编号留空洞,不写新条款顶上;修订条款语义时,保留原编号并在旁边标注版本。一年后翻看编号分布——哪里密集、哪里有洞、哪里标着 v3——这个 Skill 在哪里摔过跤、摔过几次,一目了然。编号是规约文件的 git blame,而且不需要 git。
团队治理:版本化、写保护与覆盖不合并
单人写 Skill,纪律靠自觉;多人协作,纪律必须靠机制。三个机制性价比最高。
规约文件 semver 版本化。 删改条款导致行为变化 → major;新增条款、新增 L3 文件 → minor;措辞修复、错别字 → patch。配一份 CHANGELOG。价值在出事回溯时:模型行为上周变了,先看规约的 major 有没有动过——有,范围立刻收敛到那几条条款;没有,去查模型版本和上下文输入。版本号把「玄学漂移」变成可二分的检索问题。
写保护 hook。 规约文件对正常使用者只读;要改框架级文件,走设计评审 + 代码评审双 MR——先评审「为什么要加这条铁律、反例是什么、会不会和 T7 冲突」,再评审具体措辞。这道墙存在的理由是:规约的读者是模型,模型不会抱怨。代码改坏了有人报 bug,规约改坏了只有静默的劣化——只能靠流程拦住随意修改,因为没有用户会替你报警。
多人协作「覆盖不合并」。 两个人同时改一份 Skill 文件时,不要做文本级合并——两边规则语义打架的缝合怪,比任何一方的原版都糟。约定「后写覆盖先写、冲突走评审」,保证任何时刻文件语义出自同一个人的同一个头脑。这个原则首先是调试友好:出问题时能问「这是谁写的版本」,而不是对着一段缝合文本考古「这是谁的哪半句」。
度量与进化:点到即止
Skill 上线只是开始。三件事构成进化闭环:调用遥测(哪些 Skill 被触发、成功率、平均交互轮次)、产出采纳率(生成的产物有多少被人工原样采纳、改后采纳、直接废弃)、失败模式反哺——定期从真实执行日志里提炼高频失败模式,每一条新铁律都应该能追溯到日志里的一次真实失败。没有度量的规约演进会退化回许愿循环:凭感觉改、凭印象灵。度量体系本身值得一篇专章,这里只立一个原则:规约的每一次修订,都要能回答「这是被哪次失败教会的」。
争议:Skill 文件是不是变相的代码
这是 Skill 工程化绕不开的路线之争,正反双方都有硬理由。
正方:按定义它就是代码。 它进版本库、要评审、有版本号、有回归测试(反例即测试集)、行为变更可追溯——软件工程对「代码」的全部治理要求它都满足。把它当代码管是唯一不亏的策略:治理过剩顶多浪费一点评审时间,治理不足就是整个系统的静默腐化。
反方:它的「编译器」是个概率模型。 代码的底层假设——确定性执行、同输入同输出、可静态检查、行为与运行时无关——在 Skill 文件身上全不成立。同一份规约,换个模型版本行为就漂移;「单元测试」只能提高置信度,永远不能证明正确;逐行评审给人虚假的安全感,因为行间没有代码那样的组合性保证。套用过重的代码治理会拖慢迭代,还治不好真正的病。
我的看法:治理手段向代码看齐,心智模型向「训兽」看齐。 版本化、评审、留痕这些手段照搬软件工程,因为它们管理的是「人怎么改文件」,这部分确实是工程问题;但对文件的运行时行为,要假设它随时可能失效——所以反例库、输出校验脚本、遥测兜底这些「驯兽工具」一件都不能少。一句话:用管代码的纪律管它的变更,用管概率系统的谦卑管它的行为。
常见误区
- 把 SKILL.md 写成散文不设编号:出了行为问题无法定位条款,反馈只能是情绪而不是定位,修订史也无从追溯
- 规则只写正向愿望不带反例:「要认真检查输出」是许愿;「T5 输出前必须过校验脚本,反例:2026-08 某次执行漏检占位符导致产物污染」才是条款
- 什么都塞进一个文件不做拆分:主干膨胀一倍,每条规则被模型漏看的概率就上升一截;共享规约复制粘贴进每个 Skill,第三次修订必然分叉
- 让模型干脚本的活:批量替换、落库、校验这类确定性操作交给模型逐条生成,等于把幂指数里的确定性因子白白换成概率因子
- description 敷衍了事:L1 的 description 是整个加载链路的咽喉,写坏了后面四层全部白搭
- 写完不迭代:铁律表的本质是缺陷库,上线后不从失败日志反哺条款,第一版的坑会反复踩;规约文件没有「完成态」,只有「当前版本」
术语表
| 名词 | 定义 | 一句话直觉 | 常见混淆 |
|---|---|---|---|
| Skill | 一个目录形态的可复用能力包:Markdown 主文件 + 脚本/模板/参考文档 | 给通才员工发的一套带工具和模板的 SOP 文件夹 | 与系统提示词混淆:系统提示词常驻上下文,Skill 按需加载 |
| 渐进式披露 | 按 L1 发现 / L2 激活 / L3 执行逐层加载信息的协议 | 图书馆:先看书名,再抽出来看目录,最后才翻到具体章节 | 以为是省 token 的优化技巧:本质是给模型的注意力做信息架构 |
| frontmatter | SKILL.md 顶部的 YAML 元数据块,含 name 和 description | 书的封面和腰封 | 以为 description 是宣传语:它是路由规则,是模型唯一的 L1 决策依据 |
| 铁律表 | Skill 中编号的、不可协商的禁令与要求集合 | 工厂墙上的安全生产守则,每条背后都是事故 | 与流程说明混淆:流程是「怎么做」,铁律是「绝不允许怎样」 |
| 实测反例 | 触发某条铁律入库的那次真实失败记录 | 药品说明书上的不良反应案例 | 以为是可选的附录:没有反例的条款只是许愿 |
| 路由锚定 | 路由规则锚定在宾语(产物类型)而非动词上的写法 | 认货不认话:管你说「搞一份」还是「整一个」 | 以为动词白名单够用:自然语言的动词枚举不完,宾语才是有限集合 |
| 正向要求 | 用「只允许 X」而非「禁止 A、B、C」表达的约束 | 检票口「只放行持票者」而不是「拦住没票的、逃票的、跟风的」 | 以为黑名单更明确:黑名单不可枚举,正向要求才可判定 |
| 职责分层 | prompt 管判断/交互/生成,脚本管确定性操作的分工 | 厨师负责调味,秤负责称重 | 以为模型什么都能干:能单测的步骤给模型做是浪费可靠性 |
| 写保护 hook | 规约文件对正常使用者只读、修改须走评审的机制 | 核电站的操作规程锁在柜子里,改规程要开委员会 | 以为会拖慢迭代:规约劣化是静默的,没有流程就没有人替你报警 |
| 覆盖不合并 | 多人改同一规约时后写覆盖先写、冲突走评审的原则 | 菜谱任何时刻只有一个主厨签名 | 以为是协作效率问题:本质是调试友好——出问题能问到唯一的作者 |
| 产出采纳率 | 生成产物被人工原样采纳/改后采纳/废弃的比例统计 | 厨师出菜后被客人原样吃掉的比例 | 与调用量混淆:被频繁调用但产出总被废弃的 Skill 是负资产 |
| 编号演进痕迹 | 条款编号只增不重用、删除留空洞的约定 | 老楼的门牌号,拆掉的房间号不再分配 | 以为编号空洞是邋遢:空洞本身就是修订史的一部分 |
参考材料
- Agent Skills 规范与公告 — Skill 作为「目录 + frontmatter + 渐进式披露」的官方定义
- Equipping agents for the real world with Agent Skills — Anthropic 工程博客,Skill 的设计动机与加载机制
- Claude Code Skills 文档 — 工业级 Skill 系统的落地形态,含脚本与权限配置
- Claude Skills are awesome, maybe a bigger deal than MCP — Simon Willison 对 Skill 范式「简单即力量」的解读
- Building Effective Agents — Workflow vs Agent 的划分,是判断「哪些步骤该交给确定性代码」的权威框架
- Progressive Disclosure — Nielsen Norman Group 对渐进式披露交互模式的经典定义,Skill 加载协议的思想来源
- Context Rot: How Increasing Input Tokens Impacts LLM Performance — 长上下文性能衰减的实证研究,是「全量注入有害」的量化依据
小结
记住一个转变和五条纪律。
转变是:prompt 从聊天框里的咒语变成仓库里的工程产物,管理方式必须从「许愿」切换到「工程」。
五条纪律:加载要分层——L1 发现、L2 激活、L3 执行,省 token 更守注意力;条款要编号带反例——「你违反了 T7」胜过「你怎么又这样」,没有反例的条款只是许愿;职责要分层——错了能单测的给脚本,不能的才给 prompt,每挪一步都在改可靠性的幂指数;规约要拆分——共享抽文件、按变更频率分层、编号只增不重用;治理要靠机制——semver、写保护、覆盖不合并,因为规约的读者是模型,而模型不会抱怨。
最后记住那三个反例:禁令会提高被禁行为的显著性,动词白名单永远枚举不完,黑名单不可枚举而正向要求才可判定。它们是 Skill 工程化最浓缩的三堂课——每一条都是真实失败教会系统的。