ARTICLE DETAIL

资讯详情

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

为你的“小龙虾”OpenClaw开发自定义 Skills:从 SKILL.md 到 TypeScript/Shell 实战

为你的“小龙虾”OpenClaw开发自定义 Skills:从 SKILL.md 到 TypeScript/Shell 实战 1. 为什么我要给 OpenClaw 写自定义 SkillOpenClaw 这个被社区叫成“小龙虾”的开源 Agent 网关最舒服的地方在于它把「意图解析」和「能力执行」拆开了。内核负责听懂你要干什么Skill 只负责干活。这意味着你不需要去改内核代码只要按规范丢一个模块进去它就能多长出一只手。我一开始只是拿它做本地文件问答后来发现每次都要手动跑脚本统计目录、抓 RSS、查接口状态太碎。于是开始研究自定义 Skill 的开发路径。实测下来OpenClaw 目前有两条路一条是 TypeScript/JavaScript 模块走plugin.jsonindex.ts类型安全、适合复杂逻辑另一条是SKILL.md 脚本目录语言无关、门槛极低Shell、Python 都能塞进去。这篇就按这两条路各走一遍从SKILL.md骨架到 TypeScript/Shell 实现再到接入 TaoToken 统一 Key/API 通道做调用验证。适合已经跑起 OpenClaw 网关、想把自己的重复操作封装成 Skill 的人。如果你还没装 OpenClaw先把 Node.js 18 和网关服务准备好后面所有命令都基于http://localhost:18789这个默认监听地址。核心检索词先摆出来OpenClaw Skills 开发、SKILL.md 写法、TypeScript Skill 示例、Shell Skill 示例、TaoToken 接入。下面每一步都能直接复制。2. 前置TaoToken 统一 Key 与 OpenClaw 的对接位置Skill 本身不负责模型调用但很多 Skill 在执行过程中需要请求大模型比如让模型总结抓到的 RSS 标题、或者对文件报表做一句话点评。这时候如果每个 Skill 各自维护一套 API Key管理会非常乱。我的做法是统一走 TaoToken 的 API 通道一个 Key 覆盖多个模型Skill 里只读环境变量。TaoToken 的 API 地址是https://taotoken.net/api官网入口在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。你需要在控制台创建一个 API Key然后把它写进 OpenClaw 的config.toml或者直接导出成环境变量给 Skill 用。我试过两种放法。第一种是放在 OpenClaw 的全局配置里所有 Skill 共享第二种是 Skill 自己的.env适合做隔离测试。推荐第一种因为 Skill 多了以后统一管理更省心。# ~/.openclaw/config.toml [gateway] host 127.0.0.1 port 18789 [llm] provider taotoken base_url https://taotoken.net/api api_key sk-你的TaoTokenKey default_model claude-sonnet-4-20250514 [skills] root ~/.openclaw/skills auto_load true这里base_url不要带 UTM 参数API 调用只认https://taotoken.net/api。api_key建议用环境变量注入比如api_key ${TAOTOKEN_API_KEY}避免明文进 Git。注意TaoToken 是统一的模型 API 通道不是让你绕过任何网络限制的工具。它的作用是让你在一个 Key 下切换不同模型Skill 里只关心base_url和api_key两个字段。Key 创建入口在控制台的 API Keys 页面模型对话调试可以用模型对话页长期跑编码类 Skill 建议看 Coding Plan。这些入口后面 CTA 会再给一次。3. 路径一TypeScript Skill 从 plugin.json 到 index.ts先走 TypeScript 这条路。我拿一个真实需求做例子统计指定目录下的文件类型和数量生成 Markdown 报表。这个 Skill 会用到文件读写权限正好演示权限声明。3.1 初始化项目与依赖mkdir -p ~/.openclaw/skills/file-report-skill cd ~/.openclaw/skills/file-report-skill npm init -y npm install typescript types/node --save-dev npx tsc --init --target ES2020 --module CommonJS --outDir dist --rootDir src目录结构最后长这样file-report-skill/ ├── plugin.json ├── src/ │ └── index.ts ├── dist/ │ └── index.js ├── package.json └── tsconfig.json3.2 plugin.jsonSkill 的身份证plugin.json告诉内核这个 Skill 叫什么、能执行哪些 action、需要什么权限。参数类型目前支持string、number、boolean。{ name: file-report-skill, version: 1.0.0, description: 统计指定目录的文件类型和数量生成 Markdown 报表, author: your-name, entry: dist/index.js, skills: [ { action: generate-file-report, description: 统计目录文件并生成 Markdown 报表, parameters: [ { name: dirPath, type: string, required: true, description: 要统计的目录绝对路径 }, { name: outputPath, type: string, required: false, default: ./file-report.md, description: 报表保存路径 } ], permissions: [file.read, file.write] } ] }权限只申请file.read和file.write不要图省事写*。OpenClaw 在加载时会校验权限最小权限原则能避免 Skill 被误用。3.3 index.ts核心逻辑与 TaoToken 调用核心逻辑分三块扫描目录、生成 Markdown、可选地让模型写一句总结。第三块走 TaoToken。import fs from fs; import path from path; interface SkillResult { success: boolean; message: string; data: any; } function countFilesByType(dirPath: string): Recordstring, number { if (!fs.existsSync(dirPath)) { throw new Error(目录不存在${dirPath}); } const stats: Recordstring, number {}; const entries fs.readdirSync(dirPath, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory()) continue; const ext path.extname(entry.name).toLowerCase() || 无扩展名; stats[ext] (stats[ext] || 0) 1; } return stats; } function generateMarkdown(stats: Recordstring, number, dirPath: string): string { const lines [# 文件统计报表, , 目录\${dirPath}\, , | 类型 | 数量 |, | --- | --- |]; for (const [ext, count] of Object.entries(stats)) { lines.push(| ${ext} | ${count} |); } return lines.join(\n); } async function summarizeWithTaoToken(markdown: string): Promisestring { const baseUrl process.env.TAOTOKEN_BASE_URL || https://taotoken.net/api; const apiKey process.env.TAOTOKEN_API_KEY; if (!apiKey) return ; const resp await fetch(${baseUrl}/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${apiKey} }, body: JSON.stringify({ model: process.env.TAOTOKEN_MODEL || claude-sonnet-4-20250514, messages: [ { role: user, content: 用一句话总结这份文件统计\n${markdown} } ], max_tokens: 120 }) }); if (!resp.ok) return ; const json await resp.json(); return json.choices?.[0]?.message?.content?.trim() || ; } export default async function run(action: string, params: any): PromiseSkillResult { try { if (action ! generate-file-report) { return { success: false, message: 不支持的动作${action}, data: null }; } const { dirPath, outputPath ./file-report.md } params; const stats countFilesByType(dirPath); let markdown generateMarkdown(stats, dirPath); const summary await summarizeWithTaoToken(markdown); if (summary) { markdown \n\n 模型总结${summary}\n; } const fullPath path.isAbsolute(outputPath) ? outputPath : path.join(process.cwd(), outputPath); fs.writeFileSync(fullPath, markdown, utf8); return { success: true, message: 文件统计报表已生成, data: { stats, reportPath: fullPath, summary } }; } catch (error) { return { success: false, message: 执行失败${(error as Error).message}, data: null }; } }编译一下npx tscdist/index.js生成后OpenClaw 加载时读的就是这个入口。4. 路径二SKILL.md Shell 脚本抓 RSSShell 这条路更适合快速封装已有脚本。我拿 RSS 抓取做例子功能是从指定 RSS 源抓最新标题并可选地让模型翻译成中文摘要。4.1 目录结构与 SKILL.md 骨架cd ~/.openclaw/skills mkdir -p rss-fetch/{scripts,assets} cd rss-fetchSKILL.md用 YAML front matter 写元信息正文写使用说明。这个文件既是配置也是文档OpenClaw 会解析 front matter 来注册 Skill。--- name: rss-fetch description: 抓取 RSS 源最新标题支持自定义条数和模型摘要 author: your-name version: 1.0.0 entry: scripts/main.sh parameters: - name: rssUrl type: string required: true description: 合法的 RSS 源地址 - name: limit type: number required: false default: 5 description: 抓取条数最大 20 permissions: - network.http --- # rss-fetch ## 功能说明 轻量级 RSS 资讯抓取工具通过 RSS 地址快速获取资讯标题可选调用模型生成中文摘要。 ## 使用方法 openclaw rss-fetch [RSS_URL] [LIMIT5] - 必选参数RSS_URL - 可选参数LIMIT默认 5最大 20 示例 openclaw rss-fetch https://blog.example.com/rss 104.2 scripts/main.sh抓取与模型摘要脚本接收两个位置参数先做参数校验再用curl抓取用xmllint解析标题。最后如果环境变量里有 TaoToken Key就调一次模型做摘要。#!/bin/bash set -euo pipefail RSS_URL${1:-} LIMIT${2:-5} MAX_LIMIT20 TIMEOUT30 if [ -z $RSS_URL ]; then echo 错误请输入 RSS 地址 exit 1 fi if [ $LIMIT -gt $MAX_LIMIT ]; then LIMIT$MAX_LIMIT fi RAW$(curl -s --connect-timeout $TIMEOUT $RSS_URL) if [ -z $RAW ]; then echo 错误抓取失败请检查 RSS 地址或网络 exit 1 fi TITLES$(echo $RAW \ | xmllint --format - 2/dev/null \ | grep -oP (?title)[^] \ | tail -n 2 \ | head -n $LIMIT) echo 抓取到 $LIMIT 条标题 echo $TITLES if [ -n ${TAOTOKEN_API_KEY:-} ]; then BASE_URL${TAOTOKEN_BASE_URL:-https://taotoken.net/api} MODEL${TAOTOKEN_MODEL:-claude-sonnet-4-20250514} PROMPT用中文一句话总结这些资讯标题\n$TITLES SUMMARY$(curl -s --connect-timeout $TIMEOUT \ -X POST $BASE_URL/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d {\model\:\$MODEL\,\messages\:[{\role\:\user\,\content\:\$PROMPT\}],\max_tokens\:150} \ | grep -oP (?content:)[^] | head -n 1) if [ -n $SUMMARY ]; then echo echo 模型摘要$SUMMARY fi fi给脚本加执行权限chmod x scripts/main.sh注意grep -oP依赖 PCREmacOS 自带 grep 可能不支持可以brew install grep后用ggrep或者换成sed。这是我在 macOS 上踩过的坑。5. 本地加载与调用验证Skill 写完了得让 OpenClaw 认出来。两种路径的加载方式略有不同。TypeScript Skill 需要确认plugin.json里的entry指向编译后的dist/index.js然后重启网关openclaw gateway restart openclaw skill list你应该能在列表里看到file-report-skill和rss-fetch。如果没出现检查config.toml里的skills.root是否指向~/.openclaw/skills以及auto_load是否为true。调用 TypeScript Skillopenclaw skill run file-report-skill generate-file-report \ --params {dirPath:/Users/me/Documents,outputPath:./report.md}返回结果里会有success: true和reportPath。打开report.md如果配了 TaoToken Key末尾会多一行模型总结。调用 Shell Skillopenclaw skill run rss-fetch --params {rssUrl:https://blog.example.com/rss,limit:3}或者用 CLI 的测试模式openclaw skill test rss-fetch --params https://blog.example.com/rss 3成功的话终端会打印标题列表有 Key 的情况下还会打印中文摘要。这一步验证通过说明 Skill 已经能被内核正常调度。6. 本篇常见错排查报错一Skill not found。九成是SKILL.md的 front matter 格式不对比如---没顶格、YAML 缩进用了 Tab。YAML 只认空格。另外name字段必须和目录名一致否则注册会失败。报错二Permission denied: file.write。检查plugin.json或SKILL.md里的permissions是否声明了对应权限。OpenClaw 默认拒绝未声明的权限这是安全设计不是 bug。报错三TaoToken 返回 401。先确认TAOTOKEN_API_KEY环境变量在当前 shell 里能echo出来。如果是在config.toml里写的注意不要带引号以外的空格。API 地址必须是https://taotoken.net/api不要拼成带 UTM 的官网地址。报错四Shell 脚本xmllint: command not found。Ubuntu 下apt install libxml2-utilsmacOS 自带。如果 RSS 源返回的是 JSON 而不是 XMLxmllint会解析失败需要换jq。报错五TypeScript 编译后dist/index.js找不到。检查tsconfig.json的rootDir和outDir以及plugin.json的entry路径是否相对于 Skill 根目录。我习惯在package.json里加一个build: tsc每次改完先 build 再 restart。报错六模型摘要为空。先看curl是否返回了choices字段。如果返回的是错误 JSON可能是模型名写错。TaoToken 的模型名以控制台展示为准不要凭记忆写。7. 下一步把 Skill 接进你的日常工作流两条路径走通之后你会发现 OpenClaw 的 Skill 体系其实很轻。TypeScript 适合做需要类型约束和复杂状态处理的 Skill比如文件报表、接口聚合Shell 适合做胶水层把已有的命令行工具包一层就能用。两者可以混用同一个skills目录下放不同类型的 Skill内核都能加载。如果你打算长期跑编码类或 Agent 类 Skill建议把 TaoToken 的 Key 统一放在config.toml的[llm]段Skill 里只读环境变量。这样换模型、换 Key 都不用改 Skill 代码。Key 在控制台的 API Keys 页面创建接入细节看接入文档模型调试用模型对话页长期编码任务可以了解 Coding Plan。我自己的习惯是每写一个新 Skill先在openclaw skill test里跑通最小用例再挂到网关自动加载。这样出问题的时候能快速判断是 Skill 逻辑问题还是内核调度问题。
返回列表