OpenClaw 插件开发:创建自定义插件
OpenClaw 的插件系统让你可以扩展其功能,添加自定义工具、命令和渠道。本文将详细介绍如何开发 OpenClaw 插件。
插件概述
OpenClaw 插件是独立的 npm 包,可以:
- 注册工具:添加 AI Agent 可以调用的新工具
- 注册命令:添加自定义 CLI 命令
- 注册渠道:添加新的聊天平台支持
- 注册技能:添加自定义技能和提示词
插件开发环境
前置要求
- Node.js:22+
- TypeScript:推荐使用 TypeScript
- pnpm:推荐的包管理器
安装开发工具
# 安装 OpenClaw SDK
$ npm install @openclaw/sdk
# 或使用 pnpm
$ pnpm add @openclaw/sdk
创建插件项目
初始化项目
# 创建项目目录
$ mkdir my-openclaw-plugin
$ cd my-openclaw-plugin
# 初始化项目
$ pnpm init
# 安装依赖
$ pnpm add @openclaw/sdk
配置 TypeScript
创建 tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"declaration": true,
"outDir": "./dist",
"strict": true,
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
插件基础结构
创建 src/index.ts:
import { Plugin, PluginAPI } from '@openclaw/sdk';
export class MyPlugin implements Plugin {
name = 'my-plugin';
version = '1.0.0';
description = 'My custom OpenClaw plugin';
async onLoad(api: PluginAPI): Promise {
// 插件加载时执行
console.log(`${this.name} v${this.version} loaded`);
// 注册工具
api.registerTool({
name: 'my-tool',
description: 'My custom tool',
execute: async (params: any) => {
return { success: true, result: 'Hello from my tool!' };
}
});
// 注册命令
api.registerCommand({
name: 'hello',
description: 'Say hello',
handler: async () => {
console.log('Hello from my plugin!');
}
});
}
async onUnload(): Promise {
// 插件卸载时执行
console.log(`${this.name} unloaded`);
}
}
// 导出插件
export default new MyPlugin();
开发工具
注册工具
工具是 AI Agent 可以调用的函数:
api.registerTool({
name: 'calculator',
description: 'Perform mathematical calculations',
parameters: {
type: 'object',
properties: {
expression: {
type: 'string',
description: 'Mathematical expression to evaluate'
}
},
required: ['expression']
},
execute: async (params: { expression: string }) => {
try {
// 简单示例:使用 eval (生产环境应使用更安全的解析器)
const result = eval(params.expression);
return { success: true, result: String(result) };
} catch (error) {
return { success: false, error: (error as Error).message };
}
}
});
注册命令
命令是可以通过 CLI 执行的命令:
api.registerCommand({
name: 'status',
description: 'Show plugin status',
handler: async (args: string[]) => {
console.log('Plugin Status: Running');
console.log(`Version: ${this.version}`);
}
});
注册渠道
添加新的聊天平台支持:
api.registerChannel({
name: 'custom-platform',
description: 'Custom chat platform',
connect: async (config: any) => {
// 连接到平台
console.log('Connected to custom platform');
},
disconnect: async () => {
// 断开连接
console.log('Disconnected from custom platform');
},
sendMessage: async (channelId: string, message: string) => {
// 发送消息
console.log(`Sending to ${channelId}: ${message}`);
}
});
示例插件
天气插件
创建一个获取天气信息的插件:
import { Plugin, PluginAPI } from '@openclaw/sdk';
export class WeatherPlugin implements Plugin {
name = 'weather-plugin';
version = '1.0.0';
async onLoad(api: PluginAPI): Promise {
api.registerTool({
name: 'get_weather',
description: 'Get weather information for a city',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: 'City name'
}
},
required: ['city']
},
execute: async (params: { city: string }) => {
// 调用天气 API(示例)
const weather = await this.fetchWeather(params.city);
return { success: true, result: weather };
}
});
}
async onUnload(): Promise {
console.log('Weather plugin unloaded');
}
private async fetchWeather(city: string): Promise {
// 这里应该调用真实的天气 API
// 示例返回
return `Weather in ${city}: 25°C, Sunny`;
}
}
export default new WeatherPlugin();
时间插件
创建一个获取时间的插件:
import { Plugin, PluginAPI } from '@openclaw/sdk';
export class TimePlugin implements Plugin {
name = 'time-plugin';
version = '1.0.0';
async onLoad(api: PluginAPI): Promise {
api.registerTool({
name: 'get_time',
description: 'Get current time in a timezone',
parameters: {
type: 'object',
properties: {
timezone: {
type: 'string',
description: 'Timezone (e.g., Asia/Shanghai)',
default: 'UTC'
}
}
},
execute: async (params: { timezone: string }) => {
const time = new Date().toLocaleString('zh-CN', {
timeZone: params.timezone
});
return { success: true, result: time };
}
});
}
async onUnload(): Promise {
console.log('Time plugin unloaded');
}
}
export default new TimePlugin();
构建和发布
构建插件
# 编译 TypeScript
$ pnpm build
更新 package.json:
{
"name": "my-openclaw-plugin",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"dev": "tsc --watch"
}
}
本地安装
# 在插件目录安装
$ pnpm link
# 在 OpenClaw 目录链接
$ pnpm link my-openclaw-plugin
发布到 npm
# 发布
$ pnpm publish
安装和使用插件
从 npm 安装
$ pnpm add -g my-openclaw-plugin
配置插件
在 openclaw.json 中配置:
{
"plugins": {
"my-plugin": {
"enabled": true,
"config": {
"apiKey": "your-api-key"
}
}
}
}
测试插件
单元测试
使用 Jest 进行测试:
$ pnpm add -D jest @types/jest
创建测试文件 src/__tests__/index.test.ts:
import { PluginAPI } from '@openclaw/sdk';
import { MyPlugin } from '../index';
describe('MyPlugin', () => {
let plugin: MyPlugin;
let mockApi: jest.Mocked;
beforeEach(() => {
plugin = new MyPlugin();
mockApi = {
registerTool: jest.fn(),
registerCommand: jest.fn(),
registerChannel: jest.fn()
} as any;
});
it('should load successfully', async () => {
await plugin.onLoad(mockApi);
expect(mockApi.registerTool).toHaveBeenCalled();
});
it('should register tool', async () => {
await plugin.onLoad(mockApi);
expect(mockApi.registerTool).toHaveBeenCalledWith(
expect.objectContaining({
name: 'my-tool'
})
);
});
});
最佳实践
错误处理
execute: async (params) => {
try {
// 工具逻辑
return { success: true, result: data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
类型安全
interface ToolParams {
city: string;
units?: 'metric' | 'imperial';
}
execute: async (params: ToolParams) => {
const city = params.city;
const units = params.units || 'metric';
// ...
}
日志记录
api.logger.info('Tool executed', { tool: 'my-tool' });
api.logger.error('Tool failed', { error: error.message });
总结
OpenClaw 插件系统提供了强大的扩展能力。通过创建自定义插件,你可以添加任何你需要的功能,让 AI 助手更符合你的需求。
相关资源
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。







