如何写好一个 Skill:划分、结构与实践

系列第二篇。知道 Skill 是什么,和真的把它写对,中间差得其实很远。很多人第一次写 Skill,文件看起来像模像样:有 frontmatter、有步骤、有格式说明,甚至还加了几个卫星文件。结果放进工具里一跑,不触发,或者触发了也不按你想的来。

我自己后来回头看,问题通常不在"写得不够认真",而在于一开始用错了写法。有人把 Skill 写成百科全书,有人把它写成项目说明书,也有人把它写成一堆正确但没有立场的建议。这篇想解决的不是"怎么把文档写漂亮",而是:怎么把它写成一个 Agent 真会照着走的东西。

〇、先建立一个判断标准

写 Skill 之前先想清楚一件事:怎么算"好"?

一个好的 Skill 满足三个条件:

  1. 触发得准:该用它的时候,Agent 能想起来用它;不该用的时候不会误触发。
  2. 执行得稳:Agent 照着它做,十次有九次走的是同一条路、得到同样质量的结果。
  3. 活得久:项目代码改了、文件挪了,Skill 不用跟着改。

下面所有的技巧,都是在为这三个目标服务。


一、解剖一个 Skill:它只有两个部分

任何 Skill 本质上只有两部分:门牌正文

markdown 复制代码
---

name: pdf-extract

description: 从 PDF 提取文本和表格、填写表单、合并文档。当用户提到 PDF、表单或文档提取时使用。

---

↑↑↑ 这是门牌(frontmatter)


下面全是正文......

门牌(description)是整个 Skill 最重要的一句话

这里有个新手必须知道的机制:Agent 平时不读你的 Skill 正文。 它启动时只把所有已安装 Skill 的 description 装进脑子。用户提需求时,它扫一眼这些 description,觉得哪个匹配,才去读那个 Skill 的全文。

这个机制叫渐进式披露,目的是省上下文------你装了 50 个 Skill,不能让 50 篇全文天天占着 Agent 的脑容量。

所以 description 是一份合同:它是 Agent 决定"用不用你"的唯一依据。写法有固定公式:

csharp 复制代码
第一句:它能干什么。

第二句:Use when ...(什么时候用:具体的关键词、场景、文件类型)。

对比一下:

复制代码
坏:帮助处理文档。

好:从 PDF 提取文本和表格、填写表单、合并文档。

当用户提到 PDF、表单或文档提取时使用。

坏的那个,Agent 没有任何办法把它和其他文档类 Skill 区分开------等于没装。很多人的 Skill "不生效",问题九成出在 description 太模糊。

正文:把"做什么"和"背景知识"分开写

正文的最佳实践是双层结构

  • 行动层 :一步一步的指令,全部用祈使句------"先做 X"、"然后检查 Y"、"在 Z 完成前不要继续"。这是 Agent 要执行的部分。
  • 参考层:背景知识、格式说明、依赖声明,用陈述句。这是 Agent 执行时需要查阅的部分。

为什么要分开?因为混在一起时,Agent 会把背景知识误当成指令去执行,或者把关键指令当成背景扫过去。人类读混排的文档也会犯同样的错------AI 只是放大了这个问题。

一个简洁的双层模板:

markdown 复制代码
---

name: my-skill

description: 一句话说清能力。Use when [具体触发条件]。

---

## 怎么做(行动层,祈使句)

**第一步 ------ 收集需求**

问用户 X、Y、Z 三个问题,一次问一个。

**第二步 ------ 执行**

...

在测试全绿之前,不要进入第三步。 ← 关卡(Gate)

**第三步 ------ 验收**

...


## 参考资料(参考层,陈述句)

- 输出格式见 FORMAT.md

- 本 Skill 依赖项目根目录存在 CONTEXT.md,没有则先提示用户创建

二、我最常看到的三个写坏方式

1. 一上来就写太长

这不是洁癖,是机制约束。Skill 全文会被塞进 Agent 的上下文窗口,越长越贵、越长越容易被"稀释"(重要指令淹没在废话里)。(写多了就有自己优化的经验了,不要怕写不出优雅的 skill)。

内容超了怎么办?拆卫星文件

perl 复制代码
my-skill/
├── SKILL.md # 100 行以内的主入口(必须)
├── FORMAT.md # 输出格式详细说明(需要时才读)
├── EXAMPLES.md # 示例(需要时才读)
└── scripts/ # 确定性操作的脚本(需要时才执行)

SKILL.md 里只留一句引用:"输出格式见 FORMAT.md"。Agent 走到那一步、真的需要格式时,才会去读它------这是渐进式披露在 Skill 内部的第二次应用。

但注意:默认不拆。只有满足以下任一条件才拆卫星文件:

  • 内容确实超出 100 行预算
  • 内容属于明显不同的领域(比如财务 schema vs 销售 schema)
  • 某块内容很少被用到(高级功能)

新手最常见的错误是反过来:为一个 30 行就能说清的 Skill 建了五个文件。单个精炼的 SKILL.md 是简单技能的正确形态。

2. 写得太客气,像没说一样

对比两种写法:

arduino 复制代码
温和:"你可以考虑先写测试,也可以先写实现,看情况。"

有立场:"禁止先写完所有测试再写所有实现(这叫水平切片,是反模式)。

必须一个测试 → 一段实现 → 下一个测试,垂直推进。"

模型在模糊指令下会回归自己的默认行为------而你写 Skill 的初衷恰恰是要矫正默认行为。所以好的 Skill 都很"凶":

  • 点名反模式:明确写出"不要做什么",最好给反模式起个名字("水平切片"),名字让概念可以被引用和识别
  • 设关卡(Gate):用二元条件卡住流程------"复现不出来之前,禁止改代码"。注意是"禁止",不是"建议尽量"
  • 给每个立场配理由:一句"为什么"能显著提高模型的遵守率,因为它能把规则泛化到你没列举的情况

3. 写死路径,文件一挪就废

arduino 复制代码
脆弱:"打开 src/utils/triage.ts,修改第 42 行的 handleLabel 函数"

耐久:"找到处理 triage 标签的函数(搜索关键词 handleLabel),

它接受一个 label 字符串并返回新状态"

文件会改名,行号几天就过期,但接口、行为、类型签名能活很久。判断标准很简单:如果明天有人把项目文件全部重新组织一遍,你的 Skill 还成立吗?

同理:Skill 里不要写绝对路径(你的 Skill 可能被装到别人机器的不同位置)、不要写"当前日期"这种时效信息。

这三个问题是我最先看的。除此之外,还有两条很常用但不一定每次都展开讲的判断:

  • 确定性的事交给脚本,不要交给模型。 如果只是校验 JSON、批量重命名文件、格式转换,就写进 scripts/,让 Agent 去跑。
  • 依赖要分清硬软。 没有它就一定会出错的,写成硬依赖;有了更好、没有也能跑的,写成软依赖。

这两条我平时会在改第二版、第三版的时候补进去。第一版 Skill 能跑起来,比一开始就把所有规则写全更重要。


三、怎么划分:一个 Skill 该多大?

这是被问得最多的问题。答案借用 Unix 哲学:

一个 Skill 只做一件事,把它做好。

按"动作"划分,不按"领域"划分

bash 复制代码
按领域:一个巨大的 "前端开发 Skill"(里面塞了组件规范、测试、部署、性能优化......)
按动作:/tdd(测试驱动开发)、/diagnose(诊断 bug)、/triage(分类 issue)

判断粒度是否合适的试金石:你能用一个动词短语命名它吗?

mattpocock/skills 里的技能全部通过这个测试:tddtriagediagnoseto-issues(拆成 issue)、zoom-out(拉远视角)、grill-me(拷问我)。每个名字就是一个动作。

我平时怎么判断该拆还是该并

如果 description 里老出现"和""以及",而且两边的触发场景根本不是一回事,我通常就会拆。

如果正文已经长成两条几乎不相交的流程分支,我也会拆。因为这时 Agent 读起来已经不是"一个动作有几步",而像"两件事硬塞在一个文件里"。

反过来,如果两个 Skill 总是一起被触发,其中一个还只有十来行、全部作用只是给另一个铺垫,那大概率是拆过头了,应该并回去。

让 Skill 之间能"接力"------可组合性

好的 Skill 库不是孤岛集合,而是工作流网络:A 的输出刻意设计成 B 的输入。

mattpocock 的技能链是个绝佳示范:

bash 复制代码
/grill-me(拷问需求)→ /to-prd(生成 PRD)→ /to-issues(拆成 issue)

→ /tdd(逐个实现)→ /diagnose(出 bug 时诊断)

每个技能独立可用,串起来就是一条完整的工程流水线。实现可组合的手法很朴素:

  • 在 A 的文档里写明"本技能的输出可直接交给 /B 消费"
  • 共享格式文件:两个 Skill 引用同一个 FORMAT.md,而不是各自定义一遍

四、Agent(子代理)的划分:什么时候不该用 Skill,该用 Agent?

Skill 和子 Agent 经常被混为一谈,其实分工很清晰:

Skill 子 Agent
本质 一份说明书 一个独立工人(带独立上下文)
改变什么 当前 Agent 的行为方式 任务的执行结构
成本 几乎为零(读一个文件) 高(新开一个会话)

三种情况值得派子 Agent:

  1. 脏活隔离:要读 200 个文件做调研,但主对话只需要三段结论。派子 Agent 去读,免得撑爆主对话的上下文。
  2. 并行:几个互不依赖的任务(配合 worktree 隔离,见第一篇)。
  3. 角色对立:审查者不能是写代码的本人。Code review、安全审计要用独立 Agent,否则就是"自己改自己的作业"。

反过来,这些情况不要用子 Agent:任务只有两三步、需要和用户来回对话、需要主对话的完整历史。开销不值得。

最佳实践是把两者结合:用 Skill 来定义"什么时候派子 Agent、给它什么指令"。Skill 是剧本,子 Agent 是按剧本上场的演员。


五、我现在会怎么从零写一个 Skill

如果让我今天从头写一个新 Skill,我通常不会想着"把完整方法论全部落进去",而是先按下面这个顺序做:

第 1 步 ------ 回答四个问题

  1. 这个 Skill 完成什么任务?(一句话,必须是动词短语)
  2. 什么应该触发它?(关键词、场景、文件类型------这直接变成 description 的后半句)
  3. 它属于哪类?(工程类 / 生产力类 / 杂项------影响你对它的质量要求)
  4. 需要脚本吗?还是纯指令就够?

第 2 步 ------ 写 description

先写门牌再写正文。如果 description 写不清,说明你自己还没想清楚这个 Skill 的边界------回到第 1 步。

第 3 步 ------ 写行动层

祈使句,分阶段,阶段之间放关卡。问自己:模型最可能在哪一步偷懒抄近路?在那里设一个"禁止"。

第 4 步 ------ 写参考层 + 按需拆卫星文件

依赖声明(硬/软)、格式说明、与其他 Skill 的组合关系。超过 100 行才拆。

第 5 步 ------ 跑质量检查清单

  • description 包含 "Use when..." 触发条件
  • SKILL.md 在 100 行以内
  • 行动层全是祈使句,关卡是二元的("禁止 X"而非"尽量避免 X")
  • 没有文件路径、行号、时效性信息
  • 反模式有名字、立场有理由
  • 卫星文件都被 SKILL.md 引用了(没有"孤儿文件")

第 6 步 ------ 实测和迭代

开一个全新会话(避免上下文污染),用自然语言提一个应该触发它的需求。观察:触发了吗?步骤走全了吗?关卡卡住了吗?没有就回去改 description 或加关卡。

Skill 是养出来的,不是一次写成的。 每次 Agent 在某个 Skill 上跑偏,都是一次免费的需求反馈------把跑偏的原因写回 Skill 里,它就比昨天更稳一点,所以不要吝啬对你的 Skill 库进行修改, 调整。


六、新手最常踩的五个坑

  1. 把 Skill 当百科全书写:塞满所有相关知识。→ Skill 是 SOP 不是教材,只写"做这件事需要的"。
  2. description 写成自夸:"强大的 PDF 处理能力" → Agent 不吃营销话术,它要的是触发条件。
  3. 全是建议没有禁令:模型在模糊地带永远选省事的路。该禁止就禁止。
  4. 在 Skill 里硬编码自己机器的路径:换台机器就废。
  5. 写完从来不测:不开新会话实测的 Skill,等于没写。

我自己现在最在意的两件事

写 Skill 的时候,我现在最先盯的不是"格式标准不标准",而是两件更实际的事:

  1. 它会不会被想起来。 也就是 description 到底写得准不准。
  2. 它会不会在关键地方拦住模型。 也就是 Gate 到底设得狠不狠。

很多看起来很专业的 Skill,问题其实都出在这两处。要么 description 太虚,像没装一样;要么正文太温和,模型一路顺着自己的惯性就滑过去了。

写在最后

写 Skill 这件事,对我来说越来越像带新人。你不是在写一篇"解释我多懂"的文档,而是在写一份别人真能照着做的手册。区别只在于,现在这个"别人"是 Agent,而且它会在每次会话里真的去执行你写下来的东西。

下一篇我不打算继续讲抽象原则,而是直接拆一份已经被很多人反复验证过的技能库:从 mattpocock/skills 我们能学到什么。

相关推荐
nbtang20261 小时前
AI Agent 入门(三):Tool Use 入门 —— Function Calling 原理与实战
人工智能·ai·agent
新知图书1 小时前
RAG之生成技术
人工智能·agent·ai agent·智能体·langgraph
武子康1 小时前
调查研究-211 AgentBound 深度解析:AI Agent 不只要“有权限”,还要有可验证的行为治理
人工智能·llm·agent
aovenus2 小时前
Skill / Agent / Workflow 使用场景指南及对比
agent·workflow·skill
JouYY4 小时前
聊一下知识答疑Agent的“层次聚类”流程
架构·llm·agent
L3S4 小时前
Agent为什么会死循环?
人工智能·agent
云烟成雨TD4 小时前
LangFlow 1.x 系列【3】入门案例
人工智能·python·agent
墨流藏于库5 小时前
Electron 应用 macOS 自动更新的正确姿势 —— 没有 Apple Developer Program 也能用
agent
新知图书5 小时前
智能体基础架构
人工智能·agent·ai agent·智能体·langgraph