文章目录
- 前言
- 一、Skill 概念简介
- 1、一句话定义
- 2、三部分构成
- 3、规范与文档入口
- 二、架构原理 : 渐进式加载
- 1、三层加载模型
- 2、为什么这样设计
- 3、上下文成本账
- 三、调用逻辑 : 模型怎么想到要用它
- 1、四步链路
- 2、触发失败的两个根因
- 3、让模型遇事提问
- 4、让模型稳定执行
- 四、Skill 与 MCP 的区别
- 1、本质差异
- 2、多维度对比
- 3、组合使用
- 五、怎么写好一个 Skill
- 1、定人设与边界
- 2、写 description
- 3、主干是决策树
- 4、拆 references
- 5、定义输入输出契约
- 6、好 Skill 的六个特征
- 六、迭代 : 从模糊需求到可交付
- 1、第一版不求全
- 2、迭代循环
- 3、版本敏感内容
- 七、常见踩坑与解法
- 1、技能不触发
- 2、触发了但不照做
- 3、加载与性能
- 4、平台与格式问题
- 5、内容层面的坑
- 总结
前言
装过 IDE 插件的人大概都熟悉这种体验 :工具越装越多 , 真正用得顺手的没几个;提示词越攒越长 , 换个项目又要重新粘贴一遍 ;
Agent Skills 想解决的正是这件事 ; 它把 " 某类任务该怎么做 " 沉淀成一个文件夹, 放进 项目目录 或 用户目录 ,需要时 由模型自己取用, 不需要每次手工喂上下文 ;
本篇博客按四个层次展开 :
- 先讲清楚Skill 是什么、由什么构成 ;
- 再拆开Skill 为什么能这样工作 ;
- 然后把 最容易混淆的 MCP 摆在一起做多维度对比 ;
- 最后落到怎么写、怎么迭代、怎么避开那些反复出现的坑 ;
全程不需要提前读过任何规范 , 顺着往下看即可 ; 文中出现的案例来自 MCP 官方三个开发技能build-mcp-server、build-mcp-app、build-mcpb的真实结构 , 数据都做过逐文件核对 ;
在 【AI 大模型】MCP 开发实战 ⑤ ( 使用 build-mcp-server、build-mcp-app、build-mcpb 等 Skill 技能开发 MCP 服务器 ) 中 , 有上述 三个开发 MCP 的 Skill 技能 ;
一、Skill 概念简介
1、一句话定义
Agent Skills 的官方定义是" a lightweight, open format for extending AI agent capabilities with specialized knowledge and workflows ";
翻译过来 :一种轻量、开放的文件格式 , 用来给 AI agent 补充专门知识与工作流程 ;
这里有个容易被忽略的限定词 :它不提供新能力 , 只提供" 怎么把现有能力用对 " 的知识;
这个区别决定了后面所有设计取舍 ;
- MCP :想给模型加一项它做不到的能力, 比如查数据库、调企业微信接口 ,那是 MCP 的活;
- Skill :想让模型在特定场景下按固定流程办事 , 才是 Skill 的活 ;
官方对自身的定位还有一句关键表述 :
The Agent Skills format was originally developed by Anthropic, released as an open standard, and has been adopted by a growing number of agent products.
由 Anthropic 发起 ,以开放标准的形式发布 , 生态可以贡献; 目前支持列表里既有 Claude Code、VS Code、GitHub Copilot、Cursor、Gemini CLI , 也有 TRAE、Spring AI , 属于跨产品的通用格式 ,不是某一家产品的私有扩展 ;
2、三部分构成
一个 Skill 就是一个文件夹; 里面最少只有一个文件 , 最多可以带一整套工程资产 ;
三部分构成 :说明书、操作脚本、参考资料 ;
- 说明书 ( SKILL.md ):唯一必需的入口文件,由 YAML 元数据加 Markdown 正文组成, 回答三个问题 :这是什么、什么时候用、大致怎么做 ;
- 操作脚本 ( scripts/ ):可选 , 放可执行代码 ;复杂逻辑交给代码, 而不是写进提示词让模型一步步推演 ;
- 参考资料 ( references/ ):可选 , 放按需读取的文档 ;字段表、避坑清单、平台差异这类长篇细节都归这里 ;
真实技能的目录结构长这样 , 以build-mcp-server为例 :
- 对应的 Skill 源码位置 : https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev/skills/build-mcp-server ,
- 对应的 中文版本的 Skill , 在 【AI 大模型】MCP 开发实战 ⑤ ( 使用 build-mcp-server、build-mcp-app、build-mcpb 等 Skill 技能开发 MCP 服务器 ) 五、三个 Skill 中文版全文 ( 翻译内容、仅做参考 ) 1、build-mcp-server / SKILL.md 博客章节中 ;
build-mcp-server/ # 目录名必须与 name 字段完全一致 ├── SKILL.md # 必需 : 元数据 + 主干指令 , 221 行 ├── references/ # 可选 : 8 份按需加载的文档 │ ├── tool-design.md # 工具描述与 schema 的写法细则 │ ├── auth.md # OAuth / CIMD / DCR 三种鉴权路线 │ ├── versions.md # 版本敏感论断的台账 , 25 行 │ └── ... # 其余 5 份 , 合计约 1.1 万 tokens ├── scripts/ # 可选 : 本技能不含脚本 └── assets/ # 可选 : 本技能不含静态资源注意一件事 :这份技能总共 1275 行、约 1.4 万 tokens, 但入口文件只有 221 行; 剩下 1000 多行全部躺在references/里 , 模型没用到就不会去读 ;
这就是Skill与" 把 提示词 存成文本文件 "的根本差别 , 下一章会展开 ;
3、规范与文档入口
所有一手资料都在agentskills.io, 不需要翻二手文章 ;
常用地址 :五个入口 , 覆盖规范、仓库、脚手架 ;
- 首页与概念介绍 :
https://agentskills.io/ - 完整格式规范 :
https://agentskills.io/specification - 标准源码仓库 :
https://github.com/agentskills/agentskills - 官方校验工具 :
https://github.com/agentskills/agentskills/tree/main/skills-ref - 可参考的真实技能集 :
https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev
规范的必填字段只有两个 , 剩下的都能省 :
| 字段 | 必填 | 约束 |
|---|---|---|
name | 是 | 1 至 64 字符 ; 只允许a-z、0-9、-; 不能首尾是连字符 ; 不能出现连续--; 必须与父目录名一致 |
description | 是 | 1 至 1024 字符 ; 非空 ; 要同时说清做什么、何时用 |
license | 否 | 许可证名 , 或包内 LICENSE 文件的说明 |
compatibility | 否 | 1 至 500 字符 ; 环境要求 , 如系统依赖、网络需求 |
metadata | 否 | 字符串键值映射 , 供客户端存自定义属性 |
allowed-tools | 否 | 空格分隔的预授权工具列表 , 标注为实验性 |
正文部分没有任何格式限制, 规范原话是There are no format restrictions. Write whatever helps agents perform the task effectively.;
但有三条推荐值值得当硬线用 :主SKILL.md不超过 500 行 ;正文不超过 5000 tokens ;文件引用只嵌套一层 , 即只到references/xxx.md,不要再往下套 ;
需要提醒一个来源差异 : 网上流传的 "description不能含尖括号 " 并不是规范条文 , 而是某些客户端自带校验脚本的额外限制 ; 写规范时以官网为准 , 跑本地校验时按客户端报错调整 ;
二、架构原理 : 渐进式加载
1、三层加载模型
Skill 之所以能做到 " 装几十个也不炸上下文 " , 全靠渐进式加载; 官方把它拆成三个阶段 , 分别是发现、激活、执行 ;
三层加载 :每一层解决一个问题 , 加载量逐层放大 ;
- 第一层 , 元数据 :启动时只加载每个技能的
name与description, 约 100 tokens ;目的是让模型知道 " 有这么个东西 , 大概管什么 " ; - 第二层 , 指令 :判断 当前任务 与 某个技能 的描述匹配后, 才把整个
SKILL.md正文读进上下文 ;规范建议这一层控制在 5000 tokens 以内 ; - 第三层 , 资源 :正文里指到的
references/、scripts/、assets/文件, 只有真正用到时才逐个读取 ; 引用到此为止 ,不能再出现第四层引用了 ;
对应到具体技能上 , 这三层的成本差得非常悬殊 ;
以build-mcp-server实测数据为例 :
| 加载层 | 内容 | 规模 | 何时发生 |
|---|---|---|---|
| 第一层 | description字段 | 约 117 tokens | 每次会话启动 , 常驻 |
| 第二层 | SKILL.md全文 | 221 行 , 约 3522 tokens | 任务匹配到该技能时 |
| 第三层 | 8 份references/ | 1054 行 , 约 10700 tokens | 正文指到哪读到哪 ,按需加载某一个或某几个 |
| 合计 | 全部内容 | 1275 行 , 约 14222 tokens | 实际极少全部读完 |
关键比例是 117 比 14222 , 接近 1 比 120 ; 也就是说 , 常驻开销只占全部内容的不到百分之一 ;
2、为什么这样设计
这个设计针对的是一个很具体的约束 :上下文窗口是线性成本, 而人的需求是发散的 ;
如果把所有技能的完整正文都常驻 , 装 20 个技能就要吃掉十万 tokens, 任何一个模型都撑不住 ;
反过来 , 如果技能内容全靠用户每次手工粘贴 , 那就退回到 " 攒提示词 " 的老路, 换台机器就得重来 ;
渐进式加载在两者之间找了个平衡点 :元数据常驻 , 内容按需;
它带来的三个直接好处 :
- 规模不受限 :装 50 个技能 , 启动成本只多约 5000 tokens; 装满一整个团队的知识库也不会拖慢会话 ;
- 命中更准 :全量加载时 , 无关技能的正文会干扰判断; 按需加载时 ,上下文里只有当前任务真正相关的内容 ;
- 可维护 :想改某个细节 ,只改对应那份 reference, 不用动主干 , 也不会影响其他技能 ;
代价也有一个 :能否被触发完全押在description上;这一层写得含糊 ,后面内容再精彩也不会被读到 ;
3、上下文成本账
理解了这套机制 , 就能明白为什么规范要给 500 行、5000 tokens 这两个数字 ;
它们不是审美要求 , 而是在守第二层的加载成本;
一个技能如果正文写到 8000 tokens ,就意味着每次激活都相当于塞进去一篇中等长度的文章, 而且模型还要在这篇文章里找到该执行的那一段 ;
判断标准很简单 :一段内容如果" 删掉之后模型仍能选对方向 , 但具体做不了 “, 它就该留在Skill.md主干 ; 如果” 删掉之后模型直接做不了 ", 它就该搬进references/;
举个具体例子 , 同样是部署环节 , 主干里写 :
<!-- 主干只写 " 选哪个 " 和 " 去哪读 " --> - **最快部署 :** Cloudflare Workers , 详见 references/deploy-cloudflare-workers.md - **可移植的 Node 或 Python :** references/remote-http-scaffold.md - **需要读写本机文件 :** 转 build-mcpb 技能而deploy-cloudflare-workers.md里才写wrangler.toml怎么写、npm run deploy报错怎么排查 ;
主干负责 " 选 " ,参考文件负责 " 做 " ;这条分工线划清了 , 技能就不会臃肿 ;
三、调用逻辑 : 模型怎么想到要用它
1、四步链路
很多人以为 Skill 是被某个关键词硬匹配命中的, 实际上它走的是语义判断; 完整链路分四步 ;
四步链路 :从用户发问到技能被执行 ;
- 第一步 , 常驻扫描 :会话开始时 ,所有技能的
name与description已经在上下文里, 模型对 " 有哪些能力可用 " 心里有数 ; - 第二步 , 匹配判断 :用户提出需求后 ,模型把需求与每条
description做语义比对 , 判断哪一条最贴近 ; - 第三步 , 主动读取 :判定匹配后 , 模型自己调用读取工具 , 把对应的
SKILL.md拉进上下文, 这一步不需要用户确认 ; - 第四步 , 按图执行 :读正文 ,遇到指针再去读
references/, 需要跑命令就调scripts/,中途缺信息就回头问用户 ;
这四步里 , 第一步和第二步是黑盒 , 我们能干预的只有description的写法; 第三步和第四步是白盒 , 由正文里的指令和指针控制 ;
2、触发失败的两个根因
技能装了却不用 , 原因基本只有两个 , 且都不在正文里 ;
两个根因 :一个在写法 , 一个在环境 ;
- 描述写成了自我介绍 :
description: 帮助处理 PDF 文件这类写法只说了 " 我是干什么的 ",没说 " 什么时候该叫我 "; 模型拿到需求 " 把这个合同里的表格提出来 " 时 , 无法把两句话连起来 ; - 模型能力不足 :小参数模型 对 长描述 的 语义匹配精度明显下降, 尤其是在有多个相似技能同时存在时 , 容易选错或干脆不选 ;
第一条可以用改写解决 ; 官方规范给了正反例 , 差别很直接 :
# 差 : 只说了领域 , 没说触发条件description:Helps with PDFs.# 好 : 动作 + 何时用 + 关键词 , 三者齐全description:Extracts text and tables from PDF files,fills PDF forms,and merges multiple PDFs. Use when working with PDF documents or when the user mentions PDFs,forms,or document extraction.第二条需要换模型或减少干扰项 ; 如果环境里有多个功能重叠的技能 , 比如同时装了官方的mcp-builder和社区的build-mcp-server, 触发就会互相抢 ; 处理办法是只留一个 , 或用中文描述让其中一个在中文语境下占优 ;
3、让模型遇事提问
Skill 最容易被写成" 一份必须执行完的脚本 ", 结果模型缺信息也不敢问 , 靠猜把流程走完 , 产出全是错的 ;
正确做法是在正文开头就写明" 什么时候必须停下来问 " ;
让模型提问的三种写法 :都放在SKILL.md靠前的位置 ;
- 硬关卡 :直接写" 在拿到下面五个问题的答案之前 , 不要开始搭建 "; 这一句比任何 " 请谨慎 " 都有效 , 因为它给了模型一个明确的阻断条件 ;
- 问题清单 :把要问的东西列成表格 , 每行一个问题加几个可选分支; 模型按表逐条确认 , 不会漏 ;
- 缺省处理 :对可以合理假设的项 ,明确写 " 若用户未指定 , 默认取 X " ;这样只对真正关键的分支发问 , 不会把用户烦死 ;
build-mcp-server就是这么做的 ; 它在第 13 行立了规矩 , 然后用一张五行的表格列清要探询的内容 :
| 探询项 | 要确认什么 | 影响哪个决策 |
|---|---|---|
| 连的是什么 | 云 API、本地进程、文件系统、硬件 | 决定部署形态 |
| 谁会用 | 只有自己、团队、任意安装者 | 决定要不要做鉴权与分发 |
| 动作面有多大 | 几个操作 , 还是包一整套大 API | 决定工具切分模式 |
| 需要交互吗 | 纯文本、结构化表单、富 UI | 决定用 elicitation 还是 MCP apps |
| 上游怎么鉴权 | API Key、OAuth、无 | 决定鉴权实现路线 |
五问答完 , 后面所有分支都能收敛到唯一路径 ; 这就是 " 先问再动 " 的价值 ;
4、让模型稳定执行
问清楚之后 , 还要保证模型真的按顺序执行 , 而不是跳步 ;
四个提高稳定性的手段 :按有效性从高到低排列 ;
- 阶段化 :把流程切成阶段一、阶段二、阶段三 , 每个阶段有明确的产出物 ;模型一次只处理一个阶段 , 出错容易定位 ;
- 决策表替代散文 :需要做选择的地方用表格 , 左边条件、右边结论 ;散文式的 " 视情况而定 " 会让模型自由发挥 ;
- 默认值前置 :每条路径都标一个默认推荐, 并写明 " 选它 , 除非满足下列例外 " ; 默认值能兜住绝大多数场景 ;
- 指针带条件 :引用参考文件时 , 不要只写文件名 , 要写" 什么情况下读哪一份 "; 把判断成本从模型那边拿回来 ;
反过来 , 有四种写法会让执行变得不稳定 :
| 反模式 | 为什么坏 | 改法 |
|---|---|---|
| 通篇 " 建议 “” 可以考虑 " | 没有约束力 , 模型随机取舍 | 改成 " 必须 “” 不得 " , 关键处加阻断 |
| 一段话里塞三个并列条件 | 模型容易只执行第一个 | 拆成表格 , 一行一个条件 |
| 只写 " 参考 references 目录 " | 模型不知道读哪份 , 干脆不读 | 每个指针都带触发条件 |
| 把完整代码贴进正文 | 单次激活吃掉上万 tokens | 代码移到references 或 scripts |
四、Skill 与 MCP 的区别
1、本质差异
这两个东西经常被放在一起讨论 , 但它们根本不是同一层的概念 ;
一句话区分 :一个管 " 能不能做 " ,一个管 " 该怎么做 " ;
- MCP 是连接协议 :它规定了 客户端 与 服务器 之间怎么通信 ,让模型能够调用外部系统 ;有进程、有网络、有 JSON-RPC 消息 ;
- Agent Skills 是文档格式 :它规定了一种组织文本的约定, 让模型在需要时读到正确的知识 ;没有进程、没有依赖 , 拷文件夹即安装 ;
举个具体的例子 , 同样是 " 发一条企业微信消息 " ,MCP 服务器提供的是send_message这个可调用的动作, 以及它的参数 schema ; Skill 提供的是" 什么场景该发、文案怎么写、发之前要确认什么、发失败了怎么重试 "这类判断依据 ;
少了 MCP , 模型没手 ; 少了 Skill , 模型有手但不知道规矩 ;
2、多维度对比
把八个维度摆在一起 , 差异一目了然 ;
| 维度 | Agent Skills | MCP |
|---|---|---|
| 本质 | 开放文档格式 | 连接协议 |
| 承载物 | 纯文本 , Markdown 加 YAML | 服务器进程 , JSON-RPC 通信 |
| 提供什么 | 程序性知识、判断依据、执行流程 | 可调用的工具、资源、提示模板 |
| 加载方式 | 渐进披露 , 元数据常驻、正文按需 | 工具 schema 通常常驻上下文 |
| 上下文成本 | 每个技能约 100 tokens 起步 | 每个工具数百到上千 tokens |
| 分发方式 | 拷文件夹 , 或 git clone | 需部署、安装、配置连接 |
| 运行依赖 | 无 | 需要运行时 , 可能还依赖网络与凭据 |
| 治理重点 | 内容准确性、触发描述 | 权限、鉴权、输入校验、注入防护 |
再补两个常被问到的点 :
谁控制触发 ;Skill 由模型自主判断是否使用 , 用户不需要点任何按钮 ;MCP 的工具也是模型调用 ,但 MCP 的 prompts 原语是用户手动选择的, 规范明确写了这是user-controlled; 三者的控制权归属不同 ;
能不能互相替代 ;不能 ; 但如果只需要传递知识 , 用 Skill 就够了, 不必为了 " 显得正规 " 去搭一个 MCP 服务器 ; 反过来 ,如果需要真实执行动作 , 光靠 Skill 也做不到, 因为 Skill 里没有执行环境 ;
3、组合使用
实际项目里两者通常是配套出现的 , 而且有成熟的组合范式 ;
三种常见组合 :按复杂度递增 ;
- 并列分发 :一个 MCP 服务器加一个配套的 Skill , 各自独立安装; 服务器提供能力 , 技能提供方法论 ; MCP 官方文档明确推荐这种做法 , 说多数合作方两者都会分发 ;
- 技能宿主型服务器 :把
skills/目录打进 MCP 服务器 ,用list_skills与read_skill两个工具复刻三层加载 ;好处是单包分发 , 且保留了模型的自主触发 ; - instructions 加 prompts :连接时用
instructions注入技能摘要 , 用 prompt 暴露全文 ; 代价是 prompt 需要用户手动选择 , 失去了自动触发 ;
如果目标只是" 让模型按流程办事 " , 选第一种就够; 只有当技能必须和服务器一起交付时 , 才考虑第二种 ;
五、怎么写好一个 Skill
1、定人设与边界
动手写之前 , 先把两件事定下来 :这个技能扮演什么角色 , 以及它明确不做什么 ;
人设 :一句话定位 , 写在正文最前面 ;
- 写法 :在正文开头用第二人称写给模型, 例如 " 你是一位 MCP 服务器架构师 , 负责把客户的 API 封装成可被模型调用的工具 " ;
- 作用 :给模型一个稳定的立场 , 决定它用什么标准做取舍 ;
- 注意 :人设单独使用的效果有限 ,必须配合后面的硬约束才管用; 只写 " 你是一位资深专家 " 而不写具体流程 , 等于没写 ;
边界 :明确列出不做的事 , 比列做哪些更重要 ;
- 反向划界 :直接写 " 以下情况不要使用本技能 , 改用 XXX "; 能主动把用户推给别的技能的技能 , 才可信 ;
- 能力边界 :写清 " 本技能不负责部署后的运维 " 这类限定, 避免模型在无关环节硬撑 ;
- 风险边界 :涉及删除、覆盖、外发这类不可逆操作时 ,必须写明 " 执行前须经用户确认 " ;
build-mcp-server在这点上做得相当克制 ; 它在正文里把本地 stdio 这条路径标成 " 不建议用于分发 " , 并主动提示改用build-mcpb打包 ; 这种自我否定看似削弱了技能 , 实际提高了可信度 , 因为模型不会在错误的路径上一条道走到黑 ;
2、写 description
description是整个技能里投入产出比最高的一行 ;它决定技能是否存在, 而正文只在触发之后才有意义 ;
写法三要素 :动作、时机、关键词 , 缺一不可 ;
- 动作 :用动词开头 , 说清具体做什么 ;避免 " 帮助 “” 支持 " 这类空词 ;
- 时机 :明确写
Use when ...或中文的" 当……时使用 "; 这是触发的主要依据 ; - 关键词 :把用户可能说出的原话塞进去 ,包括同义词和常见误称 ;
长度控制 :上限 1024 字符 , 但别写满 ;200 至 400 字符通常最合适, 太长会稀释关键词权重 ;
一个实用的检验方法 :用五种完全不同的说法问同一件事 , 五种都能触发, 说明描述写到位了 ; 只要有一种没触发 , 就把那种说法的关键词补进去 ;
对于中文环境 , 有个额外技巧 :中文句子加英文关键词混排;中文负责语义匹配 , 英文短语负责字面锚定 ;这样中文提问命中率高 , 英文提问也不至于完全落空 ;
name:build-mcp-serverdescription:从零搭建 MCP 服务器。先探询使用场景(连什么、谁用、动作面大小、 交互需求、鉴权方式),再决定部署形态与工具设计模式。Use when the user wants to "build an MCP server","wrap an API for Claude",or "make an MCP integration".3、主干是决策树
新手最容易犯的错 , 是把SKILL.md写成一篇教程 ;教程是给人从头读到尾的 ,而模型需要的是 " 到这个岔路口该往哪走 " ;
决策树的四个组成部分 :按顺序出现 ;
- 立规矩 :开头几句写定位与硬性禁令 ;例如 " 第一项工作是摸清需求 , 而不是写代码 " ;
- 收集输入 :用表格列出要确认的问题 ,每行一个问题加可选分支 ;
- 做选择 :每个岔路口给一张小表 , 左边条件、右边结论 , 并标出默认项 ;
- 分派执行 :选定路线后 , 用指针把具体怎么做交给
references/;
一个可复用的判断标准 : 如果一段内容删掉之后 , 模型仍然能 " 选对方向但具体做不了 " , 它该留在主干; 如果删掉之后模型 " 直接做不了 " , 它该搬进参考文件 ;
再看build-mcp-server的骨架 , 221 行切成六段 , 每段只干一件事 :
| 段落 | 内容 | 性质 |
|---|---|---|
| 开头 | 定位、前置约束、硬性禁令 | 立规矩 |
| 阶段一 | 五个探询问题 , 每问配分支表 | 收集输入 |
| 阶段二 | 四条部署路径 , 标默认 , 写例外 | 做选择 |
| 阶段三 | 两种工具设计模式 , 以动作数量分界 | 做选择 |
| 阶段四至六 | 框架选择、分支执行、测试发布四步 | 分派执行 |
| 结尾 | 决策矩阵加参考文件索引 | 二次路由 |
值得注意的一点 : 它通篇没有一段完整可运行代码 ; 真实的脚手架代码全在remote-http-scaffold.md里 ; 主干只负责 " 选 " , 参考文件负责 " 做 " ;
4、拆 references
参考资料的质量 , 决定技能能走多深 ;但拆得不好 , 反而会让模型读不到 ;
每个文件只回答一个问题 :命名和内容都要围绕单一主题 ;
- 命名 :用主题词而非序号, 如
auth.md、tool-design.md; 模型靠文件名判断要不要读 ,part1.md这种名字等于没有信息 ; - 开头三段式 :标题写 " 主题加一句话定位 ";第二段直接给结论 ;第三段给适用前提或警告 ;
- 能中途退出 :让模型读完前 20 行就能决定 " 要不要继续 "; 按需加载不只是 " 打不打开文件 " , 更是 " 打开后读多深 " ;
指针必须带条件 :只写 " 参考references/目录 " 是最常见的错误 ;
- 坏写法 :详见 references 目录 ;
- 好写法 :需要配置 OAuth 时 , 读
references/auth.md;只需要 API Key 时 , 看该文件第三节即可 ;
差别在于 : 前者把 " 该读哪份 " 的判断成本丢回给模型 , 后者替模型做完了判断 ;
嵌套只到一层 :SKILL.md指向references/xxx.md, 到此为止 ;不要再让 reference 指向另一个 reference, 否则模型很容易在半路迷路 ;
5、定义输入输出契约
Skill 本身没有形式化的参数定义, 不像 MCP 工具那样有inputSchema; 但它完全可以通过正文约定 , 让每次产出结构一致 , 从而被其他接口消费 ;
输入契约 :用表格固定必填项与默认值 ;
- 必填项 :明确列出 缺了就不能开工的信息, 并说明缺失时应当向用户发问 ;
- 可选项 :每项给一个默认值, 减少来回确认的次数 ;
- 示例 :给一段真实的输入样例 , 比字段说明更直观 ;
输出契约 :用模板固定产物结构 ;
- 结构固定 :规定层级、字段名、单位、日期格式; 哪怕只是 Markdown , 也要固定标题层级 ;
- 机器可读 :如果产物要被后续流程解析 , 让它输出 JSON 或固定表头的表格, 而不是自由散文 ;
- 失败态 :明确约定出错时输出什么; 例如统一返回
{"status": "failed", "reason": "..."}, 避免每次写法不同 ;
**输入** | 字段 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | | api_spec | 是 | 无 | OpenAPI 文档路径或 URL ; 缺失时先向用户索取 | | transport | 否 | http | 取值为 http 或 stdio | | auth | 否 | none | 取值为 api_key、oauth、none | **输出** 必须按以下结构交付 , 字段名不得改动 : - 服务器代码 : src/server.ts - 工具清单 : 表格 , 列为 name、description、参数 - 启动命令 : 一段可直接复制的 shell 命令 - 未决问题 : 列表 , 无可写 " 无 "这套契约不增加运行成本 , 但能让产出可被下游直接使用 , 也让不同次执行之间的结果可对比 ;
6、好 Skill 的六个特征
综合下来 , 一个可用的技能通常同时具备这六点 ;
六个特征 :可以作为自检清单 ;
- 单一职责 :一个技能只解一类任务 ;说不出一句 " 什么时候用 " , 就是边界不清 ;
- 描述可搜 :
description里包含 用户原话 与 关键词, 五种说法都能触发 ; - 主干轻 :正文控制在 500 行、5000 tokens 以内 ,细节全在
references/; - 有刹车 :关键环节有硬关卡 , 该问就问, 不靠猜 ;
- 会拒绝 :明确写清不适用场景 ,主动指向其他技能 ;
- 可组合 :需要交棒给别的技能时 ,直接写出 技能名 与 交接条件 ,形成链路 ;
最后一点值得展开 ; 前面提到的三个 MCP 开发技能就是典型的组合关系 :build-mcp-server是入口 , 探询完场景后判断 , 如果要加内联 UI 就交给build-mcp-app, 如果要打包成免安装分发就交给build-mcpb;
这种交接必须写死在正文里 , 例如 :
- 需要交互表单或图表 : 转 build-mcp-app 技能 , 不要在本技能内实现 UI - 需要打包成 .mcpb 供非开发者安装 : 转 build-mcpb 技能 - 只做本地原型 : 留在本技能 , 用 stdio 路径即可只装入口技能、不装被交接的两个 , 链路就断了 ; 这也是为什么这三个技能通常要一起安装 ;
六、迭代 : 从模糊需求到可交付
1、第一版不求全
技能不是一次写成的 , 而是磨出来的 ;官方那套技能累计 1275 行 , 几乎不可能第一版就长成这样 ;
第一版的正确目标 :能跑通一条最短路径 ;
- 只覆盖主干 :把最常用的那条路写清楚, 其余场景先写 " 暂不支持 " ;
- 描述先行 :先把
description写到能稳定触发 , 再补正文; 顺序颠倒的话 , 会写出一堆触发不了的内容 ; - 留空位 :在正文末尾预留 " 参考文件索引 " 小节, 后面新增的文档往里挂 ;
举个例子 , 需求是 " 帮我做个处理 Excel 的技能 " ;
第一版可能只有 80 行 :读文件、清洗空行、导出 CSV , 三个动作写清楚 , 边界写 " 不做图表、不做透视表 " ;
这个版本能用了 , 但显然不够 ; 而它之所以有价值 , 是因为能立刻拿去试;
2、迭代循环
接下来是一个不断重复的循环 ,每一轮都由真实使用中的失败驱动 ;
四步循环 :每轮只改一处 ;
- 第一步 , 真实任务跑一遍 :不要用自己编的例子 ; 用上周实际处理过的那份表格 , 看它哪里卡住 ;
- 第二步 , 定位失败层 :是没触发 ( 改描述 ) 、触发了但不照做 ( 改主干 ) 、还是照做了但细节错 ( 补 reference ); 三层对应三种改法 , 别混 ;
- 第三步 , 只改一处 :一次改多处 , 出了问题无法归因; 改完立刻重跑同一个任务验证 ;
- 第四步 , 记录触发语料 :把这次用户实际说的话追加到
description的关键词里; 语料越攒越准 ;
几轮之后会出现一个典型现象 : 正文越来越短 , 参考文件越来越多 ; 这是好事 , 说明职责在往正确的层落 ;
还有一条经验 :用户给出的模糊需求 , 本身就是最好的触发语料; 他说 " 帮我搞一下这个表 " 时的原话 , 比任何精心设计的描述都更贴近真实分布 ;
3、版本敏感内容
技能是 " 冻结的提示词 " , 但外部世界一直在动 ; 版本号、API 路径、平台限制这类内容写死在正文里 , 半年后就会变成误导 ;
处理办法 :单独建一份台账 , 而不是散落在各处 ;
- 集中登记 :把所有会过期的论断收集到一个文件 , 例如
references/versions.md; - 标注坐标 :每条记录写清出现在哪个文件的第几行 , 更新时照单核对 , 不用通读全文 ;
- 附核验命令 :每条论断后面跟一条可直接执行的检查命令 , 例如查 npm 包版本、查 API 响应头 ;
- 记录核验日期 :写上最近一次确认的时间 , 读的人一眼能看出新鲜度 ;
build-mcp-server的versions.md只有 25 行 , 却登记了散落在五个文件里的版本相关论断 , 并附上三条核验命令 ; 这是整个技能里最容易被忽略、但维护价值最高的设计 ;
七、常见踩坑与解法
1、技能不触发
这是最高频的问题 , 九成以上出在描述上 ;
| 现象 | 原因 | 解法 |
|---|---|---|
| 完全不触发 | description只写了领域 , 没写时机 | 补Use when ..., 加入用户原话 |
| 有时触发有时不 | 关键词覆盖不足 | 收集真实提问的五种说法 , 全部补进描述 |
| 中文提问不触发 | 描述是纯英文 | 中文句子加英文关键词混排 |
| 两个技能抢触发 | 功能重叠 , 描述相似 | 只保留一个 , 或用语言差异做区分 |
| 换了模型就不触发 | 小模型语义匹配精度不足 | 换更大参数模型 , 或精简描述聚焦关键词 |
还有一类隐蔽情况 : 技能目录名与name字段不一致 ; 部分客户端直接跳过整个目录 , 不报错也不提示 , 排查时容易漏掉 ;
2、触发了但不照做
比不触发更麻烦 , 因为很难判断是模型问题还是写法问题 ;
四种典型表现 :对应四种改法 ;
- 跳步 :模型跳过探询直接开始产出 ;解法是在开头加硬关卡 , 明确写 " 未获得下列信息前不得开始 " ;
- 只做第一步 :长流程里后续步骤被忽略 ; 解法是把流程切成显式阶段 , 每阶段标出产出物, 让模型逐段交付 ;
- 不读参考文件 :指针没带条件 , 模型判断不了该读哪份; 解法是每个指针都写清触发条件 ;
- 自由发挥 :指令太软 , 通篇 " 建议 “” 可以考虑 " ; 解法是改成 " 必须 “” 不得 " , 并给出默认值 ;
还有一种情况是模型参数设得太低 ; 温度过高会导致相同输入产出差异很大 , 而技能恰恰需要稳定复现 ; 执行类任务通常建议用较低温度 ;
3、加载与性能
技能越写越大是自然趋势 , 但超过阈值后效果会反降 ;
| 症状 | 阈值参考 | 处理 |
|---|---|---|
| 激活后回复变慢 | 正文超过 5000 tokens | 把细节拆进references/ |
| 上下文被挤占 | 同时激活多个大技能 | 拆分职责 , 避免一个技能管太多 |
| 模型记不住后段指令 | 正文超过 500 行 | 关键约束前置 , 细节后移 |
| 参考文件读不完 | 单份 reference 超过 2000 tokens | 再拆 , 或改成" 只读前两节 " 的指引 |
一个反直觉的结论 :把内容删短 , 效果往往变好; 因为模型能稳定执行的指令数量是有限的 , 无关信息会稀释注意力 ;
4、平台与格式问题
最后一类坑不在内容 , 而在文件和平台 ;
五个高频问题 :都在实际操作中出现过 ;
- YAML 解析失败 :中文冒号、中文引号、值里出现未转义的
#都会破坏 frontmatter ; 写完用skills-ref validate ./my-skill跑一遍 ; - Windows 下中文乱码 :部分校验脚本读文件时未指定
encoding, 中文系统默认按 GBK 解码 UTF-8 ;name是 ASCII 所以照样通过 , 但description会显示乱码 , 不是文件坏了 ; - 同名技能冲突 :两个版本用同一个
name放在不同目录 , 触发行为不可预期 ; 只能装一个 , 同名目录覆盖即可 ; - 中文包与英文包无法共存 :只有
name必须 ASCII , 其余中英文都能用 ; 但同名技能同时存在会互相干扰 , 二选一 ; - 文档里的代码围栏打架 :如果技能文档本身含三反引号代码块 , 外层包裹时要用四个反引号 , 否则渲染器会提前闭合 ;
最后一条补充一句原理 : 围栏代码块内部没有任何转义手段 , 反斜杠和 HTML 实体都只是字面量 ; 唯一解法是让外层围栏比内层长 , 或者外层改用波浪号 ;
5、内容层面的坑
还有两个不涉及技术、但影响很大的问题 ;
把技能写成百科全书 :一个技能试图覆盖所有情况 , 结果每条路径都很浅; 正确做法是承认能力边界 , 把不常走的分支直接删掉或指向别的技能 ;
把技能写成免责声明 :通篇 " 根据实际情况判断 “” 视需求而定 " , 看起来严谨 , 实际没有可执行性 ;技能的价值恰恰在于替模型做出判断 , 该给默认值就给 , 该划红线就划 ;
总结
把上面的内容压缩成几条可以直接拿走的结论 :
五条核心结论 :覆盖概念、架构、写法、对比与迭代 ;
- 本质 :Skill 是把 " 怎么做 " 写成文本 ,MCP 是把 " 能做 " 做成接口 ;前者无进程 , 后者有运行时 ;
- 架构 :元数据常驻约 100 tokens ,正文按需约 5000 tokens ,资源用到才读 ;三层设计让技能数量可以无限扩展 ;
- 触发 :全部押在
description上 ;写 " 何时用 " 而不是 " 是什么 " , 把用户原话塞进去 ; - 写法 :主干是决策树不是教程 , 细节下沉到
references/,指针必须带触发条件 , 关键环节设硬关卡 ; - 迭代 :第一版只求跑通最短路径 ,之后由真实失败驱动 ,每轮只改一处 , 正文越来越短、参考文件越来越多 ;
如果只记一句话 :一个好技能的标准 , 是模型读了前 20 行就知道该不该用它 , 用了之后每一步都知道该往哪走;
规范本身很薄 , 两个必填字段、三层加载 ; 难的不是格式 , 而是把某个领域里那些 " 老手才懂 " 的判断 , 拆成模型能照着走的岔路口 ;