第八章:技能开发与技能包
技能包结构说明
技能包(Skill Pack)是 OpenClaw 中功能封装和分发的基本单元。一个完整的技能包包含三个核心组成部分:清单文件(manifest)、代码文件和资源文件。技能包的设计遵循即插即用的理念,开发者可以像安装手机应用一样安装和启用技能。
标准技能包的目录结构如下:
my-skill/
├── manifest.json # 技能清单
├── index.ts # 入口文件
├── handlers/ # 消息处理器
│ ├── message.ts
│ └── command.ts
├── tools/ # 工具定义
│ └── custom-tool.ts
├── prompts/ # 提示词模板
│ └── system.md
├── assets/ # 静态资源
│ ├── icon.png
│ └── examples.json
├── config.ts # 技能配置
└── README.md # 使用说明
Manifest 清单文件详解
{
"name": "weather-skill",
"version": "1.2.0",
"displayName": "天气查询技能",
"description": "提供实时天气查询和天气预报功能",
"author": "OpenClaw Team",
"license": "MIT",
"minAppVersion": "2.0.0",
"categories": ["utility", "weather"],
"permissions": [
"network:fetch",
"storage:session"
],
"configSchema": {
"type": "object",
"properties": {
"apiKey": {
"type": "string",
"description": "天气 API 密钥",
"secret": true
},
"defaultUnit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"default": "celsius"
}
},
"required": ["apiKey"]
},
"hooks": {
"onInstall": "scripts/install.ts",
"onUninstall": "scripts/uninstall.ts",
"onEnable": "scripts/enable.ts",
"onDisable": "scripts/disable.ts"
}
}
开发第一个技能
让我们从零开始创建一个简单的翻译技能。首先创建技能包目录和清单文件,然后实现核心逻辑:
// index.ts
import { defineSkill, SkillContext } from 'openclaw/skills';
export default defineSkill({
name: 'translator',
version: '1.0.0',
// 注册消息处理器
setup(ctx: SkillContext) {
// 注册斜杠命令
ctx.registerCommand({
name: 'translate',
handler: async (params) => {
const { text, target } = params;
const apiKey = ctx.config.apiKey;
const result = await translateText(text, target, apiKey);
return \`翻译结果:${result}\`;
},
});
// 注册消息中间件
ctx.on('message', async (message) => {
// 自动检测并翻译非中文消息
if (message.text && !isChinese(message.text)) {
const translated = await translateText(message.text, 'zh', ctx.config.apiKey);
ctx.reply(`原文:${message.text}\n中文:${translated}`);
}
});
// 注册工具
ctx.registerTool({
name: 'translate_text',
description: '将文本翻译成指定语言',
parameters: {
text: { type: 'string', description: '待翻译文本' },
target: { type: 'string', description: '目标语言代码' },
},
execute: async (args) => {
return translateText(args.text, args.target, ctx.config.apiKey);
},
});
},
});
async function translateText(text: string, target: string, apiKey: string) {
const response = await fetch('https://api.example.com/translate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
},
body: JSON.stringify({ q: text, target, source: 'auto' }),
});
const data = await response.json();
return data.translatedText;
}
function isChinese(text: string): boolean {
return /[\u4e00-\u9fff]/.test(text);
}
技能生命周期管理
OpenClaw 的技能系统提供了完整的生命周期管理接口,确保技能在安装、启用、禁用和卸载各阶段的资源得到妥善管理。
# 安装技能
openclaw skill install ./path/to/my-skill
# 或从远程仓库安装
openclaw skill install weather-skill@latest
# 启用/禁用技能
openclaw skill enable translator
openclaw skill disable translator
# 查看已安装技能列表
openclaw skill list
# 卸载技能
openclaw skill uninstall translator
在 manifest.json 的 hooks 字段中配置各个生命周期回调脚本,框架会在对应时机自动执行:
| 生命周期阶段 | 触发时机 | 典型用途 |
|---|---|---|
| onInstall | 技能安装后 | 创建数据库表、注册 API 路由 |
| onEnable | 技能启用时 | 连接外部服务、初始化缓存 |
| onDisable | 技能禁用时 | 断开连接、持久化状态 |
| onUninstall | 技能卸载前 | 清理数据、释放资源 |
技能配置参数说明
技能的配置参数通过在 manifest.json 的 configSchema 字段中定义,支持设置默认值和标记敏感字段。用户在安装或使用时可以通过 UI 或 CLI 修改配置:
# 查看技能配置
openclaw skill config translator
# 修改技能配置
openclaw skill config translator --set apiKey=xxx --set defaultUnit=celsius
标记为 secret: true 的字段在存储和日志中会自动脱敏,防止 API Key 等敏感信息泄露。
发布技能到 ClawdHub
完成开发后,可以将技能发布到官方的 ClawdHub 市场,供其他用户安装使用:
# 打包技能
openclaw skill pack ./my-skill -o ./dist/my-skill-1.0.0.osk
# 发布到 ClawdHub(需要账号登录)
openclaw hub login
openclaw hub publish ./dist/my-skill-1.0.0.osk
发布时系统会自动验证清单文件的完整性和权限声明的合理性。审核通过后,技能将在 ClawdHub 市场上架,用户可以通过 openclaw skill install 命令搜索和安装。
对比表:内置技能 vs 自定义技能
| 对比维度 | 内置技能 | 自定义技能 |
|---|---|---|
| 开发成本 | 零开发,开箱即用 | 需要编写代码和配置 |
| 定制程度 | 固定功能,不支持修改 | 完全可控,满足特定需求 |
| 维护责任 | 框架作者负责维护 | 开发者自行维护 |
| 发布范围 | 随框架版本发布 | 可发布到 ClawdHub 或私有仓库 |
| 更新频率 | 随框架更新 | 独立版本管理,随时发布 |
| 性能表现 | 经过优化,性能稳定 | 取决于代码质量 |
| 社区支持 | 官方文档和 Issue 支持 | 由开发者提供支持 |
选择内置技能还是自定义技能,取决于你的实际需求。内置技能适合通用场景,而自定义技能则能解决特定领域的复杂问题。一般建议优先使用内置技能,当功能不满足时再考虑自定义开发。