1. 先搞清楚 SKILL.md 到底解决什么问题
Agent Skills 这个词最近出现频率很高,但很多人第一次接触会误以为它又是某种 prompt 模板或者插件格式。实际上它更接近一种「带发现元数据的文件系统知识包」:一个目录,入口固定叫SKILL.md,里面用 YAML frontmatter 声明name和description,正文写流程和约束,旁边可以挂references/、scripts/、assets/。Agent 启动时只把元数据放进上下文,等用户请求命中description之后才去读正文,更深层的资料和脚本只在任务真正需要时才访问。这套机制叫渐进式披露(progressive disclosure),核心价值是让一个 Agent 同时「会很多流程」又不把上下文撑爆。
我试过把一份两千行的内部规范直接塞进 system prompt,结果每轮对话都在为它付 token,而且模型经常在无关任务里被这些规范干扰。换成 Skill 目录之后,启动阶段每个技能只占大约一百 token 的元数据,未触发的技能几乎零成本。这就是它适合的场景:可重复的程序性工作流,比如按仓库约定开 PR、填 PDF 表单、走固定审计步骤、生成周报;细节很长但单次任务只碰一小块的参考资料;希望用脚本落地确定性校验的环节。不适合的场景也要说清楚:需要稳定契约化外部调用的,那是 MCP tools 的职责;一次性临时指令直接写在对话里就行;运行面没有文件系统和代码执行能力的,按官方模型根本没法用 bash 读 Skill。
三级加载的分工可以这样理解。Level 1 是name加description,启动时进入 system,模型靠它做相关性匹配,所以description不是产品简介而是触发条件说明书。Level 2 是匹配成功后读入SKILL.md正文,官方表记在 5k token 以内,实践上正文控制在 500 行以内比较稳。Level 3 是references、scripts、assets按需访问,引用文件读入才占上下文,脚本经 bash 执行后只有输出进入上下文,源码本身不计费。这三层咬合起来,才叫真正的渐进式披露;把三层压成一层,就等于退化成 system 塞满。
字段规则必须先钉死,否则后面全是白忙。name只允许小写字母、数字、连字符,最长 64 字符,不能含 XML 标签,也不能出现anthropic、claude这类保留词。description非空、最长 1024 字符,并且必须同时说明「做什么」和「何时用」。Claude Code 的目录约定是个人级~/.claude/skills/、项目级.claude/skills/。API 侧 Skills 跑在带 code execution 的容器里,自定义 Skill 的共享范围因表面而异:claude.ai 是个人上传,API 是 workspace 共享,Claude Code 是本地目录或插件分发,不要假设上传一次处处可用。
安全边界也得提前讲。官方安全章节明确要求只使用可信来源,使用前审计SKILL.md、脚本与资源,警惕外链拉取内容,把安装 Skill 当作安装软件。API 容器常见约束是无网络、不能随意装包;Claude Code 与本机权限一致,网络可达性更强,治理要更严。这一段不是客套话,社区包里出现诱导 bash 调用和外联的案例并不少见。
2. 接入前的准备:统一 Key 与 API 通道
要把这套东西跑起来验证,你需要一个能稳定调用模型、并且支持工具调用轨迹观察的通道。我这边习惯用 TaoToken 做统一入口,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api 。它的作用是把你对不同模型的调用收敛到一套 Key 和一套 Base URL 上,省得在多个平台之间来回切换配置。注意这里说的是正常 API 接入,不是任何形式的网络绕行方案,配置里只出现 Base URL 和 Key 两个变量。
前置动作分三步。第一步,在控制台创建 API Key,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,创建后立刻复制保存,页面通常只完整展示一次。第二步,确认你要用的模型 ID,这个值必须和通道侧声明的名称完全一致,写错一个字符就会在请求阶段报模型不存在。第三步,把 Base URL、Key、Model ID 这三件套记在一个地方,后面所有配置文件都从这里取值,避免同一篇文章里出现两套不一致的参数。
如果你打算长期做编码类 Agent 的调试,可以顺带看一下 Coding Plan 的说明页 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,它面向的是持续编码和 Agent 场景的用量安排。只是偶尔验证一次模型行为的话,用按量 Key 就够了,不必上套餐。模型对话的在线调试入口在 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,适合先手动问两句确认通道通不通,再去写配置文件。
这里有个容易忽略的点:Skills 的验证依赖「工具调用轨迹」,也就是你要能看到模型到底有没有去cat那个SKILL.md。所以通道侧必须允许工具调用,并且你的客户端要能把工具调用记录打印出来。纯文本补全接口是看不到这些的。选模型时优先挑支持 function calling 或工具协议的型号,否则你只能验证「回答像不像」,验证不了「加载对不对」。
另外提醒一句,Key 不要写进会提交到 Git 的文件。项目级.claude/skills/是要进版本库的,但 Key 应该走环境变量或者本地未跟踪的配置文件。我见过有人把 Key 直接写进settings.json然后推上公开仓库,几分钟内就被扫到。养成习惯:目录结构可以分享,凭据永远外置。
3. 可复制配置:目录树、SKILL.md 与客户端设置
先落盘目录。以项目级为例,在仓库根目录建这样一棵树:
.claude/skills/ └── pr-checklist/ ├── SKILL.md ├── references/ │ └── REVIEW_POLICY.md └── scripts/ └── check_diff_stats.sh目录名和name字段保持一致,人和机器对齐,排查时少一层心智负担。个人级就把整个pr-checklist放到~/.claude/skills/下。
接着写最小可用的SKILL.md。frontmatter 里description必须同时含 WHAT 和 WHEN,正文保持短,把长政策外置:
--- name: pr-checklist description: 按仓库约定检查 PR 的测试、changelog 与风险说明。在用户要求开 PR、自检 diff、或提到 pull request / changelog 时使用。 --- # PR Checklist ## 快速流程 1. 用 git 查看当前分支相对主分支的 diff 范围。 2. 确认测试命令与 changelog 条目是否齐全。 3. 若 diff 统计异常(过大或仅格式化),先读 `references/REVIEW_POLICY.md`。 4. 需要机器汇总时,运行 `scripts/check_diff_stats.sh`,只根据脚本输出决策。 ## 约束 - 不要在未读 diff 的情况下声称「已覆盖全部文件」。 - 政策细节以 `references/REVIEW_POLICY.md` 为准,不要凭记忆编造门槛。references/REVIEW_POLICY.md放阈值、禁止合并条件、审查问题清单,只在流程走到「需要政策」时才读。scripts/check_diff_stats.sh输出增删行数、文件类型分布这类短结果,避免把脚本全文贴进正文反复占用 L2。
客户端配置以 Claude Code 的settings.json为例,路径与原文一致,放在项目.claude/settings.json或用户级配置里:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "sk-你的Key", "ANTHROPIC_MODEL": "你的模型ID" } }三件套齐了:Base URL 指向https://taotoken.net/api,Key 走ANTHROPIC_AUTH_TOKEN,Model ID 填通道侧声明的名称。如果你用的是 Cline 这类支持 MCP 的客户端,配置形态换成对应的 JSON 字段,但 Base URL、Key、Model ID 这三个值不变。Codex 系的auth.json同理,字段名不同,语义一致。
{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的Key", "model": "你的模型ID" }写完配置后新开一个会话,让发现机制重新扫描技能目录。改完不重启是最常见的「配置没生效」原因,先排除这一条再怀疑别的。
4. 验证请求与成功结果:用访问轨迹验收
验证不要靠感觉,要靠轨迹。准备两条对照请求:一条明显无关,比如问今天天气;一条明显命中,比如「按仓库约定帮我自检这个 PR 的 diff」。然后观察工具调用记录。
无关请求下,轨迹里不应该出现对该 Skill 目录下SKILL.md的读取,上下文占用应该主要是元数据。命中请求下,应该出现一次或少量对SKILL.md的读取,随后步骤与正文流程一致。如果任务只需要文本抽取,不应该额外读取REVIEW_POLICY.md;如果流程走到需要机器汇总,应该出现 bash 执行脚本,且上下文增量主要是输出文本而不是脚本源码。
用 curl 先确认通道本身通不通,这一步和 Skill 无关,但能快速定位问题层级:
curl https://taotoken.net/api/v1/messages \ -H "Content-Type: application/json" \ -H "x-api-key: $ANTHROPIC_AUTH_TOKEN" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "你的模型ID", "max_tokens": 64, "messages": [{"role": "user", "content": "回复 ok"}] }'返回里出现正常的content数组就说明 Key、Base URL、Model ID 三件套没问题。如果这里就失败,先别去动 Skill 目录,问题在接入层。
通道通了之后,把观察写成测试记录,格式建议固定下来:请求类型、是否读取SKILL.md、读取次数、是否读取 reference、是否执行脚本、上下文增量大致量级。这份记录比「感觉它加载了」有用得多,团队里换人接手也能复现。
如果你在自建 Agent 里复刻这套机制,最小实现同样是三层:启动时注入 metadata 列表;触发时read_file(SKILL.md);正文解析出的路径再按条件read_file或run_script。千万不要在启动时把所有SKILL.md正文拼进 system,那会直接退化成 system 塞满,渐进式披露名存实亡。
5. 常见报错排查:401、local proxy failed 与 reading choices
排障第一步永远是分层:接入层、发现层、加载层、执行层。下面这几类是我实际遇到频率最高的。
401 Unauthorized基本都在接入层。先确认 Key 有没有多余空格,复制时首尾带空格是高频事故;再确认请求头字段名对不对,Anthropic 风格用x-api-key,OpenAI 兼容风格用Authorization: Bearer,混用会直接 401;最后确认 Base URL 有没有多写或少写/v1,路径拼错有时表现为 404,有时表现为鉴权失败。用上面那段 curl 单独测,能快速把接入层和 Skill 层切开。
local proxy failed这类报错通常出现在客户端尝试走本地转发但端口没起来,或者环境变量里残留了旧的代理配置。检查settings.json里有没有多余的代理字段,检查 shell 环境里有没有遗留的HTTP_PROXY之类变量。清掉之后重启客户端。注意这里说的是清理本地残留配置,不是让你去搭任何转发通道,配置里只应该出现https://taotoken.net/api这一个地址。
reading choices或类似的响应解析错误,多半是返回体结构和客户端预期不一致。常见原因是 Model ID 写错导致通道返回了错误对象,客户端却按成功响应去解析choices字段。先把 Model ID 和通道侧声明逐字符比对,再用 curl 看原始返回,别在客户端日志里猜。
OAuth 相关报错出现在 Claude Code 登录态场景。如果你用的是 Key 方式接入,就不该触发 OAuth 流程;出现这类报错说明客户端还在走账号登录分支。检查配置优先级,确保ANTHROPIC_AUTH_TOKEN生效,必要时清掉旧的登录缓存再试。
Skill 不触发是另一类问题,报错信息往往没有,只是「装了等于没装」。九成是description只写了能力没写场景。把用户可能说出的关键词写进 WHEN,比如「提到 pull request / changelog 时使用」。其次是name含大写、下划线、空格或保留词,导致发现阶段被拒。再其次是目录放错位置,项目级放到了用户级路径下,或者改完没新开会话。
脚本执行失败要看运行面差异。API 容器常见无网络、不能随意装包,同一个脚本在 Claude Code 能跑、在 API 容器里就挂。排查时先确认脚本只依赖容器内已有命令,把外部依赖降到最低。脚本输出也要控制体量,输出几千行日志等于把 L3 的成本又拉回 L2。
6. 把验证闭环固定下来
这套东西真正落地之后,我建议把两件事固化成习惯。第一,每个 Skill 配一份对照请求清单,无关一条、命中短路径一条、命中长路径一条、命中脚本一条,改完description或正文就跑一遍,看轨迹是否符合预期。第二,description当成路由表条目来维护,同一仓库多个 Skill 并存时,让它们的 WHEN 互斥到不会同时命中,或者命中后可组合,比如pdf-extract强调文本表格抽取、pdf-forms强调填表与字段映射,两者在触发词上切开。
需要长期跑编码类 Agent、频繁调试工具调用轨迹的话,Coding Plan 页面 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 里有用量安排说明;只是验证模型行为和 Skill 加载,用按量 Key 配合模型对话入口 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 手动问两句就够。Key 的创建和管理在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,接入细节和字段说明看文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。Claude Code 相关的接入说明在 https://taotoken.net/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,配置字段和本文的settings.json片段对得上。
最后留一个实操细节:把scripts/下的脚本都加上可执行位,chmod +x scripts/check_diff_stats.sh,否则 bash 执行时会报权限拒绝,而这个报错在轨迹里看起来很像「脚本没被调用」,容易误判成加载问题。改完权限、改完description、新开会话、跑对照请求,四步走完再下结论。