核心论点
大多数人写 Skill 的心智模型是错的。
他们把 AI 当成一个听话的下属——“我写清楚了,它应该照做。” 然后困惑为什么 AI 读完 50 条规则,该犯的错一条不少。
真相是:LLM 不是在”遵守”你的规则,它是在一个概率空间中选择下一个 token。 你的 Skill 所做的,不是”下命令”,而是改变这个概率空间的地形——让正确的输出路径变成下坡路,让错误的输出路径变成需要翻越的高墙。
一旦你用这个心智模型重新看待 Skill 设计,很多”技巧”就不再是技巧,而是必然的推论。
一、为什么 90% 的 Skill 是废纸
先看一个反面教材:
## Rules- 代码要有良好的错误处理- 保持函数简短- 注意性能- 写清晰的注释这四条规则看起来合理,但对 LLM 来说等于没写。原因有三:
第一,模糊即自由。 “良好的""简短的""注意”——这些词给了模型巨大的自由裁量空间。概率模型在有自由裁量空间时,会倾向于选择生成概率最高的路径——也就是最”平庸”的输出。
第二,声明不产生动作。 “保持函数简短”是一个状态描述,不是一个动作指令。模型读完会”知道”这件事,但知道 ≠ 执行。就像你知道该早睡,但你还是在刷手机。
第三,没有验证闭环。 规则写了,但没有检查点。模型没有任何机制”回头看看自己有没有遵守”。它是逐 token 生成的,注意力会随序列长度衰减,开头的规则到 3000 token 时已经是远处的微弱信号。
理解了这三个失败原因,解决方案就清晰了:消除模糊、制造动作、强制验证。
二、Skill 的物理结构(30 秒速览)
skill-name/├── SKILL.md # 唯一必需文件:元数据 + 执行指令├── scripts/ # AI 可直接运行的脚本├── references/ # 按需加载的参考文档(省 token)└── assets/ # 模板和静态资源SKILL.md 内部分两层:
┌──────────────────────────────────────────────┐│ YAML Frontmatter(~100 tokens) │ ← 常驻内存,用于触发判断│ 只回答一个问题:"什么时候该用我?" │├──────────────────────────────────────────────┤│ Markdown 正文(< 5000 tokens) │ ← 触发后才加载│ 只回答一个问题:"具体怎么做?" │└──────────────────────────────────────────────┘唯一需要记住的铁律: description 只写触发条件,绝不总结流程。否则 AI 会照着 description 干活,跳过你精心设计的正文。
# ❌ 把流程写进了 description —— AI 会跳过正文description: 从稳定性、性能、可读性三维度审查代码,先列问题再给建议
# ✅ 只写触发条件description: 当用户提交代码要求审查时使用三、五个设计模式(核心章节)
以下不是”建议”,是从 LLM 的生成机制推导出的必然策略。
模式 1:动作化——把名词变成动词
LLM 看到动词时会”启动执行”,看到名词时会”表示理解”。
# ❌ 名词式(声明知识)代码审查需要关注错误处理、边界条件和资源释放。
# ✅ 动词式(触发动作)1. 搜索所有 async 函数,检查每一个是否有对应的 try-catch2. 列出所有外部输入参数,逐个验证是否有 null/undefined 防护3. 找到所有资源获取点(连接、文件句柄),确认每一个都有释放逻辑区别不只是”更具体”——而是前者让模型停留在”理解”状态,后者把模型推入”执行”状态。这是两种完全不同的生成模式。
转化公式:
"注意 X" → "搜索所有 X 的实例,逐个检查 [具体标准],列出不合格项"模式 2:检查门——规则 × 检测 × 阻断
单独的规则是建议。规则 + 检测方法 + 阻断条件才是约束。
# ❌ 裸规则(模型会"忘记")函数不超过 30 行。
# ✅ 检查门(模型不得不执行)## 函数长度检查1. 统计每个函数的行数2. 行数 > 30 的函数标记为 WARNING3. 行数 > 50 的函数标记为 BLOCK
阻断条件:存在任何 BLOCK 级函数时,必须先完成拆分建议,才能继续后续步骤。检查门三要素:
| 组件 | 作用 | 缺失后果 |
|---|---|---|
| 规则声明 | 定义标准 | 模型不知道标准 |
| 检测动作 | 强制模型去验证 | 模型”以为”自己遵守了 |
| 阻断条件 | 不通过不能继续 | 模型发现违规但跳过 |
模式 3:注意力锚点——对抗长序列遗忘
LLM 的注意力分布不均匀:开头和最近的内容权重最高,中段最容易被忽略。
这意味着在一个 3000 token 的 Skill 中,你在第 200 token 写的规则,到模型生成第 2000 个 token 时,影响力已经大幅衰减。
对策:三层防御架构
## Overview(开头声明——第一次曝光)核心原则:先完成根因分析,再给修复建议。绝无例外。
## Steps(中段执行——第二次曝光)### Step 3 完成后 → 中途自检- [ ] 我是否已经完成了根因分析?- [ ] 我是否在没有根因的情况下给了建议?→ 如果后者为是,删除建议,回到 Step 2 重做。
## Final Checkpoint(结尾拦截——第三次曝光)输出前最终确认:- [ ] 根因分析是否有完整的因果链(至少 3 层 Why)- [ ] 每条修复建议是否都能追溯到具体根因
未通过以上检查的内容不得出现在最终输出中。同一条规则出现三次,但不是简单重复——开头是声明,中段是动作化的自检,结尾是阻断性的最终关卡。
模式 4:堵死逃逸路径——借口反驳表
LLM 有一种行为模式我称之为”优雅逃逸”:它会用看似合理的话术跳过困难步骤。
"这段代码比较简洁,没有明显问题。" ← 翻译:我不想逐行检查"建议用户自行验证。" ← 翻译:我不确定,但不想承认"其余部分保持不变。" ← 翻译:我懒得输出完整内容解法:把高频逃逸路径预置为”被禁止的输出模式”。
## 禁止的输出模式
以下表述如果出现在你的输出中,说明你正在偷懒,必须删除并重做:
| 禁止输出 | 应替换为 ||:---|:---|| "代码整体没有问题" | 列出你具体检查了哪些路径,每条的结论 || "建议用户自行测试" | 给出具体的测试命令和预期结果 || "其余保持不变" | 输出完整内容,或明确列出"未修改的部分"清单 || "可能是 X 导致的" | 给出验证是否为 X 的具体步骤 |
触发上述任何一条时,回退当前步骤重做。这不是”提醒”模型——这是在概率空间中设置路障。当模型即将生成”代码整体没有问题”这个 token 序列时,它”知道”这条路径被明确标记为错误,概率会显著降低。
模式 5:渐进式信息投放——控制认知负荷
人的工作记忆容量是 7±2 项。LLM 的有效注意力窗口虽然更大,但同样遵循”信息越多,单条信息影响力越低”的规律。
策略:正文只放执行指令,背景知识按需加载。
## Step 2: API 兼容性检查
检查所有外部 API 调用是否符合 v3 规范。详细规范见:[API v3 迁移指南](references/api-v3-migration.md)
仅加载你需要检查的部分,不要一次性读取整个文档。Token 预算分配原则:
| 内容类型 | 位置 | 理由 |
|---|---|---|
| 触发条件 | YAML description | 必须始终在内存中 |
| 执行步骤 + 规则 | SKILL.md 正文 | 触发后加载,是核心指令 |
| 参考文档 > 100 行 | references/ | 按需加载,避免挤占注意力 |
| 代码模板 | assets/ | 需要时再读取 |
| 自动化脚本 | scripts/ | AI 调用即可,无需理解全部 |
四、四种 Skill 骨架
选对骨架再填内容,事半功倍。
A. 工作流型
触发 → Step 1 → [产出物] → Step 2 → [产出物] → ... → 交付 ↓ 失败 异常处理 / 回退 / 升级用于: 步骤有明确先后依赖关系的任务。
B. 检查清单型
加载清单 → 逐项检查 → 标记状态(Pass/Warn/Block)→ 汇总 → 判断是否通过用于: 确保覆盖面的审查型任务。
C. 生成器型
接收输入 → 校验输入完整性 → 按模板生成 → 校验输出质量 → 交付用于: 从少量输入产出标准化文档。
D. 分析决策型
收集现象 → 强制多维度分析 → 根因推导 → 方案对比 → 输出结论 ↑ 借口反驳表拦截偷懒用于: 需要深度思考、防止浅层回答的场景。
五、完整示例:代码审查 Skill
将上述所有模式整合为一个可直接使用的 Skill:
---name: code-reviewdescription: > 当用户提交代码片段或 diff 要求审查时使用。 不适用于:代码生成、格式化、简单语法纠错。---# Code Review
## Core Principle先理解意图,再逐项审查,最后结构化输出。禁止只看前 20 行就开始下结论。禁止输出"整体不错"类空话。
## Steps
### Step 1: 全局理解- 通读所有提交的代码- 用一句话概括:"这段代码的目的是 ____"- 识别核心逻辑路径和数据流方向
### Step 2: 三维度审查
对每个维度执行检查门:
#### 稳定性1. 搜索所有 async/await 调用 → 每个是否有 try-catch 或 .catch2. 列出所有外部输入 → 每个是否有 null/undefined/类型校验3. 找到所有资源获取点 → 每个是否有释放/关闭逻辑4. 识别并发场景 → 是否有竞态条件风险
#### 性能1. 识别所有循环 → 有无嵌套循环可降低复杂度2. 搜索重复计算 → 是否可缓存或提取3. 找到 I/O 操作 → 是否可批量化或并行化
#### 可读性1. 统计每个函数行数 → > 30 行标记 WARNING,> 50 行标记 BLOCK2. 检查所有命名 → 是否能脱离上下文理解含义3. 搜索魔法数字和硬编码 → 逐个判断是否应提取为常量
### Step 2.5: 中途自检 ⚠️- [ ] 三个维度是否每个都实际检查了(不是声明"已检查",是有具体发现或"检查路径 X,未发现问题")- [ ] 是否有跳过的检查项?如有,补做。
### Step 3: 结构化输出
## Output Format
### 一句话总评[具体描述主要问题类型和严重程度分布]
### 问题清单
| # | 维度 | 等级 | 位置 | 问题 | 修复建议 ||:--|:-----|:-----|:-----|:-----|:---------|
等级定义:- P0: 会导致运行时错误或安全漏洞,必须修- P1: 影响可维护性或性能,强烈建议修- P2: 代码质量优化,可选
### 亮点(如有)[具体指出设计优秀之处及原因]
## Forbidden Outputs
| 禁止出现的表述 | 替代方案 ||:---|:---|| "代码整体质量不错" | 指出具体的优秀设计,或不写亮点部分 || "建议添加更多测试" | 给出具体应该测试哪些路径 || "可能存在性能问题" | 量化:什么输入规模下、什么复杂度、影响多大 || "其他部分没有问题" | 列出你检查了哪些路径,每条的结论 |
## Escalation- 代码超过 500 行 → 建议用户分批提交- 发现安全漏洞 → 置为 P0,输出开头加 🚨 标记- 无法判断业务意图 → 先提问确认,不要猜测后审查
## Final Gate输出前扫描自己的回答:1. 是否触发了 Forbidden Outputs 中的任何一条?→ 删除重写2. 每个维度是否至少有一条具体发现(含"已检查无问题")?→ 补全3. 每条修复建议是否具体到可直接实施?→ 模糊的要补充代码示例六、Skill 写完后的调试循环
写完不是结束,是开始。 好的 Skill 是调试出来的,不是设计出来的。
调试方法:对抗性测试
写完后,故意用以下方式测试你的 Skill:
1. 给它一个极简输入,看它会不会偷懒2. 给它一个超长输入,看中段规则是否被遗忘3. 给它一个边界 case,看异常处理是否触发4. 连续跑 3 次同样的输入,看输出一致性迭代公式
每次 AI 犯错 → 分析属于哪种失败模式:
模糊导致的? → 加量化标准没执行? → 把名词改成动词中段忘了? → 加中途检查点找借口跳过了? → 加进 Forbidden Outputs超出能力了? → 加 Escalation 条件记录每次修改的原因(哪怕一行注释),三个月后你会感谢自己。
七、设计原则速查
| # | 原则 | 一句话 |
|---|---|---|
| 1 | 单一职责 | 一个 Skill 只做一件事 |
| 2 | 动作优先 | 动词 > 名词,指令 > 声明 |
| 3 | 量化一切 | 能写数字的地方绝不写形容词 |
| 4 | 三层防御 | 开头声明 + 中途自检 + 结尾拦截 |
| 5 | 堵死逃逸 | 预判偷懒路径,设为禁止输出 |
| 6 | 渐进披露 | 正文 < 500 行,背景知识按需加载 |
| 7 | 人工兜底 | 超出能力时停止,不要硬撑 |
| 8 | 持续调试 | 每次翻车都是下一条规则的来源 |
结语
回到开头的核心论点:
你不是在”告诉” AI 做什么。你是在一个高维概率空间中——用动作指令降低正确路径的生成阻力,用检查门和阻断条件抬高错误路径的生成成本,用注意力锚点确保关键约束在整个生成过程中持续施加影响。
这就是 Skill 设计的全部本质。
当你用这个视角审视自己写的每一行指令时,你会自然地问出正确的问题:
- “这句话会改变概率分布吗?还是只是让我自己感觉写了?”
- “这条规则有检查机制吗?还是全靠 AI 自觉?”
- “3000 token 之后,这条约束还能被’感知到’吗?”
能诚实回答这三个问题的人,写出的 Skill 不会差。