OpenClaw Plugin SDK 开发指南
从零到一,打造你的专属 OpenClaw 插件 —— 让 AI 拥有超能力
🎯 为什么要用 Plugin SDK?
世界上有一种能力,叫「扩展」。OpenClaw 再强大,如果没有插件生态,也只是个「单机版」AI助手。
"凌晨3点,我想让AI帮我自动发邮件。发现没有现成工具。那一刻我知道,需要学会写插件。"
Plugin SDK 让你能够:
- 🔌 扩展AI能力 - 添加自定义工具、集成外部服务
- 📦 复用和分享 - 发布到 ClawHub,让全球用户使用
- 🛡️ 安全隔离 - 插件沙箱机制,避免影响核心系统
- 🚀 快速开发 - TypeScript/JavaScript 支持,热重载开发
- 🎨 灵活架构 - 支持多种插件类型(channel、provider、tool等)
🚀 快速开始
环境准备
# 安装 OpenClaw(如果还没装)
npm install -g openclaw
# 验证安装
openclaw --version
# 创建插件开发目录
mkdir my-openclaw-plugin
cd my-openclaw-plugin
初始化插件项目
# 使用 OpenClaw CLI 初始化插件
openclaw plugins init my-first-plugin
# 或者手动创建 package.json
{
"name": "@yourname/openclaw-plugin-hello",
"version": "1.0.0",
"description": "My first OpenClaw plugin",
"main": "dist/index.js",
"openclaw": {
"plugin": true,
"type": "tool-provider"
},
"dependencies": {
"@openclaw/plugin-sdk": "^2026.5.0"
}
}
编写第一个插件
// src/index.ts
import { Plugin, Tool } from '@openclaw/plugin-sdk';
export interface HelloPluginConfig {
greeting?: string;
}
export class HelloPlugin implements Plugin {
name = 'hello-plugin';
version = '1.0.0';
private config: HelloPluginConfig;
constructor(config: HelloPluginConfig = {}) {
this.config = {
greeting: 'Hello from OpenClaw!',
...config
};
}
async getTools(): Promise<Tool[]> {
return [
{
name: 'say_hello',
description: 'Say hello with a customizable greeting',
parameters: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Name to greet'
}
},
required: ['name']
},
execute: async (params) => {
return `${this.config.greeting} ${params.name}`;
}
}
];
}
}
// 插件入口
export default function createPlugin(config?: HelloPluginConfig) {
return new HelloPlugin(config);
}
💻 核心概念
1. 插件类型
| 类型 | 说明 | 示例 |
|---|---|---|
| tool-provider | 提供自定义工具 | 天气查询、数据库操作 |
| channel | 消息通道集成 | Slack、Discord、WhatsApp |
| provider | LLM/服务供应商 | 自定义AI模型接入 |
| source-provider | 数据源集成 | 会议记录、日志采集 |
| ui-plugin | UI扩展 | 自定义控制面板组件 |
2. 插件生命周期
class MyPlugin implements Plugin {
name = 'my-plugin';
// 1. 初始化 - 插件加载时调用
async init(context: PluginContext): Promise<void> {
console.log('Plugin initialized');
// 可以访问配置、注册事件监听器等
}
// 2. 启动 - Gateway启动时调用
async start(): Promise<void> {
console.log('Plugin started');
// 启动后台任务、连接外部服务等
}
// 3. 停止 - Gateway停止时调用
async stop(): Promise<void> {
console.log('Plugin stopped');
// 清理资源、断开连接等
}
// 4. 获取工具(tool-provider类型)
async getTools(): Promise<Tool[]> {
return [/* your tools */];
}
}
3. 工具定义最佳实践
// 好的工具定义
const goodTool: Tool = {
name: 'search_documents',
description: 'Search documents in the knowledge base with full-text search',
parameters: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Search query (supports full-text search)'
},
limit: {
type: 'number',
description: 'Maximum number of results (1-100)',
minimum: 1,
maximum: 100,
default: 10
},
filters: {
type: 'object',
description: 'Optional filters (date range, tags, etc.)',
properties: {
startDate: { type: 'string', format: 'date' },
endDate: { type: 'string', format: 'date' },
tags: { type: 'array', items: { type: 'string' } }
}
}
},
required: ['query']
},
execute: async (params) => {
// 实现逻辑
const results = await searchDocs(params.query, {
limit: params.limit || 10,
filters: params.filters
});
return { results, total: results.length };
}
};
📦 发布到 ClawHub
1. 准备发布
# 构建插件
npm run build
# 检查插件清单
openclaw plugins validate
# 登录 ClawHub(如果需要)
openclaw hub login
2. 发布插件
# 发布到 ClawHub
openclaw hub publish
# 指定版本发布
openclaw hub publish --version 1.0.1
# 发布到私有 registry
openclaw hub publish --registry https://my-registry.com
3. 插件元数据(package.json 扩展)
{
"name": "@yourname/openclaw-plugin-xxx",
"version": "1.0.0",
"openclaw": {
"plugin": true,
"type": "tool-provider",
"displayName": "My Awesome Plugin",
"description": "Detailed description for ClawHub",
"icon": "icon.png",
"tags": ["productivity", "search", "ai"],
"requires": {
"openclaw": ">=2026.5.0"
},
"permissions": ["network", "file-read"],
"homepage": "https://github.com/yourname/openclaw-plugin-xxx",
"repository": "github:yourname/openclaw-plugin-xxx"
}
}
🔧 实战示例:天气查询插件
完整实现
// src/weather-plugin.ts
import { Plugin, Tool, PluginContext } from '@openclaw/plugin-sdk';
interface WeatherPluginConfig {
apiKey?: string;
units?: 'metric' | 'imperial';
}
export class WeatherPlugin implements Plugin {
name = 'weather';
version = '1.0.0';
private config: WeatherPluginConfig;
private context!: PluginContext;
constructor(config: WeatherPluginConfig = {}) {
this.config = {
units: 'metric',
...config
};
}
async init(context: PluginContext): Promise<void> {
this.context = context;
// 从配置或环境变量获取API key
if (!this.config.apiKey) {
this.config.apiKey = await context.getSecret('WEATHER_API_KEY');
}
if (!this.config.apiKey) {
throw new Error('Weather API key not configured');
}
}
async getTools(): Promise<Tool[]> {
return [
{
name: 'get_weather',
description: 'Get current weather for a city',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: 'City name (e.g., "Beijing", "New York")'
},
country: {
type: 'string',
description: 'Country code (optional, e.g., "CN", "US")'
}
},
required: ['city']
},
execute: async (params) => {
const response = await fetch(
`https://api.weatherapi.com/v1/current.json?` +
`key=${this.config.apiKey}&` +
`q=${params.city}${params.country ? ',' + params.country : ''}&` +
`units=${this.config.units}`
);
if (!response.ok) {
throw new Error(`Weather API error: ${response.statusText}`);
}
const data = await response.json();
return {
city: data.location.name,
country: data.location.country,
temperature: data.current.temp_c,
condition: data.current.condition.text,
humidity: data.current.humidity,
windSpeed: data.current.wind_kph
};
}
},
{
name: 'get_forecast',
description: 'Get weather forecast for a city',
parameters: {
type: 'object',
properties: {
city: { type: 'string', description: 'City name' },
days: {
type: 'number',
description: 'Number of days (1-7)',
minimum: 1,
maximum: 7,
default: 3
}
},
required: ['city']
},
execute: async (params) => {
// 实现预报逻辑
return { message: 'Forecast functionality coming soon!' };
}
}
];
}
}
export default function createPlugin(config?: WeatherPluginConfig) {
return new WeatherPlugin(config);
}
🎓 高级话题
1. 插件间通信
// 插件可以监听和发送事件
class MyPlugin implements Plugin {
async init(context: PluginContext) {
// 监听事件
context.events.on('user-message', (msg) => {
console.log('Received message:', msg);
});
// 发送事件
context.events.emit('my-plugin-event', { data: 'hello' });
}
}
2. 配置热重载
class MyPlugin implements Plugin {
async init(context: PluginContext) {
// 监听配置变更
context.onConfigChange((newConfig) => {
console.log('Config updated:', newConfig);
// 重新初始化或调整行为
});
}
}
3. 错误处理和日志
class MyPlugin implements Plugin {
private logger!: Logger;
async init(context: PluginContext) {
this.logger = context.logger.child({ plugin: this.name });
}
async getTools() {
return [
{
name: 'my_tool',
execute: async (params) => {
try {
this.logger.info('Executing my_tool', params);
// 工具逻辑
return { success: true };
} catch (error) {
this.logger.error('Tool execution failed', { error, params });
throw error; // 让 OpenClaw 处理错误
}
}
}
];
}
}
📚 相关资源
🎯 妙趣提示: 开发插件时,先用
openclaw plugins dev 启动开发模式,支持热重载,改代码不用重启Gateway!