插件开发

OpenClaw的插件系统允许开发者通过标准化的接口扩展平台功能,而无需修改核心代码。插件可以添加新的工具、数据源连接器、通知渠道、Agent行为策略等。本章将介绍插件架构、生命周期管理,并通过实际示例引导您编写第一个OpenClaw插件。

插件架构

OpenClaw插件采用模块化架构,每个插件是一个独立的Python包,遵循标准的插件接口规范。插件通过钩子(hooks)机制与平台核心交互,可以在Agent执行的各个阶段注入自定义逻辑。

插件系统的核心设计原则:

  • 隔离性:每个插件运行在独立的沙箱中,插件之间的故障不会相互影响
  • 声明式注册:通过配置文件声明插件提供的功能,平台自动完成注册和路由
  • 版本兼容:插件声明兼容的OpenClaw版本范围,平台自动检查兼容性
  • 热加载:支持在不重启服务的情况下安装、卸载和更新插件

一个标准的OpenClaw插件包含以下文件结构:

openclaw-my-plugin/
├── pyproject.toml          # 项目元数据和依赖
├── openclaw_plugin.yaml    # 插件声明文件
├── src/
│   └── openclaw_my_plugin/
│       ├── __init__.py     # 插件入口
│       ├── plugin.py       # 插件主类
│       ├── hooks.py        # 钩子实现
│       └── tools/          # 插件提供的工具
│           └── my_tool.py
├── tests/
│   └── test_plugin.py
└── README.md

插件生命周期

每个OpenClaw插件都遵循标准的生命周期管理。理解生命周期对于编写可靠的插件至关重要:

  1. 发现(Discovery):平台扫描已安装的插件包,读取 openclaw_plugin.yaml 声明文件
  2. 加载(Loading):平台导入插件模块,检查版本兼容性,初始化插件实例
  3. 配置(Configuration):平台将用户配置传递给插件,插件完成内部初始化
  4. 激活(Activation):插件注册钩子和工具,开始接收事件
  5. 运行(Running):插件正常处理事件和请求
  6. 停用(Deactivation):插件清理资源,注销钩子,保存状态
  7. 卸载(Unloading):插件从内存中移除

编写第一个插件

下面我们通过一个实际示例来编写一个完整的OpenClaw插件。这个插件将添加一个"翻译工具",让Agent可以将文本翻译成多种语言。

首先,创建插件声明文件 openclaw_plugin.yaml:

# openclaw_plugin.yaml
name: openclaw-translator
version: 1.0.0
description: "多语言翻译工具插件"
author: "Your Name"
license: MIT

# 兼容的OpenClaw版本
compatibility:
  openclaw_version: ">=1.0.0,<2.0.0"

# 插件提供的功能
provides:
  tools:
    - name: translate
      description: "将文本翻译成目标语言"
      handler: openclaw_my_plugin.tools.translator:TranslateTool
  hooks:
    - event: agent.before_execute
      handler: openclaw_my_plugin.hooks:before_agent_execute
    - event: agent.after_execute
      handler: openclaw_my_plugin.hooks:after_agent_execute

# 插件配置Schema
config_schema:
  type: object
  properties:
    default_target_language:
      type: string
      default: "en"
      description: "默认目标语言"
    supported_languages:
      type: array
      items:
        type: string
      default: ["en", "zh", "ja", "ko", "fr", "de", "es"]
    api_provider:
      type: string
      enum: ["openai", "google", "deepl"]
      default: "openai"

接下来,实现插件主类和翻译工具:

# src/openclaw_my_plugin/plugin.py
from openclaw.plugins import PluginBase

class TranslatorPlugin(PluginBase):
    name = "openclaw-translator"
    version = "1.0.0"

    async def on_load(self, config):
        """插件加载时的初始化"""
        self.default_language = config.get(
            "default_target_language", "en"
        )
        self.supported_languages = config.get(
            "supported_languages",
            ["en", "zh", "ja", "ko", "fr", "de", "es"]
        )
        self.api_provider = config.get("api_provider", "openai")
        self.logger.info(
            f"翻译插件已加载,支持语言: {self.supported_languages}"
        )

    async def on_activate(self):
        """插件激活"""
        self.logger.info("翻译插件已激活")

    async def on_deactivate(self):
        """插件停用时清理资源"""
        self.logger.info("翻译插件已停用")


# src/openclaw_my_plugin/tools/translator.py
from openclaw.tools import ToolBase
from openclaw.tools.schema import ToolParameter

class TranslateTool(ToolBase):
    name = "translate"
    description = "将文本翻译成指定的目标语言"

    parameters = [
        ToolParameter(
            name="text",
            type="string",
            description="需要翻译的文本",
            required=True
        ),
        ToolParameter(
            name="target_language",
            type="string",
            description="目标语言代码(如 en, zh, ja)",
            required=False,
            default="en"
        )
    ]

    async def execute(self, text: str,
                      target_language: str = "en") -> dict:
        """执行翻译"""
        model = self.get_model("openai/gpt-4o-mini")
        prompt = f"Translate the following text to {target_language}:\n\n{text}"

        response = await model.generate(
            prompt=prompt,
            max_tokens=2000,
            temperature=0.3
        )

        return {
            "original": text,
            "translated": response.text,
            "target_language": target_language,
            "provider": self.plugin.api_provider
        }

提示:插件测试

OpenClaw提供了插件测试框架,可以在隔离环境中测试插件功能。运行 openclaw plugin test --path ./openclaw-my-plugin 可以执行插件的自动化测试。测试框架会模拟Agent运行环境,验证钩子和工具的正确性。

钩子系统

钩子(hooks)是插件与平台核心交互的主要机制。OpenClaw在Agent执行的各个阶段提供了丰富的钩子点:

# src/openclaw_my_plugin/hooks.py
from openclaw.plugins.hooks import HookContext

async def before_agent_execute(ctx: HookContext):
    """Agent执行前的钩子"""
    agent = ctx.agent
    agent.logger.info(f"Agent {agent.name} 即将执行任务")

    # 可以修改Agent的上下文
    ctx.metadata["plugin_start_time"] = ctx.timestamp

    # 可以注入额外的系统提示
    ctx.add_system_prompt(
        "如果用户请求翻译,请使用translate工具。"
    )

async def after_agent_execute(ctx: HookContext):
    """Agent执行后的钩子"""
    duration = ctx.timestamp - ctx.metadata["plugin_start_time"]
    ctx.agent.logger.info(
        f"Agent执行完成,耗时: {duration:.2f}秒"
    )

    # 可以记录自定义指标
    ctx.metrics.record("plugin.translation.duration", duration)

# 可用的钩子事件列表:
# agent.before_execute    - Agent开始执行前
# agent.after_execute     - Agent执行完成后
# agent.on_error          - Agent执行出错时
# tool.before_call        - 工具调用前
# tool.after_call         - 工具调用后
# model.before_request    - 模型请求发送前
# model.after_response    - 模型响应接收后
# message.received        - 收到用户消息时
# message.sent            - 发送回复消息时

发布到插件仓库

完成插件开发后,您可以将其发布到OpenClaw插件仓库,让其他用户安装和使用。发布流程如下:

# 1. 构建插件包
cd openclaw-my-plugin
python -m build

# 2. 验证插件包
openclaw plugin validate ./dist/openclaw_translator-1.0.0.tar.gz

# 3. 注册插件仓库账号(首次发布)
openclaw plugin registry login

# 4. 发布插件
openclaw plugin publish ./dist/openclaw_translator-1.0.0.tar.gz

# 5. 发布后,其他用户可以通过以下命令安装
# openclaw plugin install openclaw-translator

核心概念:插件审核

发布到官方插件仓库的插件需要通过自动审核流程,包括安全扫描、代码质量检查和兼容性测试。审核通常在24小时内完成。您也可以搭建私有插件仓库,供团队内部使用,私有仓库无需审核。

通过OpenClaw的插件系统,您可以灵活地扩展平台功能,将自定义的工具、数据源和Agent行为策略集成到平台中。插件架构的设计确保了扩展性与稳定性的平衡,让社区开发者能够为OpenClaw生态系统贡献价值。