☰
Agent Skill 从能跑到稳定跑:SKILL.md 编写原则与实战指南
2026/10/4 8:02:49 网站建设 项目流程

1. 从“能跑”到“好用”:Skill 到底在解决什么问题

这两年做 Agent 的人越来越多,但真正把 Agent 落到生产环境里的人都会遇到同一个坎:模型本身够聪明,工具也接了一堆,可一到具体任务上,输出就是不稳定。同一个需求,今天跑出来是满分答案,明天跑出来就缺胳膊少腿。很多人第一反应是换模型、调温度、加 few-shot,折腾一圈发现治标不治本。

问题往往不在模型,而在Skill这一层没写好。

先把概念对齐一下。这里说的 Skill,指的是给 Agent 封装的一个可复用能力单元——它通常由一份SKILL.md描述文件加上若干脚本、模板、参考资料组成,Agent 在需要的时候加载它,按照里面定义的流程和规范去完成某类任务。你可以把它理解成给 Agent 写的“岗位操作手册”:不是告诉它“你是个聪明的助手”,而是告诉它“遇到这类活,第一步干什么、第二步干什么、什么情况该停下来问人、输出成什么格式”。

热搜里出现的skill-creator、SKILL.md、skill插件、codex skill、agent skill这些词,本质上都指向同一件事:怎么把人的经验固化成 Agent 能稳定执行的结构化指令。而去ai味的skill、狗头军师skill、打斗动作提示词skill、ai备课skill这些更具体的词,则说明大家已经在往垂直场景里钻了——不再满足于“通用助手”,而是要“某个具体活儿干得特别溜的专家”。

这篇东西我想聊的就是:一份好的 Skill 到底长什么样,写的时候哪些地方最容易翻车,以及怎么从零把一份 Skill 打磨到“换个模型也能稳定跑”的程度。适合已经在做 Agent 开发、被输出不稳定折磨过的朋友,也适合刚接触SKILL.md想搞清楚它和普通 Prompt 区别的新手。

2. 先想清楚:Skill 和 Prompt、Tool 的边界在哪

2.1 三者不是一回事,混着用必翻车

很多人写 Skill 写着写着就写成了一个大 Prompt,这是最常见的误区。我先把三者的职责划清楚:

层次职责典型内容变化频率
System Prompt定义 Agent 的身份、语气、底线“你是一个严谨的技术助手”极低
Tool提供原子能力读文件、发请求、跑命令低
Skill编排能力完成一类任务流程、判断分支、输出规范中

Prompt 管“你是谁”,Tool 管“你能做什么动作”,Skill 管“这类活该怎么干”。一份好的 Skill 里会引用 Tool,也会包含局部指令,但它本身的核心价值是流程编排和判断逻辑。

举个具体的例子。假设你要做一个“代码审查”能力。Tool 层面你可能有read_file、run_linter、git_diff。System Prompt 告诉 Agent“你是个资深工程师”。而 Skill 要写的是:先看 diff 范围,再按“正确性→边界条件→性能→可读性”的顺序过一遍,遇到涉及并发的地方必须单独列出来,最后按固定模板输出,每条问题标注严重等级。这套东西才是 Skill。

2.2 为什么不能全塞进 System Prompt

有人会问,那我直接把这些流程写进 System Prompt 不就行了?短期看行,长期一定崩。原因有三个。

第一是上下文污染。System Prompt 是每一轮对话都要带的,你把十个 Skill 的流程全塞进去,token 消耗爆炸不说,模型注意力还会被稀释,真正当前任务相关的指令反而被淹没。热搜里那个llm的token三个点key我是谁、query我在找什么、value我能提供什么说的就是这个——上下文里每一段都在争夺模型的注意力权重。

第二是加载时机。Skill 的核心优势是按需加载。Agent 平时不需要知道“怎么写周报”,只有当用户说“帮我写个周报”时,才把对应的 Skill 拉进来。这样既省 token,又让模型在那一刻只专注于这一件事。

第三是可维护性。Skill 是独立文件,可以版本管理、可以单独测试、可以复用。塞进 System Prompt 里,改一处动全身,团队协作时简直是灾难。

2.3 Skill 的合理粒度

粒度是另一个容易走偏的地方。太粗,一个 Skill 管十件事,等于没拆;太细,每个动作一个 Skill,Agent 光加载就累死了。

我的经验是:一个 Skill 对应一类“用户会一次性提出来的完整任务”。比如“把这段会议记录整理成结构化纪要”是一个 Skill,“把纪要翻译成英文”是另一个 Skill。用户不会说“先帮我做第一步再做第二步”,他说的是一句完整需求,那这个需求边界就是 Skill 的边界。

判断粒度是否合适,有个简单的测试:如果这个 Skill 的描述里出现了“或者”“根据情况选择”这类词超过三次,说明它该拆了。

3. SKILL.md 的结构:一份好 Skill 的骨架长什么样

3.1 元信息区:让 Agent 知道“什么时候该用我”

SKILL.md开头通常是一段元信息,最关键的是name和description。很多人随手写一句“这是一个处理文档的 Skill”就完事了,这是大忌。

description是 Agent 做 Skill 路由时唯一的判断依据。它要回答的是:什么情况下该加载我。所以写法上要包含触发场景,而不是功能描述。

对比一下:

  • 差的写法:处理会议记录
  • 好的写法:当用户提供会议录音转写文本、聊天记录或零散会议笔记,需要整理成结构化纪要时使用。适用于需要提取决议、待办、责任人的场景。

后者明确说了输入形态、输出目标、适用场景,Agent 匹配起来准确率高得多。热搜里book to skill、ai备课skill这类垂直 Skill,描述里几乎都会把“输入是什么、输出是什么、什么场景用”写死。

3.2 指令区:流程要写成“可执行”而不是“可理解”

指令区是 Skill 的主体。这里最大的坑是:人写流程习惯写“理解”,但 Agent 需要的是“执行”。

比如“仔细分析文档内容,提取关键信息”——这句话对人来说没问题,对 Agent 来说等于没说。什么叫仔细?什么叫关键?提取成什么形式?

改成可执行的写法:

  1. 通读全文,标记出所有包含数字、日期、人名、决策动词(决定、同意、否决)的句子
  2. 对每个标记句,判断它属于“决议”“待办”“信息同步”中的哪一类
  3. 决议类提取为“事项 + 结论”两字段;待办类提取为“事项 + 责任人 + 截止时间”三字段
  4. 字段缺失时标注“未明确”,不要自行推断

看到区别了吗?后者每一步都有明确的动作、判断标准和输出格式。Agent 执行起来几乎没有歧义空间。

3.3 示例区:给一两个“标准答案”比讲十句道理管用

Skill 里放示例(few-shot)的效果,比在指令里反复强调要强得多。但示例不是越多越好,两到三个高质量示例通常就够了,多了反而占上下文。

示例的选择有讲究:要覆盖典型情况和边界情况各一个。典型情况让 Agent 知道正常长什么样,边界情况让 Agent 知道遇到异常怎么处理。

比如一个“把自然语言转成 SQL”的 Skill,典型示例是常规查询,边界示例应该放一个“用户描述模糊、需要反问澄清”的案例。这样 Agent 遇到模糊需求时,就知道该反问而不是瞎猜。

3.4 资源区:脚本和模板怎么挂

Skill 目录下通常还会有scripts/、templates/、references/这些子目录。原则是:能用脚本确定性完成的,绝不交给模型。

比如格式化输出、字段校验、日期计算这类活,写个 Python 脚本让 Agent 调用,比让模型“自己算”靠谱一百倍。热搜里skill脚本、skill编码247、skill编码193这些词,说的就是 Skill 里挂脚本这件事。

模板同理。如果输出格式固定,直接给一个模板文件,让 Agent 往里填,比在指令里描述格式要稳定得多。

4. 写出好 Skill 的核心原则:从“能跑”到“稳定跑”

4.1 原则一:把判断逻辑显式化

模型最不擅长的就是“隐含判断”。你写“如果内容较长则分段”,模型对“较长”的理解每次都可能不一样。必须给量化标准。

我一般会这样处理:

  • 涉及数量:给具体阈值,如“超过 500 字则分段”
  • 涉及分类:给完整枚举,如“分为技术类、商务类、其他三类,不属于前两类的都归入其他”
  • 涉及优先级:给明确排序,如“先检查正确性,正确性无问题再看性能”

这套做法在llm as judge场景里尤其重要。你要让模型做评判,评判标准必须是可勾选的清单,而不是“你觉得好不好”。

4.2 原则二:给“不知道”留出口

新手写 Skill 最容易犯的错,是把 Agent 逼到“必须给答案”的墙角。结果就是模型开始编。

好的 Skill 一定会明确告诉 Agent:什么情况下应该停下来。常见的有:

  • 输入缺少必要字段,且无法从上下文推断 → 反问用户
  • 任务超出 Skill 定义范围 → 明确说明并建议其他方式
  • 多个步骤结果冲突 → 列出冲突点,请用户裁决

热搜里agent execution terminated due to error这类报错,很多时候就是因为 Skill 没给“优雅退出”的路径,Agent 硬着头皮往下跑,最后崩在某个环节。

4.3 原则三:输出格式要“机器可校验”

如果 Skill 的输出会被下游程序消费,那格式必须严格到可以用正则或 JSON Schema 校验。这时候不要指望模型“自然输出正确格式”,而是:

  1. 在指令里给出精确的格式定义
  2. 提供一个模板文件
  3. 如果可能,挂一个校验脚本,让 Agent 输出后自己跑一遍

我见过太多团队在“模型输出格式偶尔不对”上反复拉扯,最后发现加一个校验脚本 + 一次自动重试,问题就解决了。这比反复调 Prompt 高效得多。

4.4 原则四:控制上下文预算

Skill 加载进上下文是要花 token 的。一份 Skill 如果本身就有三千字,那留给实际任务的空间就被压缩了。

控制预算的几个手段:

  • 指令区只写“必须知道”的,背景知识放references/按需读取
  • 示例控制在两到三个
  • 长枚举用表格或列表压缩,不要写成大段散文
  • 能挂脚本的绝不写成文字描述

热搜里llm request failed: provider rejected the request schema or tool payload这类问题,有一部分就是 Skill 或工具定义太臃肿,导致请求体超限。

5. 实操:从零写一份“会议纪要整理”Skill

光讲原则太虚,我拿一个具体场景走一遍完整流程。选“会议纪要整理”是因为它足够典型:输入非结构化、输出有固定格式、判断逻辑不少。

5.1 第一步:拆解任务,画出流程

先别急着写文件,拿张纸把流程画出来。我的拆解是这样的:

  1. 接收输入(转写文本 / 笔记 / 聊天记录)
  2. 判断输入类型,不同类型预处理方式不同
  3. 分段识别:哪些是议题、哪些是讨论、哪些是结论
  4. 提取三类要素:决议、待办、信息同步
  5. 待办要素补全责任人和时间
  6. 按模板输出

这里面第 3 步和第 5 步是难点。第 3 步难在“讨论”和“结论”经常混在一起;第 5 步难在责任人和时间经常没明说。

5.2 第二步:写元信息

name: meeting-notes-organizer description: 当用户提供会议转写文本、会议笔记或相关聊天记录,需要整理成结构化会议纪要时使用。适用于需要提取决议事项、待办任务、责任人及截止时间的场景。不适用于纯信息同步类会议(无决议无待办)。

注意最后那句“不适用于”,这是给 Agent 划边界。没有这句话,Agent 遇到纯同步会也硬套模板,输出一堆“无决议”的空章节。

5.3 第三步:写指令区

指令区我按“预处理 → 识别 → 提取 → 补全 → 输出”五段来写。每段都尽量给可执行动作。

预处理部分:

  • 如果输入是转写文本,先按说话人切分,合并同一人连续发言
  • 如果输入是笔记,按空行或标题切分
  • 如果输入是聊天记录,按时间顺序排列,忽略寒暄类消息

识别部分:

  • 议题识别:出现“接下来讨论”“下一个议题”“关于 XX”等标记的句子,作为议题起点
  • 结论识别:出现“决定”“同意”“通过”“就这么定”等动词,且该句包含明确对象,判定为结论
  • 待办识别:出现“负责”“跟进”“下周前”“由 XX 来做”等表述,判定为待办

提取部分给字段定义:

  • 决议:事项 + 结论,两字段
  • 待办:事项 + 责任人 + 截止时间,三字段
  • 信息同步:事项 + 要点,两字段

补全部分给规则:

  • 责任人缺失时,回溯前文找最近一次提到的人名;仍找不到则标注“待确认”
  • 截止时间缺失时,标注“未明确”,不要推断为“尽快”

输出部分给模板引用:

  • 使用templates/meeting-notes.md模板
  • 按“会议信息 → 决议事项 → 待办任务 → 信息同步”顺序填充
  • 待办任务按截止时间升序排列,未明确的排最后

5.4 第四步:挂模板和脚本

模板文件templates/meeting-notes.md长这样:

# 会议纪要 ## 会议信息 - 主题: - 时间: - 参与人: ## 决议事项 | 序号 | 事项 | 结论 | |------|------|------| ## 待办任务 | 序号 | 事项 | 责任人 | 截止时间 | |------|------|--------|----------| ## 信息同步 -

再挂一个校验脚本scripts/validate.py,检查输出是否包含所有必需章节、表格列数是否正确、待办是否都有责任人字段。Agent 输出后自动跑一遍,不通过就重试一次。

5.5 第五步:写示例

放两个示例。第一个是典型情况:输入是一段有明确决议和待办的转写文本,输出是完整纪要。第二个是边界情况:输入是一段纯讨论、没有明确结论的文本,期望输出是“本次会议未形成明确决议,以下为讨论要点”,而不是硬编出决议。

第二个示例特别重要,它教会 Agent 什么时候该“认怂”。

6. 常见翻车现场与排查清单

6.1 输出格式飘忽不定

现象:同一份 Skill,跑十次有三次格式不对。

排查顺序:

  1. 检查指令区是否给了精确格式定义,还是只给了“大概长这样”
  2. 检查是否有模板文件,Agent 是否真的引用了
  3. 检查是否有校验脚本,是否在输出后执行了
  4. 检查示例里的格式是否和指令一致(示例和指令打架是常见坑)

解决:模板 + 校验脚本 + 自动重试,三件套基本能解决九成格式问题。

6.2 Agent 该反问的时候瞎猜

现象:输入缺关键信息,Agent 不反问,直接编一个填上。

排查:

  1. 指令区是否明确写了“什么情况下必须反问”
  2. 示例里是否有“反问”的案例
  3. 是否给了“不知道”的合法出口

解决:在指令区加一条硬规则——“当 X 字段缺失且无法从上下文推断时,必须停止并列出缺失字段,不得自行填充”。同时在示例里放一个反问案例。

6.3 Skill 加载了但没生效

现象:Agent 明明加载了 Skill,但行为还是按默认来。

排查:

  1. description是否写得太泛,导致路由时匹配不准
  2. Skill 内容是否太长,关键指令被淹没
  3. 是否有其他 Skill 或 System Prompt 里的指令和它冲突

解决:description加具体触发词;把最关键的三条指令放在指令区最前面;检查 System Prompt 里有没有“覆盖性”指令。

6.4 换个模型就崩

现象:在 A 模型上跑得好好的,换 B 模型输出就乱。

排查:

  1. Skill 里是否依赖了某个模型特有的“隐含理解”
  2. 指令是否足够显式,还是留了很多“你懂的”
  3. 示例是否足够覆盖各种情况

解决:把 Skill 当成写给一个“聪明但完全不了解你业务的新人”的文档。所有隐含假设都要显式写出来。跨模型测试是检验 Skill 质量的试金石。

6.5 常见问题速查表

问题可能原因快速修复
格式不稳定缺模板或校验加模板文件 + 校验脚本
该反问时瞎猜没给“不知道”出口加硬规则 + 反问示例
Skill 不生效description 太泛加具体触发场景词
换模型就崩依赖隐含理解所有假设显式化
上下文超限Skill 太臃肿背景知识移到 references
步骤跳步流程没写全每步给明确动作和判断标准

7. 进阶:让 Skill 具备“自我进化”能力

7.1 从执行日志里找改进点

Skill 上线不是终点。我习惯在 Skill 里加一个轻量的日志钩子,记录每次执行的输入特征、走了哪些分支、输出是否通过校验。跑一段时间后,把这些日志拉出来看,高频失败的分支就是需要补强的地方。

比如发现“待办责任人缺失”的情况特别多,那就在补全规则里加更细的回溯策略,或者干脆在输出模板里把“待确认”标红,提醒用户手动补。

7.2 用测试用例驱动迭代

给每个 Skill 配一组测试用例,覆盖典型、边界、异常三类。每次改完 Skill 跑一遍,确保没把之前修好的问题又改回去。这套做法在基于llm的单元测试这个方向上也适用——把 Skill 当成一个函数,输入输出就是它的接口契约。

测试用例不用多,一个 Skill 配五到十个就够。关键是每次线上出问题,都把它沉淀成一个新用例,这样 Skill 的健壮性是单调递增的。

7.3 版本管理与灰度

Skill 改动要像代码一样管理。每次改动记清楚改了什么、为什么改、影响哪些场景。如果 Skill 被多个 Agent 共用,改动前先在一个 Agent 上灰度,观察几天再全量。

我踩过的坑是:改了一个“输出格式”的小细节,结果下游解析脚本全挂了。从那以后,凡是涉及输出格式的改动,一律先跑一遍下游校验。

8. 几个容易被忽略的细节

8.1 命名要“自解释”

Skill 的name不要用缩写或内部代号。mno这种名字,三个月后你自己都想不起来是什么。用meeting-notes-organizer这种一看就懂的。热搜里workbuddy skill、cola skill这类命名,如果是内部项目无所谓,但如果要复用或分享,还是描述性命名更稳。

8.2 描述里带上“反例”

description里除了写“什么时候用”,最好也写“什么时候不用”。这一句话能挡掉大量误加载。比如“不适用于纯信息同步类会议”,就能避免 Agent 在不需要的场景浪费一次加载。

8.3 指令用第二人称

写指令时用“你”而不是“Agent”或“模型”。实测下来,第二人称的指令遵循率更高。这可能是训练数据里指令类文本的分布导致的,反正不要钱,用就完了。

8.4 关键规则放开头和结尾

模型对上下文的首尾注意力最高,中间容易衰减。所以最关键的规则,要么放指令区最前面,要么放最后面。别把“必须反问”这种硬规则埋在第三段中间。

8.5 定期清理

Skill 会随着业务变化积累冗余。每隔一段时间 review 一遍,把不再需要的分支、过时的示例、没人用的脚本清掉。臃肿的 Skill 不仅费 token,还会让模型抓不住重点。

9. 关于 Skill 生态的一点个人观察

现在 Skill 的写法还没有形成统一标准,各家有各家的风格。但有些趋势已经比较明显了。

一是从通用走向垂直。早期大家写 Skill 都想覆盖一大类任务,现在越来越多的是“只干一件事但干到极致”的 Skill。ai备课skill、打斗动作提示词skill这种就是典型,场景窄但深度够。

二是脚本比重上升。纯文字指令的 Skill 越来越少见,带脚本、带模板、带校验的 Skill 成为主流。这背后是大家意识到:确定性的事交给代码,不确定性的事才交给模型。

三是测试驱动。以前写完 Skill 靠感觉判断好不好,现在越来越多团队给 Skill 配测试集,用数据说话。这个方向我觉得是对的,Skill 本质上是软件,软件就该有测试。

四是跨模型兼容。随着模型选择越来越多,Skill 的可移植性变得重要。一份只能在特定模型上跑的 Skill,价值会打折扣。写的时候多想想“换个模型还能不能跑”,会倒逼你把指令写得更显式。

我自己在实际操作中的体会是:写 Skill 最难的从来不是“写”,而是“想清楚”。你得先把这件事的流程、判断、边界在脑子里过一遍,才能落到纸上。很多时候写着写着发现写不下去,不是文笔问题,是你自己都没想明白这个任务该怎么干。所以我现在写 Skill 之前,会先假装自己要手动做一遍这个任务,把每一步都记下来,然后再翻译成 Agent 能执行的指令。这个笨办法,比任何技巧都管用。

最后分享一个小技巧:写完 Skill 后,找一个完全不了解这个业务的人,让他照着 Skill 手动执行一遍。如果他执行过程中卡壳了、或者执行结果和你的预期不一样,那说明 Skill 里还有隐含假设没写出来。这个“人工模拟 Agent”的测试方法,比直接跑模型更能暴露问题,而且成本几乎为零。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询