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_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台生成 Key 即可。这里要强调一个原则Skill 里不要写死模型厂商的地址而是把 Base URL、API Key、Model ID 这三件套抽成环境变量或 Skill 的 config 字段。这样你换模型、换通道、做灰度都只改一处。TaoToken 的接口兼容主流协议Skill 里用 axios 或 fetch 直接请求就行不需要额外 SDK。具体操作上先去控制台创建 API Key地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。拿到 Key 之后在 Skill 的 manifest.json 里把 api_key 声明成 required 的 config 项运行时由 OpenClaw 注入。模型 ID 建议也做成可配置方便你后面切换不同能力的模型。如果你打算长期跑编码类或 Agent 类任务可以了解下 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 它更适合高频调用的场景。前置准备清单其实就三样Node.js 22 以上、OpenClaw CLI、一把 TaoToken Key。Node 版本用node -v确认建议 v22OpenClaw 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_KEYsk-你的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/apiKey 用控制台生成的Model ID 按需选。文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到字段对不上可以对照查。4. 验证请求与成功结果本地跑通第一个 Skill配置写完不算完得实际跑一遍确认链路通。验证分三步加载、测试、看日志。第一步加载 Skillopenclaw 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_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 输入同样的 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/apiKey 填控制台生成的Model ID 填你实际要用的。少任何一个都会在鉴权阶段失败。同理CC Switch 或 Cline MCP 里配置时也是这三件套别只填 Key 漏了 Base URL。排查顺序建议固定成先 curl 打通道 → 再 test 打 Skill → 最后看 logs 定位。这样能把问题范围快速二分不用瞎猜。6. 把 Skill 跑起来之后接入文档与后续动作Skill 本地跑通只是第一步接下来要让它稳定服务于你的实际场景。几个实用建议把 config 里的三件套统一走环境变量或密钥管理别提交到仓库给 execute 加超时和重试模型调用偶尔抖动是正常的日志里记录请求 ID 和耗时方便后面做性能分析。如果你要接更多模型能力接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 字段和路径都以文档为准。Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 建议按 Skill 或环境分 Key方便单独轮换。想快速验证模型输出用 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。长期跑编码或 Agent 任务看 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。最后一个实操技巧写完一个 Skill 后先别急着发布用openclaw skills test跑三组边界参数——空输入、超长输入、非法类型输入。这三组能过基本就稳了。我踩过的坑里八成线上问题都是边界没测导致的。