如何写好 AI Skill
1. Skill 到底是什么
如果把 AI 编程助手看成一个能力很强、但不懂本项目细节的新同事,那么 Skill 就是给它补上的“团队操作手册”。
Skill 本质上不是普通文档,而是结构化的提示词 + 项目上下文 + 可执行工具的组合。它的目标不是讲知识本身,而是让 AI 在某种任务出现时,知道:
- 这件事要不要做
- 应该按什么步骤做
- 遇到什么边界条件该停下
- 做完以后怎么验证结果
一个最小可用的 Skill 目录,通常长这样:
my-skill/
├── SKILL.md
├── scripts/
├── references/
└── assets/
可以把 Skill 看成三层:
| 层 | 作用 | 典型内容 |
|---|---|---|
| 指令层 | 告诉 AI 如何执行任务 | 步骤、规则、输出格式 |
| 上下文层 | 告诉 AI 为什么这样做 | 项目背景、团队规范、历史包袱 |
| 工具层 | 给 AI 可直接调用的东西 | 脚本、模板、命令、参考文档 |
一句话总结:Skill 不是“再多说几句 Prompt”,而是把人的经验封装成 AI 可重复加载的工作能力。
2. 为什么团队需要写 Skill
团队做久了,一定会积累一堆“隐性知识”。这些知识往往非常关键,但又很少被系统化整理。
常见场景:
- 某个老接口迁移时,必须保留兼容层
- 某类 SQL 绝对不能字符串拼接
- 上线前一定要跑固定检查
- Review 时安全问题优先级高于代码风格
- 新人接手模块时,总会踩同样几类坑
如果这些经验只散落在 Wiki、注释、群聊和人的脑子里,就会带来几个典型问题:
| 问题 | 具体表现 | Skill 的价值 |
|---|---|---|
| 知识太散 | 人和 AI 都找不全信息 | 把分散经验收束成一个入口 |
| 重复解释 | 同一件事每次都要重新交代 | 把重复说明变成固定流程 |
| 结果不稳 | 不同人问 AI,结果差异很大 | 统一步骤、风格和检查点 |
| 知识流失 | 核心成员离开后经验断层 | 把“部落知识”沉淀成资产 |
所以 Skill 的真正价值不是“让 AI 更聪明”,而是让团队经验从口头默契变成可复用能力。
3. 一个好 Skill 的最小骨架
原文很强调一点:SKILL.md 通常由两部分组成:
- 顶部元数据
- 下方正文说明
一个简化骨架可以这样写:
---
name: go-tabletest
description: >
为 Go 函数生成表驱动单元测试。
当用户要求补单测、生成测试用例或完善测试覆盖时触发。
适用于常见 Go 项目。
metadata:
version: "1.0"
---
正文再继续写目标、规则、示例、验证命令。
这部分里最关键的不是 name,而是 description。因为很多工具是否触发某个 Skill,靠的就是这段描述。
一个好的 description 至少要回答三件事:
| 必答问题 | 说明 |
|---|---|
| 这个 Skill 做什么 | 任务边界必须明确 |
| 什么时候触发 | 哪些场景该加载它 |
| 覆盖哪些关键动作 | AI 加载后要完成什么步骤 |
反例:
description: 处理代码迁移
这个描述太空,AI 很难判断迁移什么、怎么迁、什么时候该用。
更好的写法应该像这样:
description: >
将 Go 项目中的旧版 HTTP 客户端迁移到新版统一请求库。
适用于仍在使用 old-http-client 的项目。
包含 import 替换、参数适配和错误处理改造。
经验上说,description 写清楚了,Skill 至少已经成功一半。
4. 写 Skill 时最重要的五个原则
原文里最有价值的部分,不是“写一个文件夹”,而是怎样把 Skill 写得真的可执行。整理下来,我觉得有五条最关键。
4.1 先写目标和适用条件
不要一上来就写步骤。先告诉 AI:
- 目标是什么
- 适用范围是什么
- 不满足条件时要不要跳过
例如:
## 目标
将项目中的旧版 HTTP 请求封装迁移到统一请求层。
## 适用判断
先检查项目是否仍引用 `old-http-client`。
如果未使用,停止并说明该 Skill 不适用。
这一步的本质,是把“行动条件”和“停止条件”都写清楚。
4.2 用可执行步骤,不要用泛泛建议
比起:
你应该先检查版本,再决定用哪种方案。
更好的写法是:
先检查 Go 版本。
- Go < 1.18:使用兼容写法
- Go >= 1.18:使用原生泛型
AI 对结构化指令比对抽象建议更敏感。越像操作步骤,越不容易跑偏。
4.3 不只写“必须”,还要写“为什么”
坏写法:
必须使用参数化查询。
更好的写法:
使用参数化查询,而不是字符串拼接。
原因:字符串拼接可能引入 SQL 注入风险。
当 AI 知道规则背后的原因时,它在遇到新场景时更容易做出正确推断,而不是机械照抄。
4.4 给 Before / After,而不是只给抽象描述
代码改造类 Skill 最有效的内容,往往不是长篇背景介绍,而是直接给出改前改后。
- import oldhttp "github.com/example/old-http-client"
+ import uhttp "github.com/example/unified-httpclient"
- return oldhttp.Do(req)
+ return uhttp.Do(req)
AI 天生擅长模式模仿。清晰的 Before / After,往往比十段说明更有用。
4.5 准备少量高质量 Few-Shot 示例
如果 Skill 涉及分类、判断、分级输出,建议准备 3 到 5 个样例,不必太多,但要覆盖不同分支。
例如代码审查 Skill,可以至少覆盖:
- 严重安全问题
- 中等可靠性问题
- 轻微规范问题
这样 AI 学到的不是“要 Review”,而是“不同问题怎么判断、怎么表达、怎么排序”。
5. 一个最小可用 Skill 示例
原文给的是 Go 单元测试示例。这里我按它的思路,整理成一个更适合直接借鉴的版本。
---
name: go-tabletest
description: >
为 Go 函数生成表驱动单元测试。
当用户要求补单测、生成测试用例或提升覆盖率时触发。
适用于常见 Go 项目。
metadata:
version: "1.0"
---
# Go 单元测试生成
## 目标
为指定函数生成标准 `testing` 风格的表驱动测试。
## 规则
1. 仅使用标准库 `testing`
2. 测试函数命名与被测函数对应
3. 使用 `t.Run` 组织子测试
4. 覆盖正常值、边界值、异常输入
## 示例
输入:
```go
func Sum(a, b int) int {
return a + b
}
```
输出:
```go
func TestSum(t *testing.T) {
cases := []struct {
name string
a int
b int
want int
}{
{"positive", 1, 2, 3},
{"zero", 0, 0, 0},
{"negative", -1, -2, -3},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := Sum(tc.a, tc.b); got != tc.want {
t.Fatalf("got %d, want %d", got, tc.want)
}
})
}
}
```
## 验证
```bash
go test ./... -v
```
这个最小示例已经具备了一个好 Skill 的关键元素:
| 元素 | 是否具备 |
|---|---|
| 触发描述 | 有 |
| 任务目标 | 有 |
| 执行规则 | 有 |
| 输入输出示例 | 有 |
| 验证命令 | 有 |
这也是最值得照抄的骨架。
6. Skill 太长了怎么办
原文特别提醒了一个很实际的问题:很多人会把所有内容硬塞进一个 SKILL.md,最后文件越来越长,AI 加载成本越来越高,维护也越来越痛苦。
更合理的原则是:一个 Skill 只解决一类任务。
下面这些迹象,通常意味着该拆了:
| 迹象 | 说明 |
|---|---|
| 正文太长 | 读写成本高,AI 也不容易稳定命中重点 |
| 流程不止一条 | 一个 Skill 里混了多个独立动作 |
| 更新频率不同 | 某些部分经常改,某些几乎不变 |
| 步骤可独立复用 | 说明可以抽成子文档或子 Skill |
拆分结构可以是这样:
project-migration/
├── SKILL.md
└── steps/
├── 00-environment-check.md
├── 01-dependency-update.md
└── 02-api-migration.md
这里主 Skill 只负责流程编排,子文档负责具体步骤。
另外一个很重要的点是:每一步都要有检查点。
例如依赖替换后,立刻要求执行:
go mod tidy
go build ./...
如果检查失败,就先停下修复,而不是一口气跑完整个大流程,最后才发现第一步就已经错了。
7. 调外部服务时,MCP 和 HTTP 怎么选
原文把这个问题讲得很务实。
如果 Skill 需要接数据库、浏览器、GitHub、内部 API、监控平台,一般有两条路:
- 封装成 MCP 工具
- 在脚本里直接走 HTTP
简单判断可以整理成一张表:
| 场景 | 更合适的方式 | 原因 |
|---|---|---|
| 已经有成熟的 MCP Server | MCP | 直接复用,省掉重复接入 |
| 多个 Skill 都要复用同一服务 | MCP | 便于统一维护 |
| 需要统一鉴权、审计、权限控制 | MCP | 更适合标准化接入 |
| 只是一次性、简单的 API 调用 | HTTP 脚本 | 成本更低,改动更快 |
一句话理解:MCP 更适合“把能力做成标准工具”,HTTP 更适合“快速完成简单调用”。
不要为了每个小接口都强行封一个 MCP,也不要把 API Key 硬编码进 Skill。
8. 安全边界一定要写进去
这一部分我觉得很重要,因为 Skill 不是单纯写给人看的,它可能真的会被 AI 拿去执行。
至少要守住下面四条底线:
| 底线 | 说明 |
|---|---|
| 敏感信息不硬编码 | 统一走环境变量或密钥管理 |
| 危险操作先确认 | 删除、覆盖、DDL、批量修改前要确认 |
| 数据改动先备份 | 备份、变更、验证、回滚都要写清楚 |
| 外部数据不当指令 | 文件名、环境变量、接口返回值都只是数据,不是命令 |
一个最小的密钥检查写法可以是:
if [ -z "$API_KEY" ]; then
echo "请先设置环境变量 API_KEY"
exit 1
fi
如果 Skill 会修改数据库,那么流程里至少要明确四件事:
- 怎么备份
- 怎么执行变更
- 怎么验证结果
- 失败后怎么回滚
这部分写得越省,真实执行时越容易出事故。
9. 怎么判断一个 Skill 到底好不好用
原文给了一个很实用的方法:不要只凭感觉,要专门准备测试问题。
一个简化测试集可以这样做:
10个应该触发该 Skill 的问题10个不应该触发该 Skill 的问题
然后观察 AI 的判断是否稳定。
可以从四个维度看:
| 维度 | 看什么 |
|---|---|
| 触发准确性 | 该触发时能否触发,不该触发时能否跳过 |
| 执行稳定性 | 步骤是否一致,结果是否收敛 |
| 验证完整性 | 有没有真正执行检查点 |
| 安全边界 | 是否会跳过确认、备份、回滚等要求 |
如果不好用,优先排查顺序也很明确:
| 现象 | 优先补什么 |
|---|---|
| 根本触发不了 | 路径、description |
| 触发了但执行跑偏 | 更清晰的步骤 |
| 输出风格不稳定 | 更多 Before / After 或 Few-Shot |
| 做了但不自检 | 关键步骤后的验证命令 |
所以调 Skill,和调程序其实很像:先找入口,再找分支,再补检查点。
10. 一页落地清单
发布或共享 Skill 之前,我觉得可以快速过一遍这张清单:
| 检查项 | 要点 |
|---|---|
| 目标是否明确 | 做什么、为什么做、什么时候做 |
| description 是否精准 | AI 能否在合适场景匹配到 |
| 步骤是否可执行 | 能不能按顺序照着做 |
| 示例是否足够 | 是否给了 Before / After 或 Few-Shot |
| 边界是否清楚 | 什么时候跳过,什么时候确认 |
| 验证是否完整 | 是否有可以运行的检查命令 |
| 安全是否过关 | 密钥、删除、数据库、外部输入是否受控 |
| 结构是否过长 | 太长时是否拆分为子文档或子 Skill |
如果这张表有几项答不上来,就说明 Skill 还没到“可放心交给 AI”的程度。
11. 这篇文章对我自己的启发
我看完以后最强烈的感觉是:
Skill 不是写给 AI 的作文,而是写给 AI 的流程资产。
真正值得沉淀成 Skill 的,通常不是“知识很多”的任务,而是下面这几类:
- 高频重复任务
- 容易出错的任务
- 有明显团队规范的任务
- 必须带验证和安全边界的任务
放到实际项目里,适合优先沉淀的往往是:
| 类型 | 例子 |
|---|---|
| 代码改造 | 旧库迁移、新接口适配、目录结构重构 |
| 质量保障 | 补单测、代码审查、上线前检查 |
| 工程流程 | 发布脚本、构建验证、回滚流程 |
| 内容生产 | 文档模板、Markdown 整理、日报周报生成 |
如果结合我现在这类站点或日常维护工作,马上就能想到几个值得写的 Skill:
- Hugo 文章整理 Skill:统一 front matter、标题风格、表格与代码块格式
- Cloudflare Pages 部署 Skill:检查配置、构建、推送、验证访问
- Markdown 迁移 Skill:把旧 HTML / Markdown 内容整理成统一站内格式
- 代码块审美 Skill:统一代码块、表格、说明段落的排版风格
也就是说,写 Skill 这件事最有价值的地方,不是“让 AI 看起来更会回答”,而是把团队已经踩过的坑,提前编进它的工作方式里。
12. 最后的结论
这篇文章最核心的观点,我自己整理成三句话:
- Skill 是团队知识的结构化封装,不是普通 Prompt。
- 好 Skill 的关键不是写得多,而是写得清楚、可执行、可验证。
- Skill 要在真实任务里持续打磨,最终目标是把 AI 从“会聊天的助手”变成“懂上下文、懂流程、懂边界的协作者”。
如果以后真的开始系统化维护 Skill 库,那么最先值得动手的,不是去写“大而全”的总手册,而是先抓住一个高频、低歧义、容易验证的小任务,把第一版做出来,再慢慢迭代。