如何创建一个 Agent Skill?从 SKILL.md 到 frontmatter 的完整配置指南 1. 从零理解 Agent SkillSKILL.md 到底是什么Agent Skill 是 Claude 这类 AI 工具在 2025 年之后主推的一种能力扩展方式。你可以把它理解成给 AI 装了一个「专业插件包」一个文件夹里面有一个必须存在的SKILL.md再加上可选的脚本、参考资料和素材。Claude 平时不会把整个技能读进上下文它只先看SKILL.md顶部的 frontmatter也就是name和description两个字段判断「当前这个任务要不要用这个技能」。只有判断要用才会把正文加载进来。这个设计解决了一个很现实的问题。以前我们想让 AI 干特定领域的活要么把一大堆说明塞进系统提示要么每次对话都手动粘贴背景资料。前者会长期占用上下文窗口后者效率极低。Skill 的思路是「按需加载」元数据常驻约 100 字正文触发时才读建议 5000 字以内捆绑资源则完全由 Claude 自己决定要不要读。这就是所谓的渐进式披露Progressive Disclosure。适合谁用三类人最该上手。第一类是经常让 Claude 处理固定格式文档的人比如批量改 Word、提取 PDF 表格第二类是做企业内部工具链的开发者想把公司 API 规范、数据库 schema 变成 Claude 能直接调用的知识第三类是搭 Agent 工作流的工程师需要把多步骤流程固化下来避免每次重新描述。一个 Skill 的目录结构长这样skill-name/ ├── SKILL.md (必需) │ ├── YAML frontmatter (必需) │ │ ├── name: (必需) │ │ └── description: (必需) │ └── Markdown 正文 (必需) ├── scripts/ (可选可执行代码) ├── references/ (可选按需加载的文档) └── assets/ (可选输出用的模板/字体/图标)关键点在于SKILL.md的正文只在技能被触发后才加载所以「什么时候用这个技能」这类信息必须全部写在description里写进正文是没用的——Claude 在决定要不要触发时根本看不到正文。这是新手最容易踩的坑我见过太多人把触发条件写在正文第一段结果技能死活不生效。另外要明确一点Skill 里不要放README.md、安装指南.md、更新日志.md这类文件。技能是给 AI 看的不是给人看的。多余的文档只会增加混乱。技能里只保留「AI 完成当前任务真正需要的信息」。2. 前置准备用 TaoToken 打通 Claude 与 Skill 的调用链路在写SKILL.md之前得先保证你的 Claude 调用链路是通的。因为 Skill 的加载和触发验证本质上还是要通过一次真实的模型请求来观察——你得能看到 Claude 到底有没有读到你的技能、有没有按技能里的流程走。如果你用的是命令行工具或者自己写的调用脚本就需要一个稳定的 API 入口。我这边实测下来用 TaoToken 作为统一入口比较省事。它的 API 地址是https://taotoken.net/api兼容 Anthropic 的接口格式Claude Code、Cline 这类工具都能直接对接。官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content注册后在控制台生成 Key 即可。这里要强调一个概念Skill 本身是「文件系统层面的约定」它不依赖某个特定厂商。但你要验证 Skill 是否生效必须有一个能读取本地技能目录的客户端。Claude Code 就是典型代表——它会扫描指定目录下的技能文件夹把name和description注入到系统提示里让模型自己判断是否调用。所以前置准备分两步。第一步拿到可用的 API Key 和 Base URL。第二步确认你的客户端支持技能目录扫描。以 Claude Code 为例技能通常放在项目根目录的.claude/skills/或者用户级的~/.claude/skills/下。不同版本路径可能略有差异建议先用claude --help或查看官方文档确认当前版本的技能目录约定。如果你用的是 Cline 这类带 MCP 的编辑器插件思路类似把技能目录挂载进去让模型能读到SKILL.md。这里有个细节MCP 配置里要写全三件套——Base URL、API Key、Model ID缺一个都会导致请求失败。Model ID 要填你实际使用的 Claude 模型标识比如claude-sonnet-4-5这类具体以你账号下可用的为准。配置好之后先做一次最简请求确认链路通curl https://taotoken.net/api/v1/messages \ -H x-api-key: $TAOTOKEN_API_KEY \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: claude-sonnet-4-5, max_tokens: 128, messages: [{role: user, content: 回复 OK 两个字母}] }返回里能看到content数组里有文本就说明 Key 和 Base URL 没问题。这一步别跳过因为后面 Skill 不生效时你要能区分是「链路问题」还是「技能配置问题」。我踩过的坑就是技能写得好好的结果是 Key 额度用完了白白排查了半天技能格式。3. 可复制配置SKILL.md 模板与 frontmatter 字段详解现在进入核心部分。一个能直接用的SKILL.mdfrontmatter 只有两个字段多一个都不要加。这是硬性规定加了别的字段打包验证会报错。先看最小可用模板--- name: pdf-rotate description: 旋转 PDF 页面并导出新文件。当用户要求旋转 PDF、调整页面方向、修正扫描件倒置问题时使用。支持按角度旋转单页或全部页面。 --- # PDF 旋转 ## 快速开始 使用捆绑脚本旋转 PDF bash python scripts/rotate_pdf.py --input input.pdf --output output.pdf --angle 90参数说明--input源 PDF 路径--output输出路径--angle旋转角度支持 90 / 180 / 270注意事项旋转后请检查页面尺寸是否变化。若原 PDF 含表单域旋转可能导致域位置偏移需人工复核。name 字段的规则小写字母、数字、连字符不能有空格和下划线长度一般不超过 64 字符。它同时也是目录名所以 name: pdf-rotate 对应的文件夹就叫 pdf-rotate。 description 是重中之重。它是唯一的触发机制。写法上要包含两部分这个技能「做什么」以及「什么时候用」。看一个反例和正例的对比 yaml # 反例太笼统Claude 无法判断何时触发 description: 处理文档 # 正例功能 触发条件都写清楚 description: 全面支持 .docx 文档的创建、编辑和分析包括跟踪更改、批注、格式保留和文本提取。当 Claude 需要处理专业文档时使用具体包括(1) 创建新文档(2) 修改或编辑内容(3) 使用跟踪更改(4) 添加批注或执行任何其他文档任务。正例里把「何时使用」拆成了四个具体场景Claude 匹配用户意图时命中率会高很多。记住所有「何时使用」的信息都放description正文里写这些没用。正文部分用祈使句写直接告诉 Claude 怎么做不要写「本技能可以帮你……」这种描述性的话。正文建议控制在 500 行以内超过就拆到references/里并在正文中明确写出「什么时候去读哪个文件」。关于自由度这是设计技能时要刻意控制的。任务越脆弱、越容易出错就越要给低自由度具体脚本、少量参数任务越开放就给高自由度文字说明、启发式引导。比如旋转 PDF 这种操作顺序和参数都不能错就该用脚本固定下来而「写一份周报」这种任务多种风格都行就给文字说明让 Claude 自己发挥。再看一个带references/的高级模板演示渐进式披露--- name: cloud-deploy description: 将应用部署到云平台。当用户要求部署服务、配置云资源、排查部署失败时使用。支持 AWS、GCP、Azure 三种目标平台。 --- # 云部署 ## 工作流程 1. 确认目标平台询问用户或从上下文推断 2. 读取对应平台的参考文档 3. 按文档执行部署步骤 4. 验证部署结果 ## 平台选择 - AWS读取 [references/aws.md](references/aws.md) - GCP读取 [references/gcp.md](references/gcp.md) - Azure读取 [references/azure.md](references/azure.md) ## 通用检查 部署前确认凭证已配置、目标区域可用、配额充足。这样 Claude 只在用户选了 AWS 时才去读aws.md其他两个文件完全不占上下文。引用只能向下嵌套一层不要SKILL.md指向 AA 又指向 B那样 Claude 容易迷路。4. 验证请求确认 Skill 加载与触发是否生效写完SKILL.md只是第一步真正要确认的是「Claude 有没有读到它」以及「该触发时有没有触发」。这两件事要分开验证。先验证加载。把技能文件夹放到客户端约定的技能目录下然后启动一次会话直接问 Claude「你现在能访问哪些技能」如果配置正确它应该能列出你刚创建的技能名。如果列不出来说明目录路径不对或者客户端版本不支持技能扫描。再验证触发。这一步要构造一个明确匹配description的请求。比如你的技能是pdf-rotate就发一句「帮我把 report.pdf 旋转 90 度」。观察 Claude 的响应里有没有引用技能里的脚本路径或参数说明。如果它直接开始瞎编命令说明技能没触发。用 API 直接验证时可以在请求里带上系统提示把技能元数据注入进去模拟客户端的做法curl https://taotoken.net/api/v1/messages \ -H x-api-key: $TAOTOKEN_API_KEY \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: claude-sonnet-4-5, max_tokens: 512, system: 可用技能\n- pdf-rotate: 旋转 PDF 页面并导出新文件。当用户要求旋转 PDF、调整页面方向时使用。, messages: [{role: user, content: 帮我把 report.pdf 旋转 90 度}] }如果返回内容里出现了scripts/rotate_pdf.py或者--angle 90这类技能正文里才有的信息就说明触发链路是通的。反之如果它只是泛泛地说「你可以用某个 PDF 工具」那就是没读到技能正文。还有一个更严格的验证方式故意在技能正文里写一个不常见的标记比如「本技能要求输出前先打印SKILL_LOADED」。然后发触发请求看返回里有没有这个标记。有说明正文被加载了没有说明只读到了元数据但没进正文通常是description匹配度不够。实测下来触发失败最常见的原因是description写得太抽象。Claude 判断是否触发靠的是语义匹配你的描述越贴近用户真实会说的话命中率越高。所以写完description后自己念一遍如果我是用户我会这么问吗5. 本篇常见错误排查401、local proxy failed 与技能不触发排障要按链路顺序来从外到内。先确认 API 通不通再确认技能目录对不对最后确认description匹配不匹配。错误一401 Unauthorized。这是最常见的。返回体里通常有authentication_error字样。原因无非三个Key 写错、Key 过期、请求头字段名不对。Anthropic 格式用的是x-api-key不是Authorization: Bearer。如果你从别的平台复制配置很容易搞混。检查方法echo $TAOTOKEN_API_KEY | head -c 8确认环境变量确实有值且前几位和你在控制台看到的一致。如果用的是配置文件检查有没有多余空格或换行。错误二local proxy failed 或连接被拒绝。这类报错说明请求根本没发出去或者被本地网络层拦了。先确认 Base URL 拼写正确是https://taotoken.net/api不要多加/v1之外的路径。再确认本地没有奇怪的端口占用。如果你在容器里跑检查容器网络是否能访问外网。这个错误和技能本身无关纯粹是链路问题。错误三reading choices 报错。这个错误通常出现在用 OpenAI 格式的客户端去请求 Anthropic 格式接口时。Anthropic 的响应结构是content数组不是choices数组。如果你看到Cannot read properties of undefined (reading choices)说明客户端在按 OpenAI 的格式解析响应。解决办法是确认客户端支持 Anthropic 格式或者用适配层转换。Cline 这类工具在配置时要选对 API 类型。错误四OAuth 相关报错。如果你用的是 Claude Code 的 OAuth 登录模式而不是 API Key 模式可能会遇到 token 刷新失败。这种情况下建议切到 API Key 模式配置更直接。在 Claude Code 里可以通过环境变量指定export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEY$TAOTOKEN_API_KEY然后重启客户端。注意ANTHROPIC_API_KEY和ANTHROPIC_AUTH_TOKEN是两个不同的变量别填错位置。错误五技能不触发。链路全通但 Claude 就是不用你的技能。按这个顺序查第一description里有没有写「何时使用」第二技能目录名和name字段是否一致第三frontmatter 有没有多余字段导致解析失败第四正文是不是超过了建议长度导致被截断。我遇到过一次是 YAML 缩进用了 Tab解析直接失败但客户端不报错只是静默忽略。YAML 必须用空格缩进。错误六打包验证失败。运行打包脚本时报字段缺失或命名不规范。检查name是否只含小写字母、数字、连字符description是否为空目录结构里有没有混入README.md这类不该有的文件。验证脚本对文件组织比较严格多余文件会导致打包中断。6. 持续迭代与接入入口技能写完不是终点。真实使用中你会发现某些触发场景没覆盖到或者正文里某段说明 Claude 理解偏了。这时候的迭代流程是在实际任务里用一次记录哪里卡壳回到SKILL.md改description或正文再测一次。一个实用技巧把每次触发失败的用户原话记下来直接补进description的触发条件里。比如用户说「帮我把扫描件摆正」你原来的描述只写了「旋转 PDF」那就把「摆正扫描件」也加进去。description是越用越准的。如果你还没配置好调用环境可以从 API Keys 页面生成 Key再对照接入文档把 Base URL 和模型 ID 填进客户端。验证模型是否正常响应可以直接在模型对话里发一条测试消息。如果是长期做编码或 Agent 工作流Coding Plan 会更适合额度和稳定性都更好。技能目录建议纳入版本管理但只提交SKILL.md和必要的scripts/、references/、assets/不要提交测试产生的临时文件。团队协作时把技能目录放在项目仓库里每个人拉下来就能用比口头传递「你要这样问 AI」靠谱得多。