OpenClaw 插件系统开发实战:从 plugin.json 到能力注册的完整链路 原创

温馨提示:
本文最后更新于 2026-09-24,已超过 1 天没有更新。 若文章内的图片失效(无法正常加载),请留言反馈或直接 联系我。

引言

插件(Plugin)是 OpenClaw 扩展能力边界的官方机制。与技能(Skill)提供”怎么做”的知识不同,插件能注册新工具、接入 MCP server、挂载 dashboard 部件、提供新技能,甚至携带可执行代码。本文从插件目录结构、manifest 规范、加载链路到开发一个完整插件的全过程,讲清楚插件如何被 Gateway 发现、安装和运行。

一、插件 vs 技能:先分清边界

很多人会混淆插件和技能。核心区别在于能力层级:

维度 技能 Skill 插件 Plugin
本质 一份 Markdown 指令 一个完整代码包
能否提供新工具 不能,只能指导调用现有工具 能,注册工具/MCP server
能否执行代码 不能 能,带 Node 模块/脚本
加载方式 模型按需 read Gateway 启动时加载
生命周期 文件即生效 install → enable → reload

判断标准:如果只是想让助手”学会一个流程”,写技能;如果要”接入一个外部系统或提供新能力”(如控制浏览器、连数据库、发 Discord),写插件。

二、插件的标准目录结构

my-plugin/
├── plugin.json          # 插件清单(必需)
├── README.md            # 说明文档
├── index.js             # 插件入口(Node 模块)
├── skills/              # 插件携带的技能
│   └── my-skill/
│       └── SKILL.md
├── tools/               # 工具定义
├── mcp/                 # MCP server 配置
├── widgets/             # dashboard 部件
└── assets/              # 静态资源

三、plugin.json manifest 规范

{
  "name": "weather-alert",
  "version": "1.0.0",
  "description": "Fetch weather and send alerts before severe weather.",
  "author": "your-name",
  "main": "index.js",
  "minGatewayVersion": "2026.9.0",
  "permissions": [
    "network:api.open-meteo.com",
    "tool:register",
    "dashboard:widget"
  ],
  "tools": ["./tools/weather.json"],
  "skills": ["./skills/weather-alert"],
  "config": {
    "defaultCity": {"type": "string", "default": "Shanghai"},
    "alertThreshold": {"type": "number", "default": 30}
  }
}

关键字段:

  • name:全局唯一标识,小写连字符
  • main:入口模块,Gateway 加载时 require 它
  • permissions:声明所需权限,遵循最小权限原则。网络访问需显式声明目标域名
  • tools/skills:声明携带的工具和技能路径
  • config:暴露给用户的可配置项及默认值

四、Gateway 插件加载链路

Gateway 启动(或执行 plugins reload)时,插件经历以下流程:

  1. 发现:扫描插件目录(本地安装或 catalog),读取每个 plugin.json
  2. 校验:检查 manifest 格式、版本兼容性、权限声明合法性
  3. 依赖检查:确认 minGatewayVersion、插件间依赖满足
  4. 加载入口:require main 模块,调用其注册钩子
  5. 注册能力:工具注册到工具表、技能加入技能索引、MCP server 建立连接、widget 挂载
  6. 就绪:插件状态变为 active

插件目录来源:

# 通过 CLI 安装的插件
~/.openclaw/plugins/

# 随系统分发
~/.local/lib/node_modules/openclaw/plugins/

五、开发一个完整插件:天气预警

1. index.js 入口

// index.js
module.exports = function register(context) {
  const { registerTool, registerWidget, logger, config } = context;

  // 注册工具
  registerTool({
    name: 'get_weather',
    description: 'Get current weather for a city',
    parameters: {
      type: 'object',
      properties: {
        city: { type: 'string', description: 'City name' }
      },
      required: ['city']
    },
    async handler({ city }) {
      const url =
        `https://api.open-meteo.com/v1/forecast?latitude=31.2&longitude=121.5¤t=temperature_2m,weather_code`;
      const res = await fetch(url);
      if (!res.ok) throw new Error(`Weather API ${res.status}`);
      const data = await res.json();
      return {
        city,
        temperature: data.current.temperature_2m,
        weatherCode: data.current.weather_code
      };
    }
  });

  // 注册 dashboard 部件
  registerWidget({
    id: 'weather-panel',
    title: '天气面板',
    render: () => buildWeatherWidget(config)
  });

  logger.info('weather-alert plugin loaded');
};

2. 携带技能


---
name: weather-alert
description: Check weather and send severe weather alerts.
  Use when user asks about weather, rain, temperature, or forecasts.
---

# Weather Alert

## Steps
1. Call get_weather tool with the city
2. If weatherCode indicates rain/storm, advise the user
3. Temperature below config.alertThreshold: mention cold warning

3. 打包与本地安装

# 本地开发目录
~/.openclaw/plugins/weather-alert/

# 或通过 plugins 工具从 catalog 安装
# plugins(action=install, name=weather-alert)

# 启用并热重载(无需重启 Gateway)
# plugins(action=enable, name=weather-alert)
# plugins(action=reload, name=weather-alert)

六、MCP server 集成

插件最常见的用途之一是桥接 MCP server,把外部工具生态接入 OpenClaw。在 manifest 声明:

{
  "mcp": {
    "servers": {
      "database": {
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-postgres"],
        "env": {"DATABASE_URL": "${secret:PG_CONN}"},
        "tools": ["query"]
      }
    }
  }
}

Gateway 会启动这个 MCP server 子进程,把它暴露的 query 工具纳入工具表。敏感连接串通过 ${secret:NAME} 引用密钥存储,绝不硬编码。

七、插件安全:权限沙箱

插件能执行代码,因此安全模型比技能严格:

  • 权限白名单:插件只能访问 manifest 中声明的权限,未声明的网络域名/文件路径/工具能力被拒绝
  • 来源审查:从 ClawHub/GitHub 安装第三方插件前应做安全审查(skill-vetter 技能专门干这个)
  • 密钥隔离:插件通过 secret 引用访问凭据,不直接读取密钥文件
  • 崩溃隔离:插件加载失败或运行时抛错不应拖垮 Gateway,异常被捕获并标记插件为 error 状态

八、调试与排障

# 查看插件状态
# plugins(action=list)  → 查看 enabled/disabled/error 状态及版本

# 插件不生效的排查顺序
1. plugin.json 是否合法 JSON,name 是否冲突
2. minGatewayVersion 是否高于当前版本
3. main 入口路径是否正确、require 是否报错
4. 权限声明是否覆盖了实际访问的资源
5. reload 是否执行(改代码后必须 reload)
6. 查看 Gateway 日志中的插件加载错误

开发期建议把插件目录软链到 ~/.openclaw/plugins/,改完代码执行 reload 即可热验证,不必反复重启。

九、发布到 catalog

插件成熟后可发布到官方 catalog 或 ClawHub 分享:

  1. 确保 README 完整说明能力、权限、配置项
  2. 版本号遵循 semver,破坏性变更升 major
  3. 移除硬编码密钥、调试代码、无关文件
  4. 提交到插件仓库或通过 workshop 提交流程

总结

插件开发的核心心智模型:plugin.json 声明”我是谁、要什么权限、提供什么”,index.js 在注册钩子里真正注册工具/部件/MCP,skills/ 顺带教会模型如何使用这些新能力。与技能的”纯知识”不同,插件是”能力包”。最小路径是先写一个只注册单个工具的插件跑通加载链路,再逐步加技能、MCP 和 widget。