1. 从“只会聊天”到“能干活”:OpenClaw Skills 开发到底难在哪
OpenClaw Skills 开发这件事,说白了就是给你的 AI Agent 装上一双能干活的手。OpenClaw 本身是一个自托管的 AI Agent 网关,能把 Discord、Telegram、微信、QQ 这些通讯工具和主流大模型串起来,但装完之后很多人会发现一个尴尬的现实:它只会聊天,不会干活。你让它查个天气,它给你编一段;你让它读个文件,它说做不到。核心原因就一个——没装 Skills。
Skills 是 OpenClaw 的核心扩展机制,你可以把它理解成手机上的 App。手机出厂只能打电话发短信,装了微信才能聊天,装了地图才能导航。OpenClaw 也一样,原生只支持基础对话和简单命令,文件读写、API 调用、数据库查询、自动化工作流这些统统做不了。而 Skills 就是把这些能力封装成可复用的模块,让 AI 能像人类专家一样按需调用专业能力。
截至 2026 年 3 月,ClawHub 上已经收录了超过 13700 个社区技能,国内也有 CocoLoop 这样的技能商店提供本地化服务。但问题在于,现成的技能不一定贴合你的业务场景。你公司内部的工单系统、你个人的笔记格式、你团队特有的部署流程,这些别人不会替你开发。所以真正想让 OpenClaw 在你的环境里跑起来,自己动手写 Skill 是绕不过去的一步。
这篇文章面向的是已经装好 OpenClaw、想让 Agent 真正干活的开发者。我会从 Skill 的目录结构和触发机制讲起,然后重点演示怎么用 TaoToken 统一 Key 通道给 Skill 接入模型能力,最后给出一份可以直接复制的 Skill 配置模板和本地验证动作。跟着走一遍,你就能跑通第一个自定义 Skill。
2. TaoToken 统一 Key 通道:给 Skill 接上模型能力的前置准备
写 Skill 的时候有一个很容易被忽略的环节:Skill 本身只是逻辑封装,它要真正“智能”起来,往往需要在执行过程中调用大模型。比如一个“智能摘要”Skill,它得把长文本丢给模型做压缩;一个“代码审查”Skill,它得让模型分析 diff 并给出建议。这时候你就需要一个稳定、统一、好管理的模型调用通道。
我试过在多个 Skill 里分别硬编码不同厂商的 Key,结果就是密钥散落在各个 manifest 和配置文件里,轮换一次要改十几个地方,还容易漏。后来改成用 TaoToken 做统一 Key 通道,所有 Skill 都通过同一个 Base URL 和同一把 Key 去请求模型,管理成本直接降下来。TaoToken 的 API 地址是 https://taotoken.net/api,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,注册后在控制台生成 Key 即可。
这里要强调一个原则:Skill 里不要写死模型厂商的地址,而是把 Base URL、API Key、Model ID 这三件套抽成环境变量或 Skill 的 config 字段。这样你换模型、换通道、做灰度,都只改一处。TaoToken 的接口兼容主流协议,Skill 里用 axios 或 fetch 直接请求就行,不需要额外 SDK。
具体操作上,先去控制台创建 API Key,地址是 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 。拿到 Key 之后,在 Skill 的 manifest.json 里把 api_key 声明成 required 的 config 项,运行时由 OpenClaw 注入。模型 ID 建议也做成可配置,方便你后面切换不同能力的模型。如果你打算长期跑编码类或 Agent 类任务,可以了解下 Coding Plan,地址是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite ,它更适合高频调用的场景。
前置准备清单其实就三样:Node.js 22 以上、OpenClaw CLI、一把 TaoToken Key。Node 版本用node -v确认,建议 v22+;OpenClaw CLI 用npm install -g openclaw装;Key 从上面控制台拿。这三样齐了,后面的配置就能直接复制粘贴跑起来。
3. 可复制配置:Skill 目录结构、manifest 与模型调用模板
这一节是全文最核心的部分,我给出一份可以直接复制、改改就能用的 Skill 配置模板。先看目录结构,一个标准 Skill 长这样:
my-first-skill/ ├── manifest.json # 技能描述:名称、版本、权限、config ├── src/ │ ├── index.js # 主逻辑:execute / validate │ └── llm.js # 模型调用封装(走 TaoToken) ├── schema.json # 输入输出定义 ├── README.md # 使用文档 └── tests/ # 测试文件初始化用openclaw skills init my-first-skill就能生成骨架。接下来是 manifest.json,注意 config 里把 TaoToken 的三件套都声明出来:
{ "name": "smart-summary", "version": "1.0.0", "description": "调用模型对长文本做智能摘要,支持自定义长度", "author": "YourName", "license": "MIT", "keywords": ["summary", "llm", "taotoken"], "entry": "src/index.js", "permissions": ["http_request"], "dependencies": { "axios": "^1.6.0" }, "config": { "base_url": { "type": "string", "required": true, "default": "https://taotoken.net/api", "description": "TaoToken 统一 Base URL" }, "api_key": { "type": "string", "required": true, "description": "TaoToken API Key" }, "model_id": { "type": "string", "required": true, "default": "claude-sonnet-4-5", "description": "模型 ID,可按需切换" } } }然后是模型调用封装 src/llm.js,把三件套拼成请求,注意路径和字段名要和通道文档保持一致:
const axios = require('axios'); async function chat(config, messages, options = {}) { const { base_url, api_key, model_id } = config; const url = `${base_url.replace(/\/$/, '')}/v1/messages`; const resp = await axios.post( url, { model: model_id, max_tokens: options.max_tokens || 1024, messages }, { headers: { 'Content-Type': 'application/json', 'x-api-key': api_key, 'anthropic-version': '2023-06-01' }, timeout: 60000 } ); const content = resp.data?.content; if (Array.isArray(content)) { return content.map(c => c.text || '').join(''); } return resp.data?.choices?.[0]?.message?.content || ''; } module.exports = { chat };主逻辑 src/index.js 里,execute 负责编排,validate 负责参数校验:
const { chat } = require('./llm'); module.exports = { name: 'smart-summary', description: '对长文本做智能摘要', parameters: { text: { type: 'string', required: true, description: '待摘要文本' }, max_words: { type: 'integer', required: false, default: 200 } }, async validate(params) { if (!params.text || typeof params.text !== 'string') { throw new Error('text 必须是非空字符串'); } return true; }, async execute(params, context) { const { text, max_words } = params; const cfg = context.config; try { const summary = await chat(cfg, [ { role: 'user', content: `请把下面文本压缩到 ${max_words} 字以内,保留关键信息:\n\n${text}` } ]); return { success: true, data: { summary } }; } catch (error) { return { success: false, error: error.message, code: error.response?.status || 'UNKNOWN_ERROR' }; } } };schema.json 定义输入输出,方便 OpenClaw 做参数推断:
{ "input": { "type": "object", "properties": { "text": { "type": "string", "description": "待摘要文本" }, "max_words": { "type": "integer", "default": 200 } }, "required": ["text"] }, "output": { "type": "object", "properties": { "success": { "type": "boolean" }, "data": { "type": "object", "properties": { "summary": { "type": "string" } } }, "error": { "type": "string" } } } }配置写完后,把 TaoToken 的 Key 通过环境变量注入,避免明文写进文件:
export TAOTOKEN_API_KEY="sk-你的key" openclaw skills load ./my-first-skill \ --config '{"base_url":"https://taotoken.net/api","api_key":"'$TAOTOKEN_API_KEY'","model_id":"claude-sonnet-4-5"}'如果你用的是 Claude Code 做 Skill 的辅助开发,接入方式也是同一套三件套,Base URL 填 https://taotoken.net/api,Key 用控制台生成的,Model ID 按需选。文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,遇到字段对不上可以对照查。
4. 验证请求与成功结果:本地跑通第一个 Skill
配置写完不算完,得实际跑一遍确认链路通。验证分三步:加载、测试、看日志。
第一步,加载 Skill:
openclaw skills load ./my-first-skill如果 manifest 或 schema 有语法错误,这一步会直接报出来,先修到不报错为止。
第二步,用 test 命令触发一次真实调用:
openclaw skills test smart-summary \ --params '{"text":"OpenClaw 是一个自托管的 AI Agent 网关,支持多通讯工具接入。Skills 是它的核心扩展机制,能把复杂业务逻辑封装成可复用模块。","max_words":50}'预期返回类似:
{ "success": true, "data": { "summary": "OpenClaw 是自托管 AI Agent 网关,Skills 是其核心扩展机制,可将业务逻辑封装为可复用模块。" } }看到 success 为 true 且 summary 有内容,说明从 Skill 到 TaoToken 再到模型的整条链路是通的。如果返回 success 为 false,先看 error 字段,再对照下一节的排查表。
第三步,看日志确认请求细节:
openclaw logs --skill smart-summary日志里能看到请求的 URL、状态码、耗时。正常应该是 200,耗时取决于模型和文本长度。如果状态码是 401,说明 Key 有问题;如果是 404,多半是 Base URL 或路径拼错了。
再补一个验证模型通道是否独立可用的动作,直接用 curl 打一次,排除 Skill 层干扰:
curl -X POST https://taotoken.net/api/v1/messages \ -H "Content-Type: application/json" \ -H "x-api-key: $TAOTOKEN_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -d '{"model":"claude-sonnet-4-5","max_tokens":64,"messages":[{"role":"user","content":"回复 OK"}]}'返回里有 content 字段就说明通道本身没问题,问题就缩小到 Skill 配置层了。这个二分法排查很省时间,建议养成习惯。想直接在网页上验证模型对话效果,可以用 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite ,输入同样的 prompt 对比结果。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
这一节把实际开发中最容易撞上的几类报错列出来,对照着改。
401 Unauthorized。最常见,九成是 Key 的问题。检查三处:环境变量 TAOTOKEN_API_KEY 是否真的导出成功(echo $TAOTOKEN_API_KEY看有没有值);manifest 里 api_key 是否 required 且被正确注入;请求头字段名是否写对,TaoToken 用 x-api-key,别写成 Authorization Bearer。如果 Key 刚生成,确认没有多余空格或换行。
local proxy failed。这个报错通常出现在你本地配了转发规则但目标地址不可达的时候。先确认 base_url 是 https://taotoken.net/api 而不是别的地址;再确认本机网络能正常访问该域名(curl -I https://taotoken.net/api看返回)。如果公司网络有出口限制,找网络管理员确认放行,不要自己搭转发。
reading 'choices' of undefined。这是解析响应时字段对不上导致的。TaoToken 的 messages 接口返回结构是 content 数组,不是 choices。如果你照搬了某些 OpenAI 风格的解析代码,就会读到 undefined。改法就是第 3 节 llm.js 里的写法,先判断 content 是否为数组,再兜底读 choices。两套结构都兼容,能省很多事。
OAuth 相关报错。如果你在 Skill 里集成了需要 OAuth 的第三方服务(比如某些协作平台),报错多半是 token 过期或回调地址不匹配。检查 refresh token 逻辑是否实现,回调地址是否和平台后台登记的一致。OAuth 的 token 建议也走统一配置管理,别散落在代码里。
Codex auth.json 场景。如果你用 Codex 类工具配合 Skill 开发,auth.json 里的字段要和实际通道对齐。三件套缺一不可:Base URL 填 https://taotoken.net/api,Key 填控制台生成的,Model ID 填你实际要用的。少任何一个都会在鉴权阶段失败。同理,CC Switch 或 Cline MCP 里配置时也是这三件套,别只填 Key 漏了 Base URL。
排查顺序建议固定成:先 curl 打通道 → 再 test 打 Skill → 最后看 logs 定位。这样能把问题范围快速二分,不用瞎猜。
6. 把 Skill 跑起来之后:接入文档与后续动作
Skill 本地跑通只是第一步,接下来要让它稳定服务于你的实际场景。几个实用建议:把 config 里的三件套统一走环境变量或密钥管理,别提交到仓库;给 execute 加超时和重试,模型调用偶尔抖动是正常的;日志里记录请求 ID 和耗时,方便后面做性能分析。
如果你要接更多模型能力,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,字段和路径都以文档为准。Key 管理在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite ,建议按 Skill 或环境分 Key,方便单独轮换。想快速验证模型输出,用 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite 。长期跑编码或 Agent 任务,看 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。
最后一个实操技巧:写完一个 Skill 后,先别急着发布,用openclaw skills test跑三组边界参数——空输入、超长输入、非法类型输入。这三组能过,基本就稳了。我踩过的坑里,八成线上问题都是边界没测导致的。