OpenClaw 的插件系统允许在 gateway 进程中挂载自定义逻辑,与 AI agent 共享运行时。插件可以做很多事情:监听 agent 事件、提供自定义 tool、定时任务,或者像我们这次一样——跑一个独立的同步守护进程。

这篇记录从零创建一个插件、验证、发布到 ClawHub,再到远程节点安装的全过程。

背景 链接到标题

OpenClaw 插件和 Skill 的区别:Skill 是一组 instructions 文件,通过注入到 agent prompt 来改变行为;插件则是编译后的 JavaScript 代码,运行在 gateway 进程内,能调用 SDK 提供的 API(config、storage、http 等)。两者互补,技能负责"教 agent 怎么做",插件负责"替 agent 做"。

环境要求 链接到标题

  • Node.js ≥ 22.19(OpenClaw 的要求)
  • TypeScript + ESM 模块
  • clawhub CLI — 用于验证和发布
  • 一个 GitHub 仓库(公开或私有均可)

安装 clawhub CLI:

npm install -g @openclaw/clawhub

创建插件项目 链接到标题

推荐项目结构:

my-plugin/
├── src/
│   ├── index.ts          # 插件入口
│   └── lib.ts            # 核心逻辑
├── openclaw.plugin.json  # 插件清单
├── tsconfig.json
└── package.json

包元数据 链接到标题

package.json 中的 openclaw 块定义了入口文件、兼容性和构建信息,是 gateway 加载和 ClawHub 发布的依据:

{
  "name": "@myorg/openclaw-my-plugin",
  "version": "1.0.0",
  "type": "module",
  "openclaw": {
    "extensions": ["./dist/index.js"],
    "compat": {
      "pluginApi": ">=2026.6.5",
      "minGatewayVersion": ">=2026.6.5"
    },
    "build": {
      "openclawVersion": "2026.6.5",
      "pluginSdkVersion": "2026.6.5"
    }
  },
  "dependencies": {
    "typebox": "^1.1.38"
  }
}
字段 说明
openclaw.extensions 编译后的 JS 入口文件路径
openclaw.compat 兼容性声明,ClawHub 据此判断插件适用的 gateway 版本
openclaw.build 构建时使用的 SDK 版本,用于发布元数据

入口文件必须指向编译后的 JS(如 ./dist/index.js),而非 TS 源码。ClawHub 发布的插件需要 compatbuild 字段。

插件清单 链接到标题

openclaw.plugin.json 是 gateway 在加载插件代码前读取的元数据,用于配置验证和能力发现:

{
  "id": "my-plugin",
  "name": "My Plugin",
  "description": "示例插件",
  "version": "0.1.0",
  "activation": {
    "onStartup": true
  },
  "contracts": {
    "tools": ["my_tool"]
  },
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "serverUrl": { "type": "string", "description": "服务地址" },
      "userName": { "type": "string", "description": "用户名" },
      "password": { "type": "string", "description": "密码" }
    }
  }
}

字段说明:

字段 说明
id 插件唯一标识,安装时使用
activation.onStartup 是否在 gateway 启动时自动加载
contracts.tools 插件提供的 tool 列表,供 agent 调用
configSchema 必需,JSON Schema 格式的配置校验规则,即使无配置也要写空对象

注意:入口文件路径不放在 openclaw.plugin.json 中,而是放在 package.json#openclaw.extensionsconfigSchema 是必需字段,缺少会导致 gateway 拒绝加载。

TypeScript 配置 链接到标题

ESM 模块编译配置,tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true
  },
  "include": ["src"]
}

SDK 入口与最小示例 链接到标题

插件入口使用 definePluginEntry 辅助函数:

import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";

export default definePluginEntry({
  id: "my-plugin",
  name: "My Plugin",
  description: "示例插件",
  register(api) {
    console.log("[my-plugin] Plugin started");

    // 读取插件自身配置(来自 openclaw.json plugins.entries.<id>.config)
    const cfg = api.pluginConfig;
    console.log("[my-plugin] Config:", JSON.stringify(cfg));

    // 你的逻辑...
  },
});

register(api) 是插件运行时入口,gateway 启动时调用。api 对象提供了访问 OpenClaw 配置、存储、HTTP 客户端等能力。

插件自身的配置通过 api.pluginConfig 直接获取,无需从 api.config 中手动取路径。

注册自定义 Tool 链接到标题

通过 api.registerTool 注册可供 agent 调用的 tool:

import { Type } from "typebox";
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";

export default definePluginEntry({
  id: "my-plugin",
  name: "My Plugin",
  description: "示例插件",
  register(api) {
    api.registerTool({
      name: "my_tool",
      description: "agent 可以调用的自定义功能",
      parameters: Type.Object({
        input: Type.String({ description: "输入参数" }),
      }),
      async execute(_id, params) {
        return {
          content: [{ type: "text", text: `处理成功: ${params.input}` }],
        };
      },
    });
  },
});

参数类型使用 typebox 定义,execute 返回 AgentToolResult 格式。Tool 名必须在 openclaw.plugin.json#contracts.tools 中声明。

插件配置 链接到标题

插件的配置通过 openclaw.json 注入,安装插件后在配置文件中添加:

{
  "plugins": {
    "allow": ["my-plugin"],
    "entries": {
      "my-plugin": {
        "enabled": true,
        "config": {
          "serverUrl": "http://内网地址:端口",
          "userName": "user",
          "password": "***"
        }
      }
    }
  }
}

代码中通过 api.pluginConfig 读取。

本地验证 链接到标题

编译项目后,使用 clawhub CLI 做完整性检查:

npx tsc
clawhub package validate .

成功输出:

Plugin Inspector: PASS
Breakages: 0
Warnings: 0
Findings: none

Inspector 会检查:清单字段完整性、入口文件存在性、依赖冲突、Node 版本兼容性等。验证报告会写入 reports/ 目录。

发布到 ClawHub 链接到标题

发布需要关联一个 GitHub 仓库(公开或私有均可):

clawhub package publish <scope>/<name> \
  --source-repo <github-user>/<repo-name> \
  --source-commit $(git rev-parse HEAD)
  • <scope>:你的 GitHub 用户名
  • <name>:包名,与插件 id 无关,独立定义
  • ClawHub 不限制仓库必须是公开的,私有仓库也能发布
  • 每次发布建议更新版本号

发布后查看:

clawhub package info <scope>/<name>

版本管理 链接到标题

建议使用 semver,每次修改后更新 openclaw.plugin.json 中的 version,再重新发布。Agent 安装时若不指定版本,默认拉取最新版。

远程节点安装 链接到标题

在有 OpenClaw gateway 运行的节点上安装:

openclaw plugins install clawhub:<scope>/<name>

安装后,编辑 openclaw.json 添加配置(可选),然后重启 gateway:

# Docker 部署场景
docker restart openclaw-openclaw-gateway-1

验证插件是否加载成功:

docker logs openclaw-openclaw-gateway-1 2>&1 | grep "plugin"

日志中应看到插件名称出现在加载列表中:

http server listening (N plugins: ... my-plugin ...)

关闭并卸载 链接到标题

openclaw.json 中可以:

  • plugins.allow 中移除(彻底卸载)
  • 或设置 plugins.entries.<id>.enabled: false(临时禁用)

日志与调试 链接到标题

插件内的标准输出会被 OpenClaw 日志系统捕获:

console.log("[my-plugin] [INFO] 信息");
console.warn("[my-plugin] [WARN] 警告");
console.error("[my-plugin] [ERROR] 错误");

建议日志格式保持 [插件名] [级别] 消息,便于 grep 过滤。

对于需要持久化的状态(如上一次处理的 seq、token 等),有两种方式:

  • 写入文件(插件进程内持久)
  • 通过 api.storage SDK 接口(推荐,配置管理等场景)

小结 链接到标题

OpenClaw 插件机制的几个要点:

  • TypeScript ESM + Node ≥22 是硬性要求
  • 插件清单定义了元数据和能力,configSchema 是必需字段
  • 入口文件package.json#openclaw.extensions 中声明,不在 manifest 中
  • 发布不要求公开仓库,私有仓库完全可用
  • 远程安装一行命令,配置通过 openclaw.json 注入
  • 日志通过 console 输出,与 gateway 日志汇总

插件的应用场景不止于此:可以挂载 HTTP handler、定时任务、集成外部服务。对于需要在 AI agent 侧执行的计算密集型或持久化任务,插件是比 Skill 更合适的选择。