ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OpenClaw 自定义技能(Skill)完整开发教程:从 SKILL.md 到 manifest.json 的 TaoToken 接入实践

OpenClaw 自定义技能(Skill)完整开发教程:从 SKILL.md 到 manifest.json 的 TaoToken 接入实践 1. 从零理解 OpenClaw SkillSKILL.md 与 manifest.json 到底管什么OpenClaw 自定义技能Skill是让 AI 真正动手操作电脑、调用接口、处理文件的最小可插拔单元。你可以把它理解成给 Agent 装的一个“插件包”Gateway 接收指令Agent 判断需求匹配到自定义 Skill 后执行最后把结果写进 Memory。整个链路里Skill 就是那个真正干活的执行载体。它分两类。一类是轻量文档型 Skill只需要一个 SKILL.md用自然语言写清楚触发规则和执行步骤不用写代码适合文件整理、简易 shell 脚本、固定重复流程。另一类是代码插件型 Skill需要 manifest.json 声明权限、参数、运行环境再配 index.js 或 main.py 写完整逻辑适合接口调用、数据库读写、复杂循环、参数校验、密钥安全存储。我试过把这两类混着用简单任务用 SKILL.md 快速搭复杂业务用代码型 Skill 兜底。实测下来新手最容易卡在“技能目录结构”和“manifest 权限声明”这两步所以这篇教程会把 SKILL.md 模板、manifest.json 配置片段、openclaw-sdk 调用链路全部拆开讲最后用 TaoToken 统一 Key/API 通道完成一次真实技能调用验证。所有自定义技能统一存放在~/.openclaw/workspace/skills/下WindowsWSL2、Linux、macOS 路径一致。单个技能文件夹的完整结构如下my-office-stat/ # 技能唯一名称小写、连字符不能中文 ├── SKILL.md # 【必需】技能元数据功能描述AI识别调用的核心 ├── manifest.json # 【代码型必需】权限、参数、运行环境声明 ├── index.js / index.ts # 【代码型必需】主执行逻辑入口 ├── scripts/ # 可选存放bash/python辅助脚本 ├── assets/ # 可选报表模板、静态资源 └── references/ # 可选API文档、业务参考资料技能目录支持热加载修改文件无需重启网关系统会自动监听变更。这一点对开发调试非常友好——你改完 SKILL.md 或 index.js保存后直接发指令测试即可。开发前的前置环境准备只有两步。第一确认 OpenClaw 已完整部署、网关正常运行openclaw gateway start -d openclaw status第二选开发依赖。JS/TS 开发是官方推荐路线Node.js 22 LTS 内置 openclaw-sdk无需额外安装Python 开发需要 Python 3.10并在 manifest 里把 runtime 声明为 python。两条路线在 manifest 结构上几乎一致只是 entry 指向的文件和运行时不同。理解清楚“SKILL.md 管识别、manifest.json 管约束、index.js 管执行”这个分工后面写代码就不会迷路。SKILL.md 里的 description 直接决定 Agent 何时调用你manifest 里的 permissions 决定沙箱放不放行index.js 的返回格式决定 Agent 能不能解析结果。三者缺一技能要么不被触发要么被沙箱拦截要么返回一堆 Agent 读不懂的数据。2. TaoToken 前置准备统一 Key 与 API 通道在写技能调用外部模型或接口之前先把 TaoToken 的通道准备好。TaoToken 提供统一的 Key 和 API 入口技能里所有需要调用大模型或外部能力的请求都可以走这一条通道避免在每个 Skill 里散落不同的密钥和地址。你需要先拿到两样东西API Key 和 Base URL。API Key 在控制台的 API Keys 页面创建Base URL 统一使用https://taotoken.net/api。创建 Key 的入口在这里https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentskill_devutm_campaignrewrite拿到 Key 之后不要硬编码进 index.js。正确做法是通过 OpenClaw 的全局环境变量注入技能代码里用context.env.XXX读取。这样密钥不会进版本库也方便多环境切换openclaw config set taotoken.api_key sk-你的实际Key openclaw config set taotoken.base_url https://taotoken.net/api配置完成后技能代码里这样读取const apiKey context.env.taotoken_api_key; const baseUrl context.env.taotoken_base_url;如果你打算在技能里调用模型对话能力做文本处理可以直接走模型对话入口验证通道是否通https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentskill_devutm_campaignrewrite对于需要长期跑编码类或 Agent 类任务的场景Coding Plan 更适合作为底层通道技能里调用时同样复用上面这套 Base URL 和 Keyhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentskill_devutm_campaignrewrite这里有个关键点manifest.json 的requires.env字段要声明技能依赖哪些环境变量沙箱才会把对应的值注入到context.env。如果你在代码里读了taotoken_api_key但 manifest 里没声明运行时拿到的就是 undefined。声明方式如下requires: { env: [taotoken_api_key, taotoken_base_url] }把 Key 和 Base URL 准备好、在 manifest 里声明依赖、代码里用 context.env 读取这三步做完技能就有了调用外部能力的“通行证”。接下来进入可复制配置环节。3. 可复制配置SKILL.md 模板与 manifest.json 片段这一节给出可以直接复制粘贴的两套配置。先看零代码的 SKILL.md 模板再看代码型的 manifest.json 完整片段。3.1 SKILL.md 模板零代码轻量技能SKILL.md 顶部用---包裹 YAML 元数据下方写 Markdown 功能说明和执行逻辑。以文本批量处理技能为例--- name: text-batch-handle description: 批量处理本地文本文件支持去重、大小写转换、关键词提取当用户需要批量处理txt文档时自动调用 emoji: user-invocable: true always: false os: [linux, darwin, win32] --- # 文本批量处理技能 ## 触发规则 用户指令包含批量txt、文本去重、大小写转换、提取关键词时优先使用本技能。 ## 入参 1. dir_path本地文件夹绝对路径必填 2. operate操作类型可选 deduplicate / upper / lower / keyword ## 执行步骤 1. 读取 dir_path 下全部 .txt 文件 2. 根据 operate 执行对应文本处理 3. 在目录生成 result.md 汇总结果 ## 执行脚本 bash for file in $dir_path/*.txt; do cat $file temp-all.txt done返回要求输出处理完成文件路径、总处理文件数量关键字段说明name 全局唯一小写字母加连字符不可重复description 最关键Agent 依赖这段文字判断何时调用该技能描述越清晰匹配越精准user-invocable: true 允许用户手动斜杠命令调用 /text-batch-handleos 限制运行系统全兼容填 [linux,darwin,win32]。 ### 3.2 manifest.json 完整片段代码型技能 manifest.json 声明技能权限、入参 JSON Schema、依赖环境变量、运行时类型。沙箱会根据配置放行文件或网络权限。以下是一个查询类技能的完整配置 json { name: stock-query, version: 1.0.0, author: 自定义开发者, runtime: node, entry: ./index.js, description: 查询A股实时股票行情传入股票代码返回价格、涨跌幅, user-invocable: true, permissions: { network: { allow: [hq.sinajs.cn] }, fs: { write: [~/.openclaw/workspace/skills/stock-query/cache/] } }, input: { type: object, required: [stock_code], properties: { stock_code: { type: string, description: A股6位股票代码 } } }, output: { type: object, properties: { success: {type: boolean}, message: {type: string}, data: {type: object} } }, requires: { env: [taotoken_api_key, taotoken_base_url] }, metadata: { openclaw: { emoji: , os: [linux, darwin, win32] } } }核心配置项拆解。permissions遵循最小权限原则禁止全盘读写和无限制网络fs.read/write只开放业务必需目录network.allow只放行目标 API 域名禁止填*。input是入参校验AI 调用时自动校验参数完整性缺失直接报错。runtime填 node 或 python对应入口文件语言。requires.env声明技能依赖的环境变量沙箱据此注入。3.3 index.js 执行入口openclaw-sdk代码型技能固定导出execute异步函数框架内置 openclaw-sdk提供上下文、日志、环境变量读取能力const { SkillContext } require(openclaw-sdk); const http require(http); const fs require(fs); const path require(path); /** * 技能统一执行入口 * param {SkillContext} context 上下文对象参数、日志、环境变量 * returns 标准化返回结果 */ exports.execute async function (context) { try { const { stock_code } context.parameters; context.log.info(开始查询股票${stock_code}); let url; if (stock_code.startsWith(6)) { url http://hq.sinajs.cn/lists_sh${stock_code}; } else { url http://hq.sinajs.cn/lists_sz${stock_code}; } const stockData await new Promise((resolve, reject) { http.get(url, (res) { let raw ; res.on(data, chunk raw chunk); res.on(end, () resolve(raw)); }).on(error, reject); }); const match stockData.match(/([^])/); if (!match) throw new Error(未查询到该股票信息); const arr match[1].split(,); const result { name: arr[0], open: arr[1], close: arr[2], high: arr[3], low: arr[4], change: (Number(arr[2]) - Number(arr[1])).toFixed(2) }; const cachePath path.join(__dirname, ./cache/stock-cache.json); fs.mkdirSync(path.dirname(cachePath), { recursive: true }); fs.writeFileSync(cachePath, JSON.stringify(result, null, 2)); return { success: true, message: 股票${stock_code}行情查询完成, data: result }; } catch (err) { context.log.error(技能执行失败, err.message); return { success: false, message: 查询失败${err.message}, data: null }; } };context 内置能力context.parameters是 AI 传入的入参context.log.info/warn/error写入全局日志用openclaw logs查看context.env.XXX读取全局环境变量如 API 密钥context.sessionId是当前会话 ID用于区分不同用户任务。如果你要在技能里调用 TaoToken 的模型能力把请求地址换成context.env.taotoken_base_url请求头带上context.env.taotoken_api_key即可其余逻辑不变。4. 验证请求从加载到成功返回的完整链路配置写完接下来验证技能是否真的跑通。整个过程分四步自动加载、确认列表、发指令触发、查看返回。第一步保存文件后网关自动扫描识别新技能。你可以用列表命令确认技能已被加载openclaw skills list如果看到stock-query出现在可用自定义技能列表里说明 SKILL.md 和 manifest.json 的元数据被正确解析。如果没出现先检查技能目录名是否小写连字符、manifest 是否 JSON 语法错误。第二步启用技能并实时查看运行日志openclaw skills enable stock-query openclaw logs --follow--follow会持续输出日志方便你在发指令时观察技能是否被触发、执行到哪一步。第三步在 Web 面板发送测试指令查询股票600036实时行情Agent 会自动识别并匹配stock-query技能拉取行情并返回格式化数据。此时日志里应该能看到开始查询股票600036这条 info 记录说明context.log.info生效、参数正确传入。第四步确认返回结果。技能返回的标准格式是{success, message, data}Agent 解析后展示给用户。如果返回success: truedata 里包含 name、open、close、high、low、change 字段说明整条链路打通。对于零代码的 SKILL.md 技能验证方式类似。保存文件后网关热加载发送指令把D盘笔记文件夹所有txt批量提取关键词生成汇总文件Agent 自动识别匹配text-batch-handle技能执行。你可以在日志里看到脚本执行过程执行完成后目录下生成 result.md。如果你在技能里接了 TaoToken 的模型通道做文本处理验证时可以发一条需要模型能力的指令观察请求是否成功返回。通道验证入口https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentskill_verifyutm_campaignrewrite实测下来验证环节最容易忽略的是“环境变量声明”。如果你在代码里读了taotoken_api_key但 manifest 的requires.env没写运行时context.env.taotoken_api_key就是 undefined请求会直接失败。所以验证前先对照 manifest 检查一遍 env 声明。另外新增环境变量后需要重启网关才能生效openclaw gateway restart技能元数据修改如 SKILL.md 的 description则无需重启热加载即可。区分清楚这两类变更能省不少调试时间。5. 常见报错排查401、local proxy failed、reading choices、OAuth技能开发过程中会遇到几类典型报错这一节逐个对照排查。401 Unauthorized。技能调用外部接口返回 401九成是 Key 没正确注入。排查顺序先确认openclaw config set taotoken.api_key已执行再确认 manifest 的requires.env里声明了taotoken_api_key最后确认代码里读的是context.env.taotoken_api_key而不是别的变量名。三处变量名必须完全一致。如果 Key 本身过期去控制台重新创建https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentskill_401utm_campaignrewritelocal proxy failed。这个报错通常出现在技能发起网络请求时沙箱拦截了目标域名。检查 manifest 的permissions.network.allow是否包含你要访问的域名。注意这里填的是域名不是完整 URL也不要用*通配。如果技能要访问 TaoToken 的 API把taotoken.net加进 allow 列表。改完 manifest 后需要重启网关。reading choices 报错。这类报错一般出现在技能解析模型返回结果时返回结构里没有预期的choices字段。原因可能是请求体格式不对或者模型 ID 写错。检查你的请求 JSON 是否符合接口规范model 字段是否填了有效的模型 ID。如果你走的是 TaoToken 通道Base URL 用https://taotoken.net/api不要多加路径后缀。OAuth 相关报错。如果技能里集成了需要 OAuth 授权的第三方服务报错通常指向 token 过期或回调地址不匹配。检查授权配置里的 redirect URI 是否和实际一致token 是否需要刷新。对于这类技能建议把 token 刷新逻辑单独封装避免每次调用都重新授权。除了这四类还有几个高频坑。技能名称含中文或大写会导致加载失败必须小写连字符。manifest 权限配置过宽会触发沙箱拦截文件读写和网络请求直接报错用openclaw doctor skills一键检测。SKILL.md 的 description 描述模糊会导致 Agent 无法匹配调用要写清触发场景加完整功能。Windows WSL 路径必须用 Linux 格式/mnt/d/xxx不能用D:\xxx。代码返回格式必须固定{success, message, data}否则 Agent 无法解析执行结果。排查时善用这两个命令openclaw doctor skills openclaw logs --follow前者做配置体检后者看实时执行日志。大部分问题看日志就能定位到具体哪一步失败。6. 技能发布与持续接入从本地跑通到可复用技能在本地跑通后如果逻辑稳定可以打包发布到 ClawHub 社区让其他用户一键安装。发布前先完善 SKILL.md 的使用文档和参数说明补充 README 和示例调用指令然后执行打包clawhub package ./stock-query clawhub publish stock-query-1.0.0.clawpkg其他用户安装你的技能只需一条命令clawhub install stock-query对于需要长期运行、频繁调用模型能力的技能建议把底层通道切到 Coding Plan避免每次单独配置 Key。技能代码里复用同一套 Base URL 和 Key 读取逻辑切换通道时只改环境变量不动业务代码https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentskill_publishutm_campaignrewrite日常运维常用命令整理如下建议收藏openclaw skills list # 查看所有本地技能 openclaw skills enable 技能名 # 启用自定义技能 openclaw skills disable 技能名 # 禁用自定义技能 openclaw doctor skills # 校验 manifest 配置、权限是否合规 openclaw logs --follow # 实时监控技能执行日志 openclaw gateway restart # 重新加载全部技能修改元数据后刷新 rm -rf ~/.openclaw/workspace/skills/技能名 # 卸载自定义技能最后分享一个实用技巧开发新技能时先用 SKILL.md 零代码版本验证触发逻辑和参数设计确认 Agent 能正确匹配后再把执行部分替换成 index.js 代码实现。这样能避免一上来就写代码、结果 Agent 根本不触发技能的尴尬。技能目录支持热加载改完保存直接测不用反复重启网关调试效率会高很多。
返回列表