13.1 扩展架构设计

生成模型:Claude Opus 4.6 (anthropic/claude-opus-4-6) Token 消耗:输入 ~700k tokens,输出 ~65k tokens(本章合计)


前两章我们深入分析了 OpenClaw 内置的六大核心通道(WhatsApp、Telegram、Discord、Slack、Signal、iMessage)。但通讯平台数以百计,不可能全部内置。OpenClaw 通过插件系统(Plugin System)实现了通道的可扩展性——任何人都可以编写一个插件来接入新的通讯平台。本章将深入剖析这套扩展机制的设计与实现。


13.1.1 扩展与核心通道的区别

OpenClaw 中的通道分为两类:

维度
核心通道(Core Channels)
扩展通道(Extension Channels)

代码位置

src/web/src/telegram/

extensions/~/.config/openclaw/extensions/

加载方式

编译时静态导入

运行时通过 jiti 动态加载

配置位置

channels.slackchannels.telegram

plugins.entries.<id>

发布方式

随 OpenClaw 主包发布

npm 包或本地目录

监听方式

直接调用 monitor*Provider()

通过 Plugin Service 或 Hook 注册

示例

WhatsApp、Telegram、Discord、Slack

MS Teams、Matrix、Twitch、飞书

这个区分不是能力层面的——扩展通道可以实现与核心通道完全相同的功能。区分的本质是部署策略:核心通道是 OpenClaw 的"出厂配置",而扩展通道是"按需安装"。

为什么需要扩展?

  1. 减小主包体积:不是每个用户都需要飞书或 Matrix

  2. 独立版本管理:扩展可以独立于主包更新

  3. 社区贡献友好:第三方可以不修改主仓库就发布新通道

  4. 原生依赖隔离:某些通道(如 Matrix)需要 native 模块(matrix-sdk-crypto-nodejs),放在扩展中可以避免安装失败影响主包


13.1.2 扩展加载机制(src/plugins/loader.ts

加载流程概览

插件的加载由 loadOpenClawPlugins() 函数编排,这是整个插件系统的核心入口:

整个流程可以概括为四个阶段:

插件发现(Discovery)

discoverOpenClawPlugins() 从四个位置搜索插件,优先级从高到低:

来源
路径
origin 标识
使用场景

配置路径

plugins.loadPaths 中指定

"config"

开发调试、自定义部署

工作区

.openclaw/extensions/

"workspace"

项目级插件

全局

~/.config/openclaw/extensions/

"global"

用户级插件

内置

OpenClaw 包中的 extensions/

"bundled"

官方扩展(MS Teams 等)

每个发现位置支持两种组织形式:

  1. 单文件插件:目录中直接放 .ts.js 文件

  2. 包形式插件:子目录包含 package.json,其中 openclaw.extensions 字段声明入口文件

插件清单(Manifest)

每个插件必须包含一个 openclaw.plugin.json 清单文件:

清单的关键字段:

字段
必填
说明

id

全局唯一标识符

configSchema

JSON Schema,用于验证插件配置

kind

插件类型(目前仅 "memory" 用于记忆插件的互斥)

channels

声明此插件提供的通道 ID

providers

声明此插件提供的模型 Provider

uiHints

配置字段的 UI 提示(用于控制面板)

jiti 动态加载

衍生解释jitiarrow-up-right 是一个即时编译 TypeScript/ESM 的运行时工具。它允许 Node.js 直接 require() TypeScript 文件,无需预编译。这对插件系统特别有价值——用户可以直接用 TypeScript 编写插件,无需配置构建工具链。

OpenClaw 使用 jiti 加载插件模块:

alias 配置将 openclaw/plugin-sdk 映射到实际的 SDK 源文件路径,使得插件可以这样导入:

启用/禁用控制

插件的启用状态由多层配置共同决定:

控制方式包括:

  1. 显式启用plugins.entries.<id>.enabled: true

  2. 显式禁用plugins.entries.<id>.enabled: false

  3. deny 列表plugins.deny: ["msteams"]

  4. allow 列表plugins.allow: ["msteams"](如果设置,则只加载列出的插件)

  5. 默认行为bundled 来源的插件默认启用,其他来源的插件默认启用


13.1.3 扩展目录结构分析(以 MS Teams 为例)

虽然我们无法在本书中展示所有扩展的源代码,但可以通过通用的扩展目录结构来理解扩展应该如何组织。一个典型的通道扩展目录结构如下:

入口文件的基本结构:

扩展与主程序的交互接口

扩展通过 OpenClawPluginApi 与 OpenClaw 主程序交互。这个 API 对象在 register() 被调用时注入,提供了注册各种能力的方法:

这个设计遵循了控制反转(IoC)原则——插件不直接调用 OpenClaw 的内部 API,而是通过注册回调的方式声明自己的能力,由 OpenClaw 的运行时在合适的时机调用。

加载到 Gateway 的流程

在 Gateway 服务器启动时,loadGatewayPlugins() 负责将插件系统接入 Gateway:


本节小结

  1. OpenClaw 的通道分为核心通道和扩展通道,两者能力等价,区别在于部署策略。扩展通道通过插件系统按需安装,减小主包体积并支持独立版本管理。

  2. 插件加载流程遵循"发现→解析→加载→注册"四阶段:从四个位置发现候选插件,读取 openclaw.plugin.json 清单,通过 jiti 动态加载 TypeScript/JavaScript 模块,最后调用 register() 函数完成注册。

  3. jiti 运行时允许直接加载 TypeScript,配合 openclaw/plugin-sdk 别名映射,使得插件开发无需配置构建工具链。

  4. OpenClawPluginApi 是插件与主程序的唯一交互接口,采用控制反转(IoC)模式,插件通过注册回调声明能力,由运行时在合适时机调用。

  5. 插件清单是必需的,它定义了插件 ID、配置 Schema、通道/Provider 声明等元信息,是插件系统进行验证和管理的基础。

Last updated