OpenClaw Plugin SDK 开发指南

从零到一,打造你的专属 OpenClaw 插件 —— 让 AI 拥有超能力

📅 更新于 2026年5月25日 ⏱️ 阅读时间:20分钟 🏷️ Plugin SDK, 插件开发, ClawHub

🎯 为什么要用 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!