1. 为什么你的 Agent 总是“会调工具但不会干活”
很多人第一次接触 Agent Skill,都会有一个错觉:以为它跟 Function Calling 差不多,无非是给模型多挂几个函数。真上手跑一遍才发现,Tool 解决的是“能不能做”,Skill 解决的是“该怎么做”。这两个问题差得很远。
我举个具体场景。你让 Agent 处理一份 PDF 发票,它手里有read_file、write_file、http_request这些工具,理论上什么都能干。但它不知道先提取字段、再跟用户确认、最后回写这个流程,也不知道公司发票的字段命名规范。结果就是每一步都要你手把手喂 prompt,稍微换个文件格式就翻车。
Agent Skill 就是来填这个坑的。它的载体非常朴素——一个文件夹,核心文件叫SKILL.md,纯 Markdown。Agent 在需要的时候自己翻这本“说明书”,不需要你手动激活。而它真正跑起来的关键机制,叫渐进式披露(Progressive Disclosure):先加载元信息做索引,命中后再读正文,最后才按需执行脚本。
这篇就按“会用 → 懂原理”的路径走一遍。我会用 TaoToken 作为统一的 Key 和 API 通道,把 Claude 生态下的 Skill 从编写、加载到 MCP 调用链完整跑通,给出可复制的settings.json、config.toml骨架和一份最小SKILL.md,每一步都带验证动作和预期输出。适合已经用过 Claude Code、想搞清楚 Skill 底层怎么跑的人。
2. 前置准备:用 TaoToken 统一 Key 打通 Claude 通道
在写 Skill 之前,先把通道理顺。Claude 生态里 Skill 的加载依赖 Agent 运行时,而运行时需要能稳定访问模型接口。如果你在多个项目、多个客户端之间来回切 Key,配置会非常散。我的做法是用 TaoToken 做统一入口,一个 Key 覆盖对话、编码、Agent 三类场景。
TaoToken 在这里的角色是 API 通道:你拿到一个 Key,把它配到 Claude Code、VS Code 插件或者自己的 SDK 脚本里,请求就走同一条链路。官网入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api (这个地址不加 UTM 参数,配置里直接写)。
具体操作分三步。第一步,进控制台创建 Key,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console_key&utm_campaign=rewrite ,创建完先复制保存,页面刷新后不再完整显示。第二步,如果你要跑长期编码或 Agent 任务,建议直接看 Coding Plan,地址 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite ,它比按量计费更适合高频调用。第三步,Key 的管理和轮换在 API Keys 页面,https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite ,建议给不同项目建不同 Key,方便排查问题。
注意:Key 只存在本地配置文件或环境变量里,不要写进
SKILL.md或提交到 Git。Skill 目录经常被团队共享,一旦 Key 混进去就是事故。
通道打通后,后面所有 Skill 的加载、脚本执行、MCP 调用都走这一条链路,排查问题时只需要看一个地方。
3. 可复制配置:settings.json 与 config.toml 骨架
Claude Code 和 VS Code 插件读取的配置位置不太一样,我分别给一份能直接用的骨架。先看 Claude Code 的用户级配置,通常放在~/.claude/settings.json:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的TaoToken密钥", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" }, "skills": { "enabled": true, "directories": [ "~/.claude/skills", ".claude/skills" ] }, "permissions": { "allow": [ "Read", "Write", "Bash(python3:*)" ] } }这里skills.directories是关键,它告诉运行时去哪里扫描 Skill 目录。用户级放~/.claude/skills,项目级放.claude/skills,团队通过 Git 共享项目级目录即可。permissions.allow里放开Bash(python3:*)是为了让 Skill 里的脚本能跑起来,否则 Level 3 资源层会被拦。
再看一份config.toml,适合用 SDK 或自建 Agent 运行时的场景:
[api] base_url = "https://taotoken.net/api" api_key = "sk-你的TaoToken密钥" model = "claude-sonnet-4-20250514" timeout = 120 [skills] enabled = true scan_paths = ["./skills", "~/.claude/skills"] progressive_disclosure = true max_index_tokens = 2000 [execution] sandbox = true allowed_commands = ["python3", "bash"] workdir = "./.skill_workspace"progressive_disclosure = true是显式打开渐进式披露,max_index_tokens限制 Level 1 索引层的总预算,防止 Skill 装太多把 System Prompt 撑爆。sandbox = true让脚本在隔离环境跑,workdir指定脚本的工作目录。
两份配置改完,重启 Claude Code 或重新加载插件。验证配置是否生效,跑一条最简单的请求:
curl https://taotoken.net/api/v1/messages \ -H "x-api-key: sk-你的TaoToken密钥" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "max_tokens": 64, "messages": [{"role": "user", "content": "回复 OK 两个字母"}] }'预期返回里能看到"text": "OK"之类的正常响应。如果返回 401,说明 Key 没配对;返回 404,检查base_url是不是写成了带/v1的完整路径——TaoToken 的基址是https://taotoken.net/api,SDK 会自己拼/v1/messages。
4. 写一份最小 SKILL.md 并验证渐进式披露
配置通了,现在写 Skill。先建目录结构:
mkdir -p .claude/skills/invoice-filler/scripts touch .claude/skills/invoice-filler/SKILL.mdSKILL.md的最小可用版本长这样:
--- name: invoice-filler description: 用于读取、填写和导出 PDF 发票表单。当用户上传 .pdf 发票、要求填写字段、核对金额或导出数据时使用。 --- # Invoice Filler ## 什么时候用这个 Skill - 用户上传 PDF 发票并要求填写、核对或导出字段 - 用户询问“这张发票的金额对不对” ## 工作流程 1. 执行 scripts/extract_fields.py 提取字段,输出 JSON 2. 把字段和用户确认,金额类字段必须人工核对 3. 执行 scripts/fill.py 回写 PDF,输出到 .skill_workspace/ ## 不要做什么 - 不要自动修改金额字段,必须用户确认 - 不要覆盖原始 PDF,只写新文件name和description是路标,Agent 靠它们在一堆 Skill 里挑相关的。正文是专家手册,只有被选中后才进 Context。这里有个细节:description要写得像搜索关键词,把典型触发语塞进去,命中率几乎全靠它。
现在验证渐进式披露。启动 Claude Code,先问一个跟发票无关的问题,比如“帮我写个快排”。观察日志或调试输出,你会看到 Level 1 索引层里出现了invoice-filler的 name 和 description,但正文没被加载。这就是渐进式披露的第一层:所有 Skill 的元信息常驻,成本极低。
再发一条相关任务:“我上传了一张发票 PDF,帮我提取字段。”这时 Agent 判断命中,发出读文件动作,把SKILL.md正文读进 Context。你会在调试日志里看到正文内容被加载,同时scripts/extract_fields.py还没被执行——那是 Level 3 的事。
最后一步,Agent 按正文指示执行脚本。如果脚本不存在,它会报错,这正好验证了 Level 3 是按需触发的。补上脚本:
# scripts/extract_fields.py import json import sys def extract(pdf_path): # 实际项目里用 pdfplumber 或 pypdf 解析 return {"invoice_no": "INV-001", "amount": "1200.00", "date": "2025-01-01"} if __name__ == "__main__": result = extract(sys.argv[1]) print(json.dumps(result, ensure_ascii=False))再跑一次任务,预期输出是 JSON 字段列表,然后 Agent 会停下来跟你确认金额。整个链路走通,你就亲眼看到了三层加载:索引常驻、正文按需、脚本显式执行。
5. 把 MCP 调用链接进 Skill 工作流
Skill 和 MCP 经常被混为一谈,其实它们在不同层。MCP 告诉 Agent“你有哪些手脚可用”,Skill 告诉 Agent“遇到这类活该怎么动手”。一个 Skill 内部完全可以调用 MCP 提供的 Tool。
假设你有一个 MCP Server 暴露了query_invoice_db这个工具,用来查历史发票。在SKILL.md里可以这样写工作流:
## 工作流程 1. 执行 scripts/extract_fields.py 提取字段 2. 调用 MCP 工具 query_invoice_db,用 invoice_no 查历史记录 3. 对比金额,不一致时标记异常 4. 执行 scripts/fill.py 回写MCP Server 的配置放在settings.json里:
{ "mcpServers": { "invoice-db": { "command": "python3", "args": ["-m", "mcp_server.invoice"], "env": { "DB_PATH": "./data/invoices.db" } } } }验证 MCP 调用链是否通,先单独测 MCP Server 能不能起来:
python3 -m mcp_server.invoice --test预期输出里能看到工具列表,包含query_invoice_db。然后在 Claude Code 里发任务:“提取这张发票字段,并查一下历史记录。”观察日志,你会看到调用顺序:先读SKILL.md正文,再执行extract_fields.py,然后触发 MCP 工具调用,最后按结果决定是否执行fill.py。
这里有个容易踩的坑:MCP 工具返回的数据格式要和 Skill 正文里描述的一致。如果正文写“对比金额”,但 MCP 返回的是字符串而不是数字,Agent 可能判断失误。建议在SKILL.md里明确字段类型,或者在脚本里做一层归一化。
提示:MCP Server 不要直连生产数据库。用只读账号或者本地副本,Skill 里的脚本也一样,
workdir指向临时目录,避免误写。
6. 本篇常见错排查
跑不通的时候,按下面几条逐个对。
Skill 没被命中。九成是description写得太泛。比如只写“处理 PDF”,Agent 不知道什么时候该用。改成“当用户上传 .pdf 发票、要求填写字段或核对金额时使用”,把触发场景写具体。另外检查settings.json里skills.directories路径对不对,~在某些运行时里不展开,建议写绝对路径。
正文加载了但脚本不执行。看permissions.allow有没有放开对应命令。Claude Code 默认会拦 Bash 调用,Bash(python3:*)这种写法要精确匹配。如果脚本路径是相对路径,确认workdir设置正确,否则会找不到文件。
渐进式披露没生效,所有 Skill 正文都被塞进 Context。检查config.toml里progressive_disclosure是不是true,以及max_index_tokens是不是设得太大。有些旧版本运行时默认全量加载,升级后才有这个开关。
MCP 工具调用超时。先单独跑 MCP Server 的测试命令,确认它能起来。如果 Server 正常但 Agent 调不到,检查mcpServers配置里的command和args能不能在运行时环境里执行,环境变量有没有传进去。
返回 401 或 403。Key 问题。去 API Keys 页面重新生成一个,确认配置里没有多余空格。如果用的是 Coding Plan,确认套餐还在有效期内。
返回 404。大概率是base_url写错。TaoToken 的基址是https://taotoken.net/api,不要自己加/v1,SDK 会拼。如果用的是原生 HTTP 请求,路径是/v1/messages。
排查顺序建议从通道开始:先用 curl 确认 Key 和基址没问题,再查 Skill 目录和配置,最后看脚本和 MCP。这样能快速定位是通道问题还是 Skill 本身的问题。
7. 继续往下走:从会用走向懂原理
把上面这套跑通,你手里就有了一个可复现的端到端链路:TaoToken 统一 Key 打通通道,settings.json和config.toml控制 Skill 扫描与渐进式披露,SKILL.md定义工作流,脚本和 MCP 工具负责确定性执行。
接下来想深入,建议做两件事。一是打开调试日志,把 Level 1、Level 2、Level 3 的加载时机逐条对照,你会对“索引 + 按需读取 + 代码执行”这套机制有肌肉记忆。二是试着把一个大 Skill 拆成三个小 Skill,观察 Agent 怎么按需组合,这比读十篇原理文章都管用。
需要长期跑编码或 Agent 任务的话,Coding Plan 比按量计费省心,地址在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。接入文档和 SDK 示例在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,遇到配置问题先翻这里。想直接验证模型对话效果,模型对话入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite 。
最后留一个我踩过的坑:Skill 目录别放太多东西,assets/里塞大文件会让扫描变慢,而且容易误提交。脚本和模板分开管理,SKILL.md保持“薄”,细节全丢reference.md。这样 Agent 读正文快,你维护也轻松。