1. 为什么你的 Agent 技能总是“跑一次就废”
如果你正在做 AI 智能体开发,大概率遇到过这种场景:写了一个能自动整理会议纪要的技能,在本地测试时跑得挺顺,换台机器或者换个模型调用就报错;想把“PDF 合并”这个能力复用到另一个 Agent 项目里,发现代码和 Prompt 缠在一起,拆都拆不干净。这不是你代码写得不好,而是缺少一套让技能“可描述、可加载、可复用”的协议层。
OpenSkills 协议要解决的就是这个问题。它用 SKILL.md 作为技能的唯一描述入口,把“这个技能能做什么、什么时候触发、执行哪段脚本、边界在哪里”全部写清楚,Agent 运行时只需要读取这份描述,就能决定是否加载、如何调用。你可以把它理解成给 AI 智能体写的“接口文档 + 执行手册”,只不过这份文档是机器可解析的。
这篇文章面向已经动手写过 Agent 技能、但被复用和工程化卡住的开发者。我会用一个最小可跑的pdf-editor技能包做例子,从 SKILL.md 的写法、settings.json 与 config.toml 的骨架配置,到通过 TaoToken 统一 Key/API 通道完成一次真实的技能加载与调用验证,把整条链路串起来。你跟着做,本地就能跑通一次完整的“技能描述 → Agent 识别 → 脚本执行 → 结果回传”。
2. TaoToken 在 OpenSkills 链路里的位置
OpenSkills 协议本身只规定技能怎么描述、怎么组织目录,它不关心你的 Agent 用哪个模型、走哪条 API 通道。但工程化落地时,模型调用这一层如果每个技能、每个工具都单独配 Key,很快就会乱成一团。TaoToken 在这里扮演的是统一通道的角色:你只需要在配置里写一次 API 地址和 Key,Agent 调用模型、加载技能、执行脚本时都走同一条通道。
具体来说,TaoToken 提供兼容 OpenAI 风格的 API 入口,地址是https://taotoken.net/api。你在 settings.json 或 config.toml 里把 base_url 指向它,再填入在控制台生成的 API Key,Agent 侧就不需要关心底层是哪个模型。对于 OpenSkills 技能包来说,这意味着 SKILL.md 里描述的执行脚本可以专注于业务逻辑,模型调用统一由外层配置接管。
如果你还没生成 Key,可以先去控制台创建一个:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 。创建时建议按项目命名,比如openskills-pdf-editor,方便后面排查是哪个技能在调用。Key 生成后只显示一次,记得先复制到安全的地方。
3. 可复制的配置骨架:settings.json 与 config.toml
OpenSkills 技能包本身不强制你用什么配置文件格式,但工程化落地时,我建议把“技能加载配置”和“模型通道配置”分开写。下面这套骨架你可以直接复制,改掉路径和 Key 就能用。
3.1 settings.json:技能加载与通道绑定
这个文件放在项目根目录,负责告诉 Agent 去哪里找技能、用哪条 API 通道。
{ "agent": { "name": "openskills-demo", "skill_root": "./skills", "auto_load": true }, "llm": { "provider": "taotoken", "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoTokenKey", "model": "claude-sonnet-4-20250514", "timeout": 60 }, "skills": [ { "name": "pdf-editor", "path": "./skills/pdf-editor", "enabled": true, "entry": "SKILL.md" } ] }这里有几个点容易踩坑。skill_root是技能包的父目录,Agent 启动时会扫描这个目录下所有含 SKILL.md 的子目录。entry字段指定技能描述文件,OpenSkills 规范里固定是 SKILL.md,但显式写出来方便以后扩展。api_key不要硬编码在提交到 Git 的文件里,生产环境建议用环境变量注入,比如"api_key": "${TAOTOKEN_API_KEY}"。
3.2 config.toml:脚本执行层的参数
有些 Agent 框架用 TOML 管理执行层配置,比如脚本解释器路径、超时、日志级别。下面这份和上面的 settings.json 配套使用。
[executor] python_path = "/usr/bin/python3" script_timeout = 120 log_level = "INFO" log_dir = "./logs" [executor.env] PYTHONUNBUFFERED = "1" TAOTOKEN_BASE_URL = "https://taotoken.net/api" [skills.pdf-editor] enabled = true max_input_files = 50 allow_encrypted = falsemax_input_files和allow_encrypted这两个参数会直接映射到 SKILL.md 里描述的约束条件。这样做的好处是,技能的行为边界既写在 SKILL.md 里给模型看,也写在 config.toml 里给执行器看,两边一致,不会出现“模型以为能处理加密文件、脚本却直接报错”的割裂。
3.3 SKILL.md 的最小写法
技能描述文件不需要写得很长,但触发条件和执行路径必须明确。下面是一个可用的最小版本。
--- name: pdf-editor version: 1.0.0 description: 合并与旋转 PDF 文件,支持批量处理。 dependency: PyPDF2>=2.10.0 --- # PDF 编辑技能 ## 触发条件 当用户提出“合并 PDF”“拼接文档”“旋转页面”时加载本技能。 ## 执行动作 1. 合并:执行 scripts/merge_pdfs.py <output> <input1> <input2> ... 2. 旋转:执行 scripts/rotate_pdf.py <file> <angle> ## 边界 - 不支持加密 PDF。 - 单次合并不超过 50 个文件。这份描述里,description和触发条件是给模型看的,执行动作里的命令是给执行器看的。模型读到触发条件后决定是否加载,加载后按执行动作里的命令调用脚本。整个过程不需要模型“猜”该怎么执行。
4. 验证一次完整的技能加载与调用
配置写好后,别急着接复杂业务,先用一个最小请求验证通道和技能加载是否生效。
4.1 启动 Agent 并观察加载日志
假设你用的是支持 OpenSkills 的 Agent 框架,启动命令通常长这样:
export TAOTOKEN_API_KEY="sk-你的TaoTokenKey" python -m agent_runtime --config ./settings.json --executor-config ./config.toml启动后,日志里应该出现类似下面的内容:
[INFO] skill_root=./skills scanned, found 1 skill [INFO] loading skill: pdf-editor from ./skills/pdf-editor/SKILL.md [INFO] llm provider=taotoken base_url=https://taotoken.net/api [INFO] agent ready如果found 0 skill,先检查 SKILL.md 是否在skills/pdf-editor/目录下,文件名大小写是否一致。OpenSkills 规范里文件名是固定的SKILL.md,写成skill.md有些框架识别不了。
4.2 发一条触发技能的消息
启动成功后,发一条会命中触发条件的请求:
curl -X POST http://localhost:8000/chat \ -H "Content-Type: application/json" \ -d '{"message": "帮我把 ./docs/a.pdf 和 ./docs/b.pdf 合并成 ./docs/merged.pdf"}'预期返回里应该包含技能被加载、脚本被调用的痕迹:
{ "reply": "已调用 pdf-editor 技能完成合并。", "skill_used": "pdf-editor", "action": "merge", "output": "./docs/merged.pdf", "status": "success" }同时本地./docs/merged.pdf应该真实生成。如果返回里skill_used为空,说明模型没有命中触发条件,检查 SKILL.md 里的触发词是否覆盖了用户说法,比如用户说“拼接”,你的触发条件里只写了“合并”,就可能漏掉。
4.3 确认通道生效
想确认请求确实走了 TaoToken 通道,可以在 config.toml 里把log_level调到DEBUG,然后看日志里是否有向https://taotoken.net/api发起的请求记录。另一种方式是去 TaoToken 控制台的用量页面看调用记录:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 。如果能看到对应时间点的调用,说明通道配置正确。
5. 本篇常见错排查
5.1 技能加载了但脚本不执行
最常见的原因是 SKILL.md 里的命令路径写的是相对路径,而执行器的工作目录不是技能包根目录。解决办法是在 config.toml 里显式指定work_dir,或者在 SKILL.md 里用绝对路径。我试过在 SKILL.md 里写python3 scripts/merge_pdfs.py,结果执行器从项目根目录找scripts/,自然找不到。改成python3 ./skills/pdf-editor/scripts/merge_pdfs.py就正常了。
5.2 报 401 或 invalid api key
先确认settings.json里的api_key没有多余空格,再确认环境变量是否覆盖了配置文件。有些框架的优先级是环境变量 > 配置文件,如果你在 shell 里 export 了一个旧的 Key,配置文件里写新的也没用。另外检查base_url是否写成了https://taotoken.net/api,末尾不要多加斜杠。
5.3 模型不触发技能
如果日志显示技能已加载,但模型回复里没有调用技能,通常是 SKILL.md 的description写得太泛。比如只写“处理 PDF”,模型不知道具体能做什么。改成“合并多个 PDF 文件、旋转页面角度”这种具体动作,命中率会高很多。另外触发条件里最好把用户可能说的同义词都列上,比如“合并、拼接、追加”。
5.4 脚本超时
大文件合并时容易超时。config.toml 里的script_timeout默认 120 秒,如果文件超过 100MB,建议调到 300 秒。同时检查 SKILL.md 里是否写了文件数量限制,超过限制时应该让模型先提示用户分批,而不是硬跑导致超时。
6. 把技能包变成可复用资产
跑通一次加载和调用之后,你可以把pdf-editor这个技能包直接复制到另一个 Agent 项目里,只需要改 settings.json 里的skill_root和skills[].path,SKILL.md 和脚本都不用动。这就是 OpenSkills 协议带来的复用性:技能描述和执行逻辑绑在一起,模型通道配置独立在外层。
如果你打算长期做 Agent 开发,建议把常用技能都按这个结构整理,每个技能一个目录,SKILL.md 写清楚触发条件和边界,脚本只做确定性执行。模型调用统一走 TaoToken 通道,Key 在控制台按项目生成,方便追踪用量。需要看模型对话效果时,可以直接在模型对话页测试:https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 。长期跑编码类 Agent 的话,Coding Plan 更适合按量使用:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。
接入文档里有更完整的参数说明,遇到配置项不确定时可以直接查:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。API Key 管理在控制台的 API Keys 页面:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。