1. 为什么你的 Agent 需要一个 SKILL.md
如果你已经在用 Claude Code、Cursor 或者自己搭的 Agent 跑自动化流程,大概率遇到过这个场景:同一个任务,今天跑得好好的,明天换个会话就翻车。你反复调提示词,把「请务必」「一定要」加了一堆,结果模型还是漏步骤、跳环节、参数传错。
问题不在模型不够聪明,而在于你把「怎么做」这件事,全塞进了每次对话的提示词里。提示词是易失的、非结构化的、无法版本管理的。而 SKILL.md 要解决的,正是把「怎么做」从一次性提示词里抽出来,变成一个可复用、可加载、可组合的能力模块。
AI Skills 这个概念,简单说就是给大模型装「专用软件」。模型本身是 CPU,MCP 是工具箱(扳手、螺丝刀、数据库连接器都配齐了),而 Skill 是那本操作手册——它告诉 Agent:遇到 PDF 提取表格这个场景,第一步调哪个工具,第二步怎么校验,第三步输出什么格式。SKILL.md 就是这本手册的载体,一个 YAML 元数据加 Markdown 指令的纯文本文件。
它适合谁?三类人最该关注。第一类是在用 Agent 做重复性工作流的开发者,比如每天要生成报告、审查代码、处理工单;第二类是在搭 MCP 工具链但发现「工具有了,Agent 还是不会用」的团队;第三类是希望把团队规范固化下来、不依赖某个人提示词技巧的工程负责人。
这篇文章不讲概念史,直接给你能跑的东西:一份可复制的 SKILL.md 模板、一套目录结构、以及把技能挂到统一 Key/API 通道上完成端到端调用的完整步骤。你跟着做,就能把单个技能稳定挂进自己的 Agent 流程。
2. TaoToken 前置:统一 Key 与 API 通道怎么准备
在写 SKILL.md 之前,得先解决一个现实问题:你的 Skill 里如果要调用大模型,Key 从哪来、请求发到哪、模型 ID 怎么填。很多人的做法是每个脚本里硬编码一个 Key,结果技能一多,Key 散落各处,换一次就得全局搜替换。更麻烦的是,不同厂商的接口格式还不一样,Skill 里得写一堆适配逻辑。
我试过用统一通道来收口这件事。TaoToken 提供的就是一个兼容主流接口格式的 API 通道,你拿一个 Key,就能在 Skill 里用统一的 Base URL 去请求不同模型。官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end ,API 入口是 https://taotoken.net/api ,注意这个 API 地址不带 UTM 参数,配置的时候别画蛇添足。
具体要准备三样东西,我把它叫做「三件套」,后面每个 Skill 配置都会用到:
第一件是 Base URL。所有请求的根地址统一填https://taotoken.net/api。注意有些客户端要求填到/v1这一层,具体看你用的框架,但根地址就是这个。
第二件是 API Key。去控制台创建,地址是 https://taotoken.net/console ,创建完在 API Keys 页面能看到,地址是 https://taotoken.net/api-keys 。Key 的格式通常是一串以特定前缀开头的字符串,复制下来存到环境变量里,别写进 SKILL.md 正文,SKILL.md 是要进版本库的。
第三件是 Model ID。这个取决于你要调哪个模型,在模型对话页面可以试,地址是 https://taotoken.net/models 。你可以在那里先手动发一条消息,确认模型能通,再把 Model ID 抄进配置。
为什么要在 Skill 里用统一通道而不是直连各家?因为 Skill 的价值在于可组合。你一个复合技能可能先调一个模型做摘要,再调另一个模型做结构化抽取。如果每个模型一套鉴权和地址,SKILL.md 里就得写分支逻辑,可读性直接崩掉。统一通道让 Skill 正文只关心「做什么」,不关心「连哪里」。
这里有个坑要提前说:不要把 Key 写进 SKILL.md 的 YAML frontmatter。frontmatter 是元数据,会被 Agent 加载进上下文,Key 写进去等于每次对话都在泄露。正确做法是 SKILL.md 里只写「需要环境变量 TAOTOKEN_API_KEY」,实际值放在运行环境的 env 里,或者放在 Agent 的 secrets 配置里。
准备好这三件套,我们就可以进入 SKILL.md 的编写了。下面给的模板你可以直接复制,改掉 name 和 description 就能用。
3. 可复制配置:SKILL.md 模板与目录结构
先看目录结构。一个 Skill 的最小形态就是一个文件夹加一份 SKILL.md,文件夹名必须和 SKILL.md 里的 name 字段完全一致,全小写加连字符。我建议你按这个结构来:
weekly-report/ ├── SKILL.md # 必需:YAML 元数据 + Markdown 指令 ├── scripts/ # 可选:可执行脚本 │ └── collect.py ├── references/ # 可选:按需加载的参考文档 │ └── format-spec.md └── assets/ # 可选:模板文件 └── report-template.mdSKILL.md 分两部分:YAML frontmatter 和 Markdown 正文。frontmatter 用三个连字符包起来,字段规范如下。name 必填,1 到 64 字符,只能小写字母、数字和连字符,不能以连字符开头结尾,不能有连续连字符,必须和文件夹名一致。description 必填,1 到 1024 字符,要包含帮助模型识别任务的关键词,这是渐进式加载时唯一会被常驻上下文的部分,写得好不好直接决定技能会不会被触发。
下面是一份可以直接复制的 SKILL.md 模板,我以「周报生成」为例,你可以把 name 和 description 换成自己的场景:
--- name: weekly-report description: Generate weekly work report from Git commits and task logs. Use when user mentions "weekly report", "周报", "工作报告", or asks to summarize a week's work. license: MIT compatibility: Requires git and python3 metadata: author: your-name version: "1.0" allowed-tools: Bash Read Write --- ## Purpose Generate a structured weekly work report summarizing completed tasks, key decisions, and next week's plan. ## Steps to Execute **Step 1: Collect Git commit history** Run the following command and capture output: ```bash git log --since="7 days ago" --oneline --author="$(git config user.name)"Parse commit messages and group by repository.
Step 2: Request task logs (if any)
Ask user: "Do you have task logs or meeting notes to include?" Store provided file paths in context.
Step 3: Generate report sections
- Completed: Summarize commits into human-readable bullets
- Decisions: Parse notes for key decisions
- Blockers: Identify obstacles mentioned
- Next week: Ask user for upcoming priorities
Step 4: Format output
Use Markdown with the following headings:
# Weekly Report (YYYY-MM-DD) ## Completed ## Key Decisions ## Blockers ## Next WeekStep 5: Output report and ask for save location
API Configuration
This skill calls the model through a unified channel. Required environment variables:
TAOTOKEN_API_KEY: your API keyTAOTOKEN_BASE_URL:https://taotoken.net/apiTAOTOKEN_MODEL: model ID, e.g. the one you verified in the console
Do NOT hardcode the key in this file.
注意几个细节。allowed-tools 字段是实验性的,空格分隔,写的是这个技能允许调用的工具名,比如 Bash、Read、Write。compatibility 最多 500 字符,写清楚依赖。正文控制在 500 行以内,详细的参考资料拆到 references/ 目录,靠渐进式加载按需读取。 如果你用的是 Claude Code,技能放 `~/.claude/skills/` 是个人级,放项目里的 `.claude/skills/` 是项目级。Cursor 放 `~/.cursor/skills/` 或 `.cursor/skills/`。VS 2026 通过 Copilot Chat 的 Skills 面板创建。不管哪个平台,SKILL.md 的格式是通用的,这是开放标准的好处。 配置里那个 `TAOTOKEN_MODEL` 字段,你需要在模型对话页面先确认一个可用的 Model ID,地址是 https://taotoken.net/models 。确认能通之后,把它填进环境变量。这样你的 Skill 正文里就不需要出现任何具体模型名,换模型只改环境变量,SKILL.md 一个字不用动。 ## 4. 验证请求:一次端到端调用 配置写完了,得验证它真的能被加载和触发。这一步很多人跳过,结果技能放进去没反应,以为是格式问题,其实是没触发。验证分三层:元数据能被解析、技能能被发现、调用能返回结果。 第一层,验证 YAML 语法。frontmatter 里任何一个缩进错误都会导致整个 Skill 不被识别。你可以用 Python 快速校验: ```python import yaml with open("weekly-report/SKILL.md", encoding="utf-8") as f: content = f.read() # 提取 frontmatter parts = content.split("---") frontmatter = yaml.safe_load(parts[1]) print(frontmatter["name"]) print(frontmatter["description"])跑通会打印出 name 和 description。如果报 yaml 解析错误,检查缩进和引号,description 里如果有冒号,整个值要用引号包起来。
第二层,验证技能被发现。以 Claude Code 为例,把技能文件夹放到.claude/skills/后,启动会话,输入一句会触发 description 关键词的话,比如「帮我生成本周周报」。如果技能被正确加载,Agent 会开始执行 SKILL.md 里的 Step 1,去跑 git log。如果没反应,说明 description 的关键词没匹配上,回去改 description,把用户可能说的原话加进去。
第三层,验证 API 调用能返回结果。这一步单独测,排除 Skill 逻辑的干扰。用 curl 直接打统一通道:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "'"$TAOTOKEN_MODEL"'", "messages": [ {"role": "user", "content": "只回复两个字:通了"} ] }'如果返回的 JSON 里 choices 数组有内容,说明 Key、Base URL、Model ID 三件套都对。这一步通了,再回到 Agent 里跑完整技能,就能区分是「通道问题」还是「技能逻辑问题」。
端到端跑通的样子是这样的:你在 Agent 里说「生成本周周报」,Agent 读取 SKILL.md 的 description 匹配成功,加载完整正文,执行 Step 1 跑 git log,Step 2 问你有没有补充材料,Step 3 调统一通道让模型把 commit 整理成人话,Step 4 按模板格式化,Step 5 输出并问你要存哪。整个过程你只说了一句话,剩下的流程由 SKILL.md 定义。
这里有个实测经验:渐进式加载意味着 Agent 平时只看到 name 和 description,所以 description 写得越贴近用户真实说法,触发率越高。我见过有人 description 写「处理文档相关任务」,太泛,永远不触发;改成「Extract tables from PDF, use when user mentions PDF, 表格提取, 表单填写」,命中率立刻上来了。
5. 本篇常见错排查
技能挂不上去,报错五花八门。我把最常见的几类列出来,对照着查。
401 未授权。这个最直接,Key 不对或没传。检查环境变量TAOTOKEN_API_KEY是否真的注入到了运行环境。很多人把 Key 写在.env文件里,但 Agent 启动时没加载这个文件,等于没设。验证方法是在 Agent 里让它执行echo $TAOTOKEN_API_KEY,看有没有输出。另外注意 Key 有没有多余空格,复制的时候容易带上换行。
local proxy failed / connection refused。这类报错通常是 Base URL 写错了。确认填的是https://taotoken.net/api,不要带结尾斜杠,不要带 UTM 参数。有些框架要求填到/v1,那就填https://taotoken.net/api/v1,但根地址不变。如果你本地有网络代理配置,检查它有没有拦截这个域名,把taotoken.net加进直连白名单。
reading choices 报错 / choices 字段为空。这说明请求发出去了,但返回体里没有 choices。常见原因是 Model ID 填错,或者请求体格式不对。先用第 4 节的 curl 单独测,确认返回结构。如果 curl 通但 Agent 里不通,检查 Agent 用的 SDK 版本,老版本 SDK 可能把响应解析成了别的结构。
OAuth 相关报错。如果你用的是 Claude Code 或 Codex 这类带 OAuth 登录的客户端,报 OAuth 错误通常不是 Key 的问题,而是客户端的登录态过期了。这种情况先重新登录客户端,再检查它读的是不是你的环境变量。有些客户端会优先用自己的登录态,忽略你设的 Key,需要在配置里显式指定用 API Key 模式。
技能不触发。没有报错,就是没反应。九成是 description 的问题。检查三点:关键词够不够具体、有没有覆盖用户可能说的同义词、name 和文件夹名是否一致。还有一个隐蔽的坑:SKILL.md 文件名必须全大写,写成skill.md有些平台识别不了。
YAML 解析失败。frontmatter 里 description 含冒号没加引号、缩进用了 Tab、或者三个连字符没顶格写,都会挂。用第 4 节的 Python 脚本先本地校验一遍,比在 Agent 里试错快得多。
Codex auth.json 配置问题。如果你用 Codex 并且走auth.json配置,注意这个文件里存的凭证格式和普通环境变量不同。三件套要写全:Base URL 填https://taotoken.net/api,Key 填你的 API Key,Model ID 填验证过的模型。缺任何一个都会导致鉴权失败。改完auth.json记得重启客户端,它不会热加载。
排查顺序建议:先 curl 测通道,再 Python 测 YAML,再在 Agent 里测触发。三层分开测,能快速定位是哪一层的问题,别一上来就怀疑模型。
6. 把技能挂进你的 Agent 流程
走到这里,你已经有了一个能跑的 Skill。接下来是把它变成流程的一部分。单个技能的价值有限,真正有用的是组合。比如你有一个「代码审查」技能和一个「周报生成」技能,可以让 Agent 先跑审查,把审查结果作为周报的一个章节。这就是复合技能层的玩法,通过编排多个原子技能实现复杂流程。
组合的关键是让每个 SKILL.md 的输出结构化。如果「代码审查」技能最后输出的是自由文本,下一个技能就没法稳定解析。所以在写 SKILL.md 的 Step 4 时,尽量约定输出格式,比如固定用 Markdown 标题,或者输出 JSON。格式越稳定,组合越可靠。
另一个实践是给技能加版本。metadata 里那个 version 字段不是摆设,技能逻辑改了要升版本,这样出问题能回滚。团队协作时,SKILL.md 进 Git,谁改了什么一目了然,比散落在各人提示词里的「祖传配置」强太多。
如果你要把这套东西用在长期编码或 Agent 流程上,可以考虑用 Coding Plan 来统一管理调用额度,入口在 https://taotoken.net/coding-plan 。模型对话验证在 https://taotoken.net/models ,接入文档在 https://taotoken.net/doc ,API Key 管理在 https://taotoken.net/api-keys 。这几个地址按需取用,别只收藏首页。
最后说一个我踩过的坑:不要试图用一个巨大的 SKILL.md 覆盖所有场景。渐进式加载虽然能扛大文件,但正文太长会让模型抓不住重点。正确做法是拆成多个小技能,每个只干一件事,靠 Agent 去调度。技能越原子,复用率越高,组合越灵活。这跟写函数是一个道理,一个函数干太多事,迟早变成没人敢动的祖传代码。