1. 从一次“重复解释”说起:Agent Skills 到底解决什么问题
如果你最近在折腾 AI 智能体,大概率遇到过这种场景:每次让智能体帮你做代码审查,都要重新贴一遍团队规范;每次让它生成周报,都要重复说明格式要求;换个会话窗口,之前教过的流程全部清零。智能体本身能力不弱,但它缺少“稳定记住一套做事方法”的机制。Agent Skills 就是冲着这个痛点来的——它用 SKILL.md 这个约定文件,把某类任务的知识、步骤和资源打包成一个可复用、可版本控制的文件夹,让智能体在需要时按需加载。
一句话概括:Agent Skills 是一种轻量、开放的格式,通过专门的知识和工作流来扩展 AI 智能体的能力。它的核心载体就是一个包含 SKILL.md 的文件夹,文件里写清楚元数据(至少 name 和 description)以及告诉智能体如何执行特定任务的指令。技能还能顺带打包脚本、参考资料、模板等资源。适合谁?适合那些想让智能体具备可复用能力、又不想每次都从零写提示词的开发者,尤其是团队里需要统一流程、统一输出格式的场景。
我试过把一套接口文档生成流程做成技能后,同一个智能体在不同项目里都能直接调用,不用再复制粘贴大段说明。这篇文章就带你从目录结构、元数据字段,到加载、触发、验证,完整走一遍,最后你能拿到一个可直接复制的 SKILL.md 模板,并在本地环境里跑通第一个自定义技能。
2. 拆解 SKILL.md:目录结构、元数据字段与渐进式披露机制
要理解 Agent Skills,先看它的物理形态。一个技能就是一个文件夹,标准结构长这样:
my-skill/ ├── SKILL.md # 必需:元数据 + 指令 ├── scripts/ # 可选:可执行代码 ├── references/ # 可选:文档资料 ├── assets/ # 可选:模板、资源 └── ... # 其他任意文件或目录SKILL.md 是整个技能的大脑,它由两部分组成:顶部的 YAML 元数据区,和下方的 Markdown 指令正文。元数据里至少要有 name 和 description 两个字段。name 是技能的唯一标识,description 则是智能体判断“这个技能什么时候该被激活”的关键依据。很多人第一次写技能时把 description 写成一句空泛的“帮助处理文档”,结果智能体永远不触发它——因为描述太模糊,匹配不上具体任务。
这里有个关键机制叫渐进式披露(progressive disclosure),它分三个阶段:
发现阶段,智能体启动时只加载每个技能的名称和描述,这点信息刚好够它判断某个技能是否可能相关,上下文开销极小。激活阶段,当任务匹配上某个技能的描述时,智能体才把完整的 SKILL.md 指令读进上下文。执行阶段,智能体遵循指令,按需执行打包的代码或加载引用的文件。
这个设计的好处是,你可以同时挂载几十个技能,而智能体平时只“记得”它们的名字和用途,真正用到哪个才展开哪个。类比一下:就像你书架上摆了很多工具书,平时只扫一眼书脊,需要查某个知识点时才把对应那本抽出来翻。所以写 description 时要像写检索关键词一样精准,把触发场景、任务类型、输入输出都点出来。
再看元数据字段的完整写法。除了 name 和 description,实际使用中还可以带上 version、author、tags 等辅助字段,方便团队管理和检索。但真正影响加载逻辑的是前两个。下面是一个可直接复制的 SKILL.md 模板,你可以先存下来,后面我们会基于它做本地加载实验:
--- name: api-doc-generator description: 根据接口定义文件生成 Markdown 格式的 API 文档,适用于需要统一接口文档格式、批量生成接口说明的场景。当用户提到“生成接口文档”“API 文档”“接口说明”时触发。 version: 1.0.0 author: your-team tags: - documentation - api --- # API 文档生成技能 ## 目标 把接口定义(JSON/YAML)转换成结构统一的 Markdown 文档。 ## 执行步骤 1. 读取用户提供的接口定义文件路径。 2. 解析每个接口的 path、method、params、response。 3. 按固定模板输出:接口名、请求方式、请求参数表、响应示例。 4. 若字段缺失,标注“待补充”,不要编造。 ## 输出格式 使用二级标题分隔每个接口,参数用表格呈现。 ## 参考资料 详细字段说明见 references/field-spec.md。注意指令正文的写法:步骤要具体到可执行,输出格式要明确,遇到缺失信息要规定行为(比如标注待补充而不是瞎编)。这几点直接决定技能激活后智能体表现是否稳定。scripts 目录放可执行脚本,references 放长文档,assets 放模板文件,这样 SKILL.md 本身保持精简,重资源按需加载。
3. 可复制配置:在本地环境接入并挂载你的第一个技能
理解了结构,接下来是落地。要让智能体真正用上技能,需要把它接入一个支持 Agent Skills 的客户端或运行环境。这里我用一个通用的本地接入流程来演示,核心是三件套:Base URL、API Key、Model ID。无论你用的是命令行工具还是带配置文件的客户端,这三项都是绕不开的。
先准备一个工作目录,把技能文件夹放进去:
mkdir -p ~/agent-skills-lab/skills cd ~/agent-skills-lab/skills mkdir -p api-doc-generator/scripts api-doc-generator/references api-doc-generator/assets然后把上一节的 SKILL.md 内容写入api-doc-generator/SKILL.md。接着配置客户端。以常见的 JSON 配置为例,路径和字段名要和你实际使用的工具保持一致,下面是一个可复制的 settings 片段:
{ "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的密钥", "model": "claude-sonnet-4-20250514", "skills": { "enabled": true, "paths": [ "/Users/yourname/agent-skills-lab/skills" ] } }如果你用的是 TOML 风格的配置,等价写法如下:
base_url = "https://taotoken.net/api" api_key = "sk-你的密钥" model = "claude-sonnet-4-20250514" [skills] enabled = true paths = ["/Users/yourname/agent-skills-lab/skills"]这里要强调三件套的完整性:Base URL 指向https://taotoken.net/api,API Key 在控制台的 API Keys 页面生成,Model ID 填你实际要调用的模型标识。三者缺一不可,只填 Base URL 不填 Model ID,请求会因为模型未指定而失败。密钥的获取入口在 API Keys 页面,生成后妥善保存,不要硬编码进公开仓库。
配置完成后,重启客户端或重新加载配置,让技能目录被扫描。此时智能体在启动阶段会读取api-doc-generator/SKILL.md的 name 和 description,完成“发现”这一步。你可以通过客户端的技能列表命令确认它是否被识别:
# 以某类客户端为例,列出已发现的技能 agent skills list # 预期输出类似: # api-doc-generator - 根据接口定义文件生成 Markdown 格式的 API 文档...如果列表里没有出现你的技能,先检查 paths 路径是否写对、SKILL.md 的 YAML 头部格式是否合法(冒号后要有空格,缩进用空格不用 Tab)。元数据解析失败是新手最常见的坑,YAML 对格式很敏感。
4. 验证请求:触发技能调用并确认生效的完整动作
技能被发现只是第一步,真正要验证的是“任务匹配时它会不会被激活”。这一步我们发一个真实请求来触发。假设你有一个接口定义文件api.json:
{ "paths": { "/user/login": { "method": "POST", "params": ["username", "password"], "response": {"token": "string"} } } }现在向智能体发起一个自然语言请求,措辞要能命中 description 里的触发词:
curl -X POST https://taotoken.net/api/v1/messages \ -H "Content-Type: application/json" \ -H "x-api-key: sk-你的密钥" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-sonnet-4-20250514", "max_tokens": 1024, "messages": [ {"role": "user", "content": "帮我根据 api.json 生成接口文档"} ] }'请求发出后,观察返回内容。如果技能被正确激活,智能体会按照 SKILL.md 里的步骤输出:先解析接口,再按模板生成带表格的 Markdown 文档,缺失字段标注“待补充”。返回结构里通常能看到content数组,里面是生成的文档文本。一个成功的响应片段大致如下:
{ "content": [ { "type": "text", "text": "## /user/login\n\n请求方式:POST\n\n| 参数 | 类型 | 说明 |\n| --- | --- | --- |\n| username | string | 待补充 |\n| password | string | 待补充 |\n\n响应示例:\n```json\n{\"token\": \"string\"}\n```" } ] }看到输出格式和 SKILL.md 里定义的模板一致,就说明技能从发现、激活到执行整条链路通了。如果返回的是通用回答、没有按模板走,说明技能没被激活,问题多半出在 description 的匹配度上——把触发词写得更贴近用户实际说法,比如加上“接口说明”“API 文档”这类同义表达。
验证时还可以做个对照实验:把 skills.enabled 改成 false,再发同样的请求,对比输出差异。关闭技能后,智能体只能靠通用能力回答,格式往往不统一。这个对比能帮你确认技能确实在起作用,而不是模型碰巧答对了。
5. 常见报错排查:401、local proxy failed 与 reading choices 怎么解
接入过程中有几类报错特别高频,这里逐个拆解。
第一类是 401 未授权。返回体里通常带"error": {"type": "authentication_error"}。原因无非三种:API Key 写错、Key 已失效、请求头字段名不对。注意不同客户端对请求头的约定不同,有的用x-api-key,有的用Authorization: Bearer。先确认你用的字段名和客户端文档一致,再去 API Keys 页面核对密钥是否还有效。密钥泄露后要及时在控制台吊销重建。
第二类是local proxy failed或连接类错误。这类报错说明请求根本没到达服务端,问题在本地网络配置或 Base URL 拼写。检查 baseUrl 是否写成了https://taotoken.net/api,有没有多写斜杠或漏写路径段。如果你在配置里填了本地代理地址,而代理服务没启动,也会报这个错。把代理相关配置清掉,直连 Base URL 再试。
第三类是reading choices或响应解析失败。这通常出现在 OpenAI 兼容格式的客户端里,报错信息类似cannot read property 'choices' of undefined。原因是服务端返回的结构和客户端预期的不一致,或者请求体里 model 字段填了一个不存在的 Model ID。解决办法是核对 Model ID 拼写,确保它和平台支持的模型标识完全一致。同时检查请求体 JSON 是否合法,多一个逗号都会导致解析失败。
第四类是 OAuth 相关报错,比如OAuth token expired或invalid_grant。如果你用的是需要 OAuth 授权的客户端,token 过期后要重新走授权流程。有些工具会把 token 缓存在本地文件里,路径通常在用户目录下的隐藏文件夹,删掉缓存重新授权即可。注意不要手动去改 token 内容,重新生成更稳妥。
排查时养成一个习惯:先看报错类型,再定位是配置层、网络层还是模型层。配置层查三件套(Base URL、Key、Model ID),网络层查连通性和代理,模型层查 Model ID 和请求体格式。按这个顺序走,大部分问题五分钟内能定位。
6. 把技能用起来:从单技能到可复用技能包的下一步
跑通第一个技能后,你可以开始扩展。比如把 scripts 目录用起来,写一个解析接口定义的 Python 脚本,让智能体在执行阶段直接调用,而不是靠模型现场推理。脚本入口在 SKILL.md 里说明清楚调用方式,智能体就会按需执行。references 目录适合放长文档,比如团队的接口字段规范,SKILL.md 里用相对路径引用,激活时才加载,不占平时上下文。
多个技能之间可以组合。比如一个“代码审查”技能加一个“提交信息生成”技能,智能体在处理一次提交时可能先后激活两者。因为渐进式披露的存在,挂载十几个技能也不会把上下文撑爆。团队协作时,把技能文件夹放进 Git 仓库,版本控制、代码评审、回滚都能复用现有流程,这也是 Agent Skills 相比散落提示词的最大优势。
如果你打算长期做编码类或 Agent 类任务,可以考虑用 Coding Plan 把技能管理和模型调用整合起来,减少反复配置的成本。需要对照模型实际输出效果时,模型对话页面能快速验证技能触发是否符合预期。而所有接入的起点,仍然是那三件套:在 API Keys 页面拿到密钥,Base URL 填https://taotoken.net/api,Model ID 按需选择。接入文档里有各客户端的详细配置示例,遇到字段名不确定时优先查文档而不是猜。
最后留一个实用技巧:给每个技能的 description 做一次“检索测试”。把 description 单独拿出来,问自己“用户会用什么话触发它”,如果描述里没有覆盖这些说法,就补进去。技能能不能被稳定激活,八成取决于这一行描述写得好不好。