万字解析 OpenClaw 源码架构-消息渠道集成简介

5 阅读26分钟

渠道插件系统由“插件 SDK(编译期、稳定、可发布)”和“插件运行时(执行面、被注入)”两层组成,所有插件通过 SDK 暴露的类型与工具函数进行开发,并通过运行时访问核心行为,避免直接依赖 src/** 的内部实现。

  • 插件 SDK:导出类型、配置工具、分组策略、消息处理辅助等,作为稳定接口层。
  • 插件运行时:提供通道文本、回复、路由、配对、媒体、提及、群组策略、防抖、命令授权等运行期能力。
  • 内置插件:以 extensions/* 下的具体渠道插件为代表,如 Discord、Telegram 等,遵循统一的 ChannelPlugin 合同并通过 openclaw.plugin.json 声明元数据。
graph TB
subgraph "插件SDK"
SDK_Index["SDK入口<br/>src/plugin-sdk/index.ts"]
SDK_Types["SDK类型与工具<br/>src/channels/plugins/types.*"]
SDK_RuntimeTypes["运行时类型<br/>src/plugins/runtime/types.ts"]
end
subgraph "内置插件"
Ext_Discord["Discord插件<br/>extensions/discord/index.ts"]
Ext_Telegram["Telegram插件<br/>extensions/telegram/index.ts"]
Ext_PluginJSON["插件清单<br/>extensions/*/openclaw.plugin.json"]
end
SDK_Index --> Ext_Discord
SDK_Index --> Ext_Telegram
Ext_Discord --> Ext_PluginJSON
Ext_Telegram --> Ext_PluginJSON
SDK_Types --> SDK_Index
SDK_RuntimeTypes --> SDK_Index

核心组件

  • 插件 SDK 入口与导出:集中导出类型、适配器、配置模式、工具函数与运行时访问点,确保外部插件只依赖 SDK。
  • ChannelPlugin 合同:定义渠道插件的 id、meta、capabilities、配置、适配器集合(认证、网关、消息、线程、目录、解析器、心跳等)以及可选的代理工具。
  • 运行时接口 PluginRuntime:提供子代理运行、会话查询、删除,以及通道级能力(文本分块、路由、配对、媒体、提及、群组策略、防抖、命令授权等)。
  • 插件 API OpenClawPluginApi:插件注册入口,支持注册工具、钩子、HTTP 路由、通道、网关方法、CLI、服务、提供商、命令与上下文引擎。
  • 卸载流程:从配置中移除插件条目、安装记录、白名单、加载路径与内存槽位,保证干净卸载。

架构总览

插件系统采用“SDK + 运行时”的双层架构,确保:

  • 可移植性:插件仅依赖 SDK 类型与工具,不直接导入 src/**。
  • 可演进性:运行时版本与 SDK 版本独立管理,插件声明所需运行时范围。
  • 可测试性:通过 adapter-level 单测与 golden 测试验证行为一致性。
sequenceDiagram
participant Dev as "开发者"
participant SDK as "插件SDK"
participant Runtime as "插件运行时"
participant Core as "核心系统"
Dev->>SDK : 使用类型与工具开发插件
SDK->>Runtime : 通过api.runtime访问运行能力
Runtime->>Core : 访问核心行为路由、配对、媒体等
Core-->>Runtime : 返回结果或状态
Runtime-->>SDK : 提供统一运行时接口
SDK-->>Dev : 导出插件合约与工具

详细组件分析

插件 SDK 与运行时接口

  • SDK 入口导出大量类型与工具,包括通道适配器、配置模式、分组策略、允许列表解析、命令授权、入站信封构建、回复派发、媒体处理、SSRF 策略、Webhook 内存守卫、日志与诊断事件等。
  • 运行时接口提供:
    • 子代理运行与等待、会话消息读取、会话删除
    • 通道级能力:文本分块与长度解析、路由解析、配对、媒体抓取与保存、提及正则构建与匹配、群组策略解析、防抖器、命令授权
classDiagram
class OpenClawPluginApi {
+registerTool(tool, opts)
+registerHook(events, handler, opts)
+registerHttpRoute(params)
+registerChannel(registration)
+registerGatewayMethod(method, handler)
+registerCli(registrar, opts)
+registerService(service)
+registerProvider(provider)
+registerCommand(command)
+registerContextEngine(id, factory)
+resolvePath(input)
+on(hookName, handler, opts)
}
class PluginRuntime {
+subagent.run(params)
+subagent.waitForRun(params)
+subagent.getSessionMessages(params)
+subagent.deleteSession(params)
+channel.text.*
+channel.reply.*
+channel.routing.resolveAgentRoute(...)
+channel.pairing.*
+channel.media.*
+channel.mentions.*
+channel.groups.*
+channel.debounce.*
+channel.commands.*
}
OpenClawPluginApi --> PluginRuntime : "通过api.runtime访问"

ChannelPlugin 合同与扩展点

  • ChannelPlugin 定义了插件的标识、元数据、能力、默认参数、重载前缀、引导向导、配置适配器、配置模式、设置、配对、安全、群组、提及、出站、状态、网关方法、网关、认证、提升权限、命令、流式、线程、消息、代理提示、目录、解析器、消息动作、心跳以及代理工具集合。
  • 扩展点覆盖从“账户配置、目录、群组策略、消息路由、配对、安全策略、消息发送、状态探测、网关方法、消息动作、心跳”到“代理工具”的全链路能力。
classDiagram
class ChannelPlugin {
+id : ChannelId
+meta : ChannelMeta
+capabilities : ChannelCapabilities
+defaults.queue.debounceMs
+reload.configPrefixes
+onboarding
+config
+configSchema
+setup
+pairing
+security
+groups
+mentions
+outbound
+status
+gatewayMethods[]
+gateway
+auth
+elevated
+commands
+streaming
+threading
+messaging
+agentPrompt
+directory
+resolver
+actions
+heartbeat
+agentTools
}

内置插件示例:Telegram 与 Discord

  • Telegram 插件:通过入口文件注册运行时并注册通道插件,配置模式为空(无额外字段),体现最小化配置原则。
  • Discord 插件:通过 openclaw.plugin.json 声明 id 与支持的渠道数组,配置模式为空对象,表明当前版本无特定配置项。
sequenceDiagram
participant Entry as "插件入口<br/>extensions/telegram/index.ts"
participant SDK as "SDK"
participant Runtime as "运行时"
participant Registry as "通道注册表"
Entry->>Runtime : setTelegramRuntime(api.runtime)
Entry->>SDK : api.registerChannel({ plugin })
SDK->>Registry : 注册Telegram ChannelPlugin
Note over Registry : 完成通道能力接入

插件安装、更新与卸载流程

  • 安装:将插件源码置于工作区或全局路径,配置安装记录与加载路径;插件通过 openclaw.plugin.json 声明 id 与渠道支持。
  • 更新:通过重新安装或替换插件包,保持配置兼容;运行时版本与 SDK 版本需满足兼容范围。
  • 卸载:从配置中移除插件条目、安装记录、白名单、加载路径与内存槽位,确保无残留引用。
flowchart TD
Start(["开始卸载"]) --> ReadCfg["读取配置中的插件段"]
ReadCfg --> RemoveEntry["从entries移除插件"]
ReadCfg --> RemoveInstall["从installs移除插件"]
ReadCfg --> RemoveAllow["从allow移除插件"]
ReadCfg --> CleanLoadPaths["从load.paths清理关联路径"]
ReadCfg --> CleanupSlots["清理内存槽位"]
RemoveEntry --> WriteCfg["写回配置"]
RemoveInstall --> WriteCfg
RemoveAllow --> WriteCfg
CleanLoadPaths --> WriteCfg
CleanupSlots --> WriteCfg
WriteCfg --> End(["完成"])

自定义插件开发指南

  • 契约与适配器:实现 ChannelPlugin 合同,按需提供 config、messaging、threading、directory、resolver、heartbeat、agentTools 等适配器。
  • 配置模式:使用 SDK 提供的配置模式工具与 Schema 构建 UI 提示与校验逻辑。
  • 运行时访问:通过 api.runtime 访问通道能力与核心行为,避免直接导入 src/**。
  • 钩子与命令:注册插件钩子与命令,实现提示词注入、消息拦截、工具调用控制与简单命令处理。
  • 文档与测试:遵循 SDK 版本与运行时版本兼容策略,提供 adapter-level 单测与 golden 测试。

API 接口规范与最佳实践

  • 插件 API:统一的注册入口,支持工具、钩子、HTTP 路由、通道、网关方法、CLI、服务、提供商、命令与上下文引擎注册。
  • 运行时接口:最小但完整的通道能力集合,确保跨渠道一致性。
  • 最佳实践:
    • 严格遵循 SDK 类型与工具,避免直接依赖核心实现。
    • 使用运行时而非直接调用核心逻辑。
    • 为复杂场景提供适配器与配置模式,简化用户配置。
    • 通过钩子与命令实现非 LLM 的快速交互与状态切换。

安全机制、权限控制与性能监控

  • 允许列表与分组策略:提供 allowlist 解析、分组访问决策、提及要求解析与工具策略,结合 DM 策略与命令授权,形成多层安全控制。
  • SSRF 与请求限制:提供 SSRF 策略、HTTPS 允许列表、请求体大小限制与异常计数器,防止滥用与资源耗尽。
  • 性能监控:通过诊断事件系统与运行时日志,记录消息队列、处理、工具调用、会话生命周期等关键指标,便于性能分析与问题定位。

依赖关系分析

  • 插件 SDK 与运行时:SDK 仅暴露类型与工具,运行时提供执行面能力,二者通过 OpenClawPluginApi 关联。
  • 内置插件与 SDK:内置插件通过 SDK 入口导出的类型与工具进行开发与注册,遵循统一合同。
  • 卸载流程:依赖配置结构与路径清理,确保插件完全移除。
graph LR
SDK_Index["SDK入口<br/>src/plugin-sdk/index.ts"] --> Types_Plugin["ChannelPlugin类型<br/>src/channels/plugins/types.plugin.ts"]
SDK_Index --> Types_Runtime["运行时类型<br/>src/plugins/runtime/types.ts"]
Types_Plugin --> Ext_Discord["Discord插件<br/>extensions/discord/index.ts"]
Types_Plugin --> Ext_Telegram["Telegram插件<br/>extensions/telegram/index.ts"]
Uninstall["卸载流程<br/>src/plugins/uninstall.ts"] --> Cfg["配置结构"]

性能考量

  • 防抖与批处理:运行时提供入站消息防抖器,降低重复处理开销。
  • 文本分块与媒体处理:提供文本分块与媒体加载优化,减少单次传输压力。
  • 请求限制与异常追踪:通过请求体限制与异常计数器,避免过载与异常放大。
  • 诊断事件:记录关键阶段的耗时与用量,辅助性能优化与容量规划。

渠道架构设计

OpenClaw 的渠道体系由“核心渠道类型定义”“插件注册表与加载器”“渠道停靠(Dock)元数据”“健康监控与路由”等模块构成。下图展示关键模块之间的关系:

graph TB
subgraph "渠道类型与适配器"
Types["types.ts<br/>类型导出"]
TypesCore["types.core.ts<br/>核心类型"]
TypesAdapters["types.adapters.ts<br/>适配器接口"]
end
subgraph "插件系统"
Registry["plugins/registry.ts<br/>插件注册表"]
Loader["channels/plugins/registry-loader.ts<br/>通道注册表加载器"]
LoadPlugin["channels/plugins/load.ts<br/>加载插件"]
LoadOutbound["channels/plugins/outbound/load.ts<br/>加载出站适配器"]
end
subgraph "渠道停靠与元数据"
Dock["channels/dock.ts<br/>渠道停靠(Dock)"]
Reg["channels/registry.ts<br/>渠道注册表/别名"]
end
subgraph "运行时与监控"
Health["gateway/channel-health-monitor.ts<br/>健康监控"]
Router["infra/outbound/bound-delivery-router.ts<br/>绑定投递路由器"]
DeliveryCmd["commands/agent/delivery.ts<br/>交付命令"]
end
Types --> TypesCore
Types --> TypesAdapters
Registry --> Loader
Loader --> LoadPlugin
Loader --> LoadOutbound
Dock --> Reg
Dock --> Loader
Health --> Registry
Router --> Registry
DeliveryCmd --> Loader

核心组件

  • 渠道类型与适配器接口

    • 类型导出与核心类型:统一导出渠道适配器、账户快照、能力集、消息动作等类型定义,便于跨模块复用。
    • 适配器接口:定义配置、状态、网关、认证、心跳、目录解析、线程处理、消息动作等适配器契约,确保不同渠道实现的一致性与可替换性。
  • 插件注册表与加载器

    • 插件注册表:集中记录已加载的插件、工具、钩子、HTTP 路由、命令、服务等,并维护渠道注册项列表。
    • 注册表加载器:基于活跃插件注册表,按渠道 ID 缓存并解析对应插件或适配器实例,避免重复导入与副作用。
  • 渠道停靠(Dock)

    • 停靠元数据:为内置渠道提供能力集、默认文本分片限制、提及规则、线程上下文构建、允许来源解析与格式化等轻量行为描述。
    • 动态停靠:从插件构建停靠信息,支持外部渠道扩展。
  • 健康监控与路由

    • 健康监控:周期性检查渠道运行时快照,评估健康度并执行重启策略,带冷却与限速保护。
    • 绑定投递路由器:根据会话绑定与请求者信息解析目标渠道账户,支持单活绑定与回退模式。

架构总览

下图展示渠道适配器在系统中的位置与交互关系:

graph TB
Client["客户端/命令行"] --> DeliveryCmd["交付命令<br/>commands/agent/delivery.ts"]
DeliveryCmd --> Loader["插件加载器<br/>channels/plugins/load.ts"]
Loader --> Registry["插件注册表<br/>plugins/registry.ts"]
Registry --> Dock["渠道停靠<br/>channels/dock.ts"]
Dock --> Router["绑定投递路由器<br/>infra/outbound/bound-delivery-router.ts"]
Dock --> Health["健康监控<br/>gateway/channel-health-monitor.ts"]
Dock --> Types["类型与适配器<br/>channels/plugins/types.*.ts"]

详细组件分析

注册表系统与插件加载

  • 设计要点

    • 活跃注册表缓存:加载器在首次访问时读取当前活跃注册表,若注册表变更则清空缓存,保证一致性。
    • 值解析器抽象:通过通用工厂函数将插件注册项映射为具体适配器或插件对象,支持出站适配器专用加载路径以降低导入成本。
    • 错误与诊断:注册表对缺失 ID、重复注册、HTTP 路由冲突等情况进行诊断并记录。
  • 关键流程(加载插件)

sequenceDiagram
participant Cmd as "交付命令"
participant Loader as "插件加载器"
participant Registry as "插件注册表"
participant Dock as "渠道停靠"
Cmd->>Loader : 请求加载渠道插件
Loader->>Registry : 查询通道注册项
alt 找到注册项
Loader->>Loader : 解析插件/适配器
Loader-->>Cmd : 返回适配器实例
Loader->>Dock : 构建停靠元数据
else 未找到
Loader-->>Cmd : 返回未命中
end

配置管理与停靠元数据

  • 设计要点

    • 内置渠道停靠:为 Telegram、WhatsApp、Discord、IRC、Google Chat、Slack、Signal、iMessage、LINE 等内置渠道提供统一的能力集、默认文本分片限制、提及规则与线程上下文构建。
    • 外部渠道停靠:从插件动态构建停靠信息,保持与内置渠道一致的行为边界。
    • 允许来源与默认目标:针对不同渠道提供允许来源解析与格式化、默认目标解析逻辑,确保安全与可用性。
  • 关键流程(解析允许来源)

flowchart TD
Start(["开始"]) --> Resolve["解析渠道配置<br/>resolveAllowFrom"]
Resolve --> Format["格式化允许来源<br/>formatAllowFrom"]
Format --> Apply["应用到线程/投递上下文"]
Apply --> End(["结束"])

消息路由与状态同步

  • 设计要点

    • 绑定投递路由器:根据目标会话键与活动绑定列表解析最终投递目标;当存在多个绑定或缺少请求者时采用回退模式,确保在多账户场景下的正确路由。
    • 状态同步:渠道状态快照包含启用/配置/连接/最近事件时间戳、错误信息、令牌状态等字段,用于健康监控与诊断。
  • 关键流程(绑定路由解析)

flowchart TD
S(["输入: 目标会话键, 请求者"]) --> CheckKey{"会话键为空?"}
CheckKey -- 是 --> Fallback["返回回退模式<br/>原因: 缺少目标会话"]
CheckKey -- 否 --> List["列出该会话的活动绑定"]
List --> HasAny{"是否存在活动绑定?"}
HasAny -- 否 --> Fallback2["返回回退模式<br/>原因: 无活动绑定"]
HasAny -- 是 --> HasReq{"是否有请求者?"}
HasReq -- 否 --> Single{"绑定数量=1?"}
Single -- 是 --> Bound["返回绑定模式<br/>原因: 单一活动绑定"]
Single -- 否 --> Fallback3["返回回退模式<br/>原因: 无请求者且不唯一"]
HasReq -- 是 --> Multi{"绑定数量>1?"}
Multi -- 是 --> Fallback4["返回回退模式<br/>原因: 不明确(多绑定)"]
Multi -- 否 --> Bound

生命周期管理与健康监控

  • 设计要点

    • 周期性检查:健康监控器在启动宽限期后开始定期检查渠道运行时快照,评估连接状态与事件新鲜度。
    • 重启策略:对不健康的渠道执行停止/启动组合操作,带冷却周期与每小时最大重启次数限制,防止风暴重启。
    • 可配置参数:检查间隔、启动宽限期、事件过期阈值、连接宽限期等均可配置。
  • 关键流程(健康检查与重启)

sequenceDiagram
participant Monitor as "健康监控器"
participant Manager as "渠道管理器"
participant Snapshot as "运行时快照"
Monitor->>Monitor : 计算冷却与限速
Monitor->>Manager : 获取运行时快照
Manager-->>Monitor : 返回快照
Monitor->>Monitor : 评估每个渠道健康度
alt 不健康
Monitor->>Monitor : 记录重启记录
Monitor->>Manager : 停止渠道
Monitor->>Manager : 启动渠道
else 健康
Monitor->>Monitor : 无需操作
end

数据传输协议、序列化与事件传播

  • 协议与序列化

    • 出站适配器支持直接/网关/混合三种投递模式,并提供文本分片器与轮询选项上限,确保消息在不同渠道间的可靠传输。
    • 消息动作适配器定义了可发现的动作清单、按钮/卡片支持与工具发送提取逻辑,便于跨渠道统一事件传播。
  • 事件传播

    • 网关上下文提供日志、状态读写与可选的渠道运行时辅助能力,使外部插件能够参与 AI 回复派发、路由、文本处理、会话管理、媒体处理、命令授权与群组策略等高级功能。

错误恢复策略与性能优化

  • 错误恢复

    • 健康监控器在检测到异常后执行重启,同时应用冷却与限速,避免频繁重启导致雪崩。
    • 出站适配器提供分片与轮询上限,减少单次传输失败的影响面。
  • 性能优化

    • 加载器缓存:按渠道 ID 缓存解析结果,避免重复解析与昂贵的插件导入。
    • 轻量化出站加载:出站路径仅加载必要能力,降低导入成本。
    • 文本分片:针对不同渠道设置合理的文本分片限制,平衡吞吐与兼容性。

依赖关系分析

  • 组件耦合

    • 渠道类型与适配器接口是所有渠道实现的基础契约,耦合度低、内聚性强。
    • 插件注册表与加载器承担“发现—解析—缓存”的职责,与具体渠道实现解耦。
    • 渠道停靠聚合了渠道行为的轻量元数据,既可来自内置定义,也可来自插件构建,形成统一入口。
  • 外部依赖与集成点

    • 健康监控依赖渠道管理器提供的运行时快照与控制接口。
    • 投递路由器依赖会话绑定服务与渠道账户状态。
    • 交付命令依赖插件注册表以解析渠道插件。
graph LR
Types["类型与适配器"] --> Dock["渠道停靠"]
Dock --> Loader["注册表加载器"]
Loader --> Registry["插件注册表"]
Dock --> Router["绑定投递路由器"]
Dock --> Health["健康监控"]
Router --> Registry
Health --> Registry
DeliveryCmd["交付命令"] --> Loader

性能考虑

  • 导入与初始化
    • 使用注册表加载器缓存解析结果,避免重复扫描与昂贵的插件导入。
    • 出站加载器仅加载必要能力,缩短冷启动路径。
  • 文本分片与传输
    • 针对不同渠道设置合理的文本分片限制,兼顾吞吐与平台兼容性。
    • 轮询选项上限限制长轮询带来的资源占用。
  • 健康监控节流
    • 通过冷却周期与每小时重启上限,避免风暴重启对系统造成压力。

渠道配置管理

渠道配置管理涉及以下关键模块:

  • 配置读写与验证:负责配置的加载、校验、写回与变更检测
  • 动态重载与热重载:监听配置文件变化,评估变更影响并执行重启或热更新
  • 渠道插件配置模式:统一构建渠道配置的 JSON Schema,并支持多账户与默认账户
  • 备份与恢复:生成可验证的归档,记录清单并支持恢复
  • UI 表单渲染:基于通道 Schema 动态渲染表单,支持额外字段展示
  • 安全审计:对渠道安全策略进行审计与告警
graph TB
subgraph "配置层"
CFG["配置读写与验证<br/>src/config/*"]
VALID["配置验证器<br/>validation.ts"]
MIG["配置迁移<br/>legacy-migrate.ts"]
ENV["环境变量保留<br/>env-preserve.ts"]
end
subgraph "网关与重载"
RELOAD["配置重载器<br/>config-reload.ts"]
PLAN["重载计划<br/>config-reload-plan.ts"]
HANDLER["重启处理器<br/>server-reload-handlers.ts"]
end
subgraph "渠道插件"
SCHEMA["通道配置Schema构建<br/>config-schema.ts"]
HELPERS["通道配置辅助<br/>config-helpers.ts"]
ONBOARD["引导配置辅助<br/>onboarding/helpers.ts"]
end
subgraph "命令与工具"
BACKUP["备份命令<br/>commands/backup.ts"]
VERIFY["备份验证<br/>commands/backup-verify.ts"]
ADD["添加渠道账户<br/>commands/channels/add.ts"]
DOCTOR["安全审计<br/>commands/doctor-security.ts"]
end
subgraph "界面"
UI["通道配置表单<br/>ui/views/channels.config.ts"]
end
CFG --> VALID
CFG --> MIG
CFG --> ENV
CFG --> RELOAD
RELOAD --> PLAN
RELOAD --> HANDLER
SCHEMA --> UI
HELPERS --> ADD
ONBOARD --> ADD
BACKUP --> VERIFY
DOCTOR --> UI

核心组件

  • 配置读写与验证
    • 提供配置加载、快照读取、写回、运行时快照刷新等能力
    • 统一的配置对象验证流程,支持插件配置校验与警告收集
  • 动态重载与热重载
    • 基于文件监控的变更检测,计算差异路径,构建重载计划
    • 支持 off/restart/hot/hybrid 模式,自动选择重启或热更新
  • 渠道配置 Schema 与多账户
    • 使用 Zod 构建 JSON Schema,兼容旧版插件
    • 支持 accounts.catchall 与 defaultAccount,实现多账户与默认账户
  • 环境变量保留
    • 在写回时识别并保留 ${VAR} 引用,避免丢失原始占位符
  • 备份与恢复
    • 生成带清单的压缩归档,支持输出路径解析、硬链接/拷贝发布、可选验证
    • 验证清单格式与字段完整性,确保可恢复性
  • UI 表单渲染
    • 基于通道 Schema 动态渲染表单,支持额外字段展示(如 groupPolicy、streamMode、dmPolicy)

架构总览

下图展示了从配置文件到运行时生效的关键流转:文件监控触发重载计划,评估是否需要重启或热更新;同时,配置验证与迁移保证数据一致性;环境变量保留确保写回后仍能保留占位符;备份与验证保障可恢复性。

sequenceDiagram
participant FS as "文件系统"
participant Watch as "配置重载器<br/>config-reload.ts"
participant Plan as "重载计划<br/>config-reload-plan.ts"
participant Handler as "重启处理器<br/>server-reload-handlers.ts"
participant Valid as "配置验证<br/>validation.ts"
participant Env as "环境变量保留<br/>env-preserve.ts"
FS-->>Watch : "文件变更事件"
Watch->>Watch : "读取配置快照"
Watch->>Valid : "验证配置"
Valid-->>Watch : "返回验证结果"
Watch->>Plan : "构建重载计划"
Plan-->>Watch : "返回计划(重启/热更新)"
alt "需要重启"
Watch->>Handler : "请求重启"
Handler-->>Watch : "重启完成"
else "热更新"
Watch-->>Watch : "执行热更新"
end
Watch->>Env : "写回前保留环境变量引用"
Env-->>Watch : "返回保留后的配置"
Watch-->>FS : "写回配置文件"

详细组件分析

配置文件结构与参数定义

  • 结构要点
    • 顶层包含 gateway、channels、plugins、agents、tools 等命名空间
    • channels 下按渠道 ID 维度组织,支持 accounts.catchall 与 defaultAccount
    • 插件配置通过 plugins.entries..config 进行声明
  • 参数定义
    • 使用 Zod Schema 生成 JSON Schema,用于 UI 表单渲染与前端校验
    • 兼容旧版 Zod v3 的插件,若缺少 toJSONSchema 则退化为允许任意属性的对象
  • 验证机制
    • 原始验证与应用默认值验证两条路径
    • 对插件配置进行独立 Schema 校验,收集错误与警告
    • 特定约束检查(如头像路径、Tailscale 绑定规则等)
flowchart TD
Start(["开始"]) --> Load["加载配置"]
Load --> ValidateRaw["原始验证<br/>validateConfigObjectRaw"]
ValidateRaw --> Valid{"验证通过?"}
Valid --> |否| ReportIssues["报告问题"]
Valid --> |是| ApplyDefaults["应用默认值"]
ApplyDefaults --> PluginValidate["插件配置验证"]
PluginValidate --> Issues{"有错误?"}
Issues --> |是| ReportIssues
Issues --> |否| Done(["完成"])

动态配置更新与热重载

  • 变更检测
    • 计算前后配置的差异路径,数组采用深度比较以避免误报
    • 支持缺失配置的有限次重试,降低瞬时文件系统抖动的影响
  • 重载决策
    • 基于预设规则集匹配变更路径,决定 restart/hot/none
    • 支持插件贡献的热更新/无操作前缀,实现通道级热更新
  • 执行策略
    • hybrid/off/restart/hot 模式由 gateway.reload.mode 控制
    • 热更新失败时记录日志并保持重载器运行等待下次变更
  • 文件监控
    • 使用 chokidar 监听配置文件目录,等待写入完成后再触发重载
flowchart TD
S(["收到变更事件"]) --> Snapshot["读取配置快照"]
Snapshot --> Missing{"文件存在?"}
Missing --> |否| Retry["有限重试/跳过"]
Missing --> |是| Valid{"快照有效?"}
Valid --> |否| Skip["跳过并记录问题"]
Valid --> |是| Diff["计算差异路径"]
Diff --> Plan["构建重载计划"]
Plan --> Mode{"模式?"}
Mode --> |off| Stop["停止重载"]
Mode --> |restart| QueueRestart["排队重启"]
Mode --> |hot| Hot["执行热更新"]
Mode --> |hybrid且需重启| QueueRestart
Mode --> |hybrid且可热更新| Hot
Hot --> End(["结束"])
QueueRestart --> End
Skip --> End
Retry --> End

配置迁移

  • 迁移流程
    • 应用遗留配置迁移规则,得到新配置与变更说明
    • 对迁移后的配置再次进行验证,若仍有问题则提示人工修复
  • 适用场景
    • 升级过程中自动修复不兼容字段
    • 保持配置可用性的同时尽量减少人工干预
sequenceDiagram
participant Raw as "原始配置"
participant Mig as "迁移器<br/>legacy-migrate.ts"
participant Val as "验证器<br/>validation.ts"
Raw->>Mig : "迁移"
Mig->>Val : "验证迁移后配置"
Val-->>Mig : "返回验证结果"
Mig-->>Raw : "返回迁移后的配置/变更说明"

多账户支持与默认账户

  • 多账户模型
    • 通过 accounts.catchall 接受任意键值,结合 defaultAccount 指定默认账户
    • 支持按账户维度启用/禁用与配置状态判断
  • 账户上下文
    • 解析默认账户 ID、账户详情、启用状态与配置状态
  • 账户操作
    • 添加/删除账户、启用状态切换、配置补丁更新
    • 渠道令牌轮换后清理相关状态(如 Telegram 更新偏移)
classDiagram
class ChannelPlugin {
+listAccountIds(cfg)
+resolveAccount(cfg, accountId)
+config.isEnabled(account, cfg)
+config.isConfigured(account, cfg)
}
class ChannelAccountContext {
+accountIds : string[]
+defaultAccountId : string
+account : unknown
+enabled : boolean
+configured : boolean
}
ChannelPlugin --> ChannelAccountContext : "解析默认账户上下文"

配置模板与环境变量替换

  • 环境变量替换
    • 支持 ${VAR} 语法,字符串中可包含多个变量与混合内容
    • 严格名称规范(大写字母、数字、下划线,可以下划线开头)
  • 写回时的引用保留
    • 当写回值与当前环境变量展开一致时,恢复原始 ${VAR} 引用
    • 避免无意中将占位符替换为实际值,导致后续启动时无法正确展开
flowchart TD
A["读取配置(含${VAR})"] --> B["解析环境变量"]
B --> C["写回配置"]
C --> D{"写回值与解析值一致?"}
D --> |是| E["恢复${VAR}引用"]
D --> |否| F["保留写回值"]
E --> G["写回文件"]
F --> G

UI 表单渲染与额外字段展示

  • Schema 解析
    • 基于通道 Schema 动态生成表单节点,支持对象与数组类型
    • 通过路径定位到具体通道的配置节点
  • 额外字段
    • 展示 groupPolicy、streamMode、dmPolicy 等非表单字段的当前值
    • 便于用户快速了解通道的附加行为设置
sequenceDiagram
participant UI as "UI 表单<br/>channels.config.ts"
participant Schema as "通道 Schema"
participant Value as "通道配置值"
UI->>Schema : "解析通道 Schema"
UI->>Value : "获取通道配置值"
UI->>UI : "渲染表单节点"
UI->>UI : "展示额外字段"

安全考虑与审计

  • 默认账户令牌策略
    • 默认账户允许使用环境变量令牌,命名账户不允许直接注入环境令牌
  • 安全审计
    • 对启用且已配置的通道收集安全策略与警告
    • 支持 DM 策略可视化与建议修复
flowchart TD
Start(["安全审计"]) --> List["枚举通道插件"]
List --> Check{"启用且已配置?"}
Check --> |否| Next["下一个"]
Check --> |是| Policy["解析DM策略/收集警告"]
Policy --> Warn["输出警告/建议"]
Warn --> Next
Next --> End(["结束"])

版本管理、备份恢复与批量部署

  • 备份
    • 自动解析输出路径,支持目录与文件两种形式
    • 生成清单并打包为压缩归档,支持硬链接/拷贝发布
    • 可选验证步骤,确保归档完整性
  • 恢复
    • 验证清单格式与字段,确保 schemaVersion、archiveRoot、createdAt 等字段有效
    • 校验资产列表与跳过项,防止越界与重复
  • 批量部署
    • 通过 CLI 命令批量添加渠道账户,自动处理默认账户与启用状态
    • 支持令牌轮换后的状态清理(如 Telegram)
sequenceDiagram
participant CLI as "CLI 备份命令"
participant Plan as "备份计划"
participant Tar as "归档打包"
participant Ver as "备份验证"
CLI->>Plan : "解析包含资产/路径"
CLI->>Tar : "生成清单并打包"
Tar-->>CLI : "输出归档路径"
CLI->>Ver : "可选验证"
Ver-->>CLI : "验证结果"

依赖关系分析

  • 组件耦合
    • 配置重载器依赖重载计划与重启处理器,形成清晰的职责分离
    • 渠道插件通过 Schema 构建与 UI 表单解耦,便于扩展
    • 备份命令与验证命令相互独立,便于测试与维护
  • 外部依赖
    • chokidar 用于文件监控
    • tar 用于归档打包
    • Zod 用于配置 Schema 生成与校验
graph TB
CR["config-reload.ts"] --> CRP["config-reload-plan.ts"]
CR --> SRH["server-reload-handlers.ts"]
CS["config-schema.ts"] --> UI["channels.config.ts"]
VAL["validation.ts"] --> CFG["config.ts"]
ENV["env-preserve.ts"] --> CFG
BK["backup.ts"] --> VER["backup-verify.ts"]
CHADD["commands/channels/add.ts"] --> CFG

性能考量

  • 文件监控稳定性
    • 使用 awaitWriteFinish 避免写入中途触发重载
    • 在测试环境下启用轮询模式,提升可靠性
  • 重载节流
    • 通过去抖与并发标记避免频繁重载
    • 缺失配置的有限重试策略降低无效工作负载
  • 归档性能
    • 优先使用硬链接发布,不支持时回退到拷贝
    • 压缩与便携选项平衡体积与跨平台兼容性

消息渠道集成

项目采用模块化设计,核心由以下部分组成:

  • 网关(Gateway):WebSocket控制平面,承载会话、存在性、配置、定时任务、钩子与事件分发
  • 渠道适配器(Channel Adapters):针对各消息平台的接入层,负责认证、连接、消息收发与格式转换
  • 客户端与节点(Clients & Nodes):桌面应用、CLI、Web界面与移动节点通过WS连接到网关
  • 插件与技能(Plugins & Skills):扩展能力与自动化工作流
graph TB
subgraph "网关控制平面"
GW["Gateway<br/>WebSocket 控制面"]
CFG["配置中心"]
SESS["会话存储"]
EVT["事件总线"]
end
subgraph "渠道适配器"
WA["WhatsApp Baileys"]
TG["Telegram grammY"]
DC["Discord Bot API"]
SG["Signal signal-cli"]
IM["iMessage imsg"]
GC["Google Chat HTTP"]
Others["其他渠道..."]
end
subgraph "客户端与节点"
CLI["CLI 工具"]
WEB["WebChat UI"]
MAC["macOS 应用"]
IOS["iOS 节点"]
AND["Android 节点"]
end
CLI --> GW
WEB --> GW
MAC --> GW
IOS --> GW
AND --> GW
GW --> WA
GW --> TG
GW --> DC
GW --> SG
GW --> IM
GW --> GC
GW --> Others
CFG --> GW
SESS --> GW
EVT --> GW

核心组件

  • 网关(Gateway)
    • 维护各提供商连接,暴露类型化WebSocket API(请求/响应/服务端推送事件)
    • 验证入站帧,发出事件如agent、chat、presence、health、heartbeat、cron
  • 渠道适配器(Channel Adapters)
    • 各平台专用适配器,负责认证、连接生命周期、消息路由与格式转换
    • 支持多账户、多账号实例、群组/频道/私聊隔离
  • 会话与路由(Sessions & Routing)
    • 基于会话键(session key)的确定性路由,确保回复回到原渠道
    • 支持主会话共享、按对端/按渠道/按账号隔离
  • 安全与配对(Security & Pairing)
    • 默认对未知发送者启用配对模式;允许通过批准码加入白名单
    • 设备级配对与本地信任模型,支持远程隧道与令牌认证

架构总览

系统采用单网关控制平面,所有消息表面(WhatsApp、Telegram、Discord、Signal、iMessage、WebChat等)均由网关统一持有连接与会话状态。客户端(桌面应用、CLI、Web UI、自动化)通过WebSocket连接到网关,节点(macOS/iOS/Android/headless)同样通过WebSocket连接并声明角色与权限。

sequenceDiagram
participant Client as "客户端/节点"
participant Gateway as "网关"
participant Adapter as "渠道适配器"
participant Provider as "消息平台"
Client->>Gateway : 连接握手(connect)
Gateway-->>Client : 连接成功(状态快照)
Gateway-->>Client : 推送事件(presence/tick)
Client->>Gateway : 请求(agent/send/...)
Gateway->>Adapter : 分发到对应渠道
Adapter->>Provider : 发送/接收消息
Provider-->>Adapter : 平台事件
Adapter-->>Gateway : 标准化消息
Gateway-->>Client : 返回结果/事件流

详细组件分析

渠道适配器架构

  • 共同特征
    • 认证与凭据管理:各渠道通过配置或环境变量提供凭据;部分渠道支持密钥管理(SecretRef)
    • 连接与重连:网关负责维持长连接与重连逻辑,避免重复会话
    • 消息路由:入站消息标准化为统一信封,出站消息根据会话键回送到原渠道
    • 会话隔离:私聊共享主会话,群组/频道/论坛主题保持独立会话
  • 多账户支持:各渠道支持多账号实例,可通过默认账号与账号级覆盖实现差异化策略
  • 配置写入:多数渠道允许通过命令或事件触发配置写入(需显式开启)

连接管理与生命周期

  • 连接建立:首次帧必须为connect;握手后请求/响应与事件推送
  • 认证:可选令牌认证(OPENCLAW_GATEWAY_TOKEN),节点需包含角色与权限声明
  • 重连与健康:网关维护心跳与健康检查,异常时自动重连
  • 远程访问:支持Tailscale Serve/Funnel或SSH隧道,配合令牌/密码认证

消息路由与状态同步

  • 确定性路由:回复总是回到消息来源渠道,模型不选择渠道
  • 会话键规则:私聊使用主会话键;群组/频道/论坛主题使用带标识的键
  • 状态同步:事件不重放,客户端断线后需刷新以重建状态

渠道特定实现概览

WhatsApp(Web)

  • 运行模型:网关拥有链接会话,忽略@status与@broadcast
  • 访问控制:默认DM策略为配对;群组支持允许列表与提及门控
  • 消息处理:媒体占位符、位置/联系人提取、未处理历史注入
  • 多账户:支持多账号实例与凭据路径
  • 故障排除:未链接、断开重连、无活动监听器、群消息被忽略等问题排查

Telegram(Bot API)

  • 运行模型:grammY Runner长轮询;Webhook可选;支持论坛主题
  • 访问控制:DM策略与群组策略分离;提及门控默认开启
  • 功能特性:实时预览流、HTML解析回退、内联按钮、贴纸动作、反应通知、投票
  • 限制与重试:文本分块、媒体上限、超时与网络不稳定处理
  • 故障排除:隐私模式、命令不可用、轮询/网络问题

Discord(Bot API)

  • 运行模型:官方网关;支持论坛/媒体频道;交互组件(buttons/selects/modals)
  • 访问控制:DM策略;公会策略(允许列表/开放/禁用);基于角色的代理路由
  • 功能特性:实时预览流、历史上下文、线程绑定会话、持久ACP绑定、反应通知、确认反应
  • 故障排除:意图权限、命令可见性、线程绑定与ACP会话

Signal(signal-cli)

  • 运行模型:通过HTTP JSON-RPC + SSE与signal-cli通信;设备模型(专用号码)
  • 访问控制:DM配对;群组策略;UUID/号码识别
  • 功能特性:打字指示、已读回执转发、反应动作、媒体限制、分块策略
  • 故障排除:守护进程可达性、DM被忽略、群消息被阻、配置校验

iMessage(legacy imsg)

  • 运行模型:通过stdio JSON-RPC与imsg通信;推荐新部署使用BlueBubbles
  • 访问控制:DM策略;群组策略;提及门控(正则)
  • 功能特性:附件与媒体、分块策略、远端附件抓取(SSH/SCP)
  • 故障排除:权限提示、DM被忽略、群消息被忽略、远端附件失败

自定义渠道开发指南

  • 适配器接口:遵循网关协议,实现connect/req/res/event帧交换
  • 认证与凭据:支持环境变量、SecretRef与多账户配置
  • 连接与重连:实现稳定的心跳与重连策略
  • 消息格式:输入标准化为统一信封,输出按渠道格式转换
  • 会话与路由:使用会话键规则,确保回复回到原渠道
  • 安全与配对:实现配对流程与白名单策略
  • 扩展机制:通过插件与技能扩展能力,遵循工具策略与沙箱配置

依赖关系分析

  • 渠道适配器依赖网关协议与配置中心,确保一致的认证、路由与会话行为
  • 客户端与节点通过WebSocket与网关交互,节点需声明角色与权限
  • 事件总线驱动各组件协作,确保状态一致性与可观测性
graph LR
GW["网关"] --> CFG["配置中心"]
GW --> ADAPTERS["渠道适配器集合"]
ADAPTERS --> PROVIDERS["消息平台API"]
CLIENTS["客户端/节点"] --> GW
GW --> EVT["事件总线"]
EVT --> CLIENTS

性能考虑

  • 连接复用:网关统一持有各渠道连接,避免重复会话与资源浪费
  • 会话隔离:按渠道/账号/对端隔离,减少并发冲突与状态竞争
  • 流式输出:Telegram/Discord支持实时预览流,提升用户体验
  • 媒体优化:图片压缩与大小限制,降低传输与渲染成本
  • 重试与降级:对外部API错误进行可恢复重试与降级策略

Web 聊天集成

WebChat 在本仓库中的定位是“网关 WebSocket 的聊天 UI”,不包含本地静态服务器或嵌入式浏览器,而是通过原生应用(macOS/iOS)或控制面板的聊天标签页直接连接到网关 WebSocket,复用相同的会话与路由规则,确保回复始终回到 WebChat。

graph TB
subgraph "客户端"
UI["WebChat 原生视图<br/>或 控制面板聊天标签"]
end
subgraph "网关"
WS["WebSocket 服务端"]
CHAT["聊天通道(chat.*)"]
AUTH["认证与授权"]
end
UI --> WS
WS --> CHAT
WS --> AUTH

核心组件

  • 网关 WebSocket 接口
    • chat.history:历史消息获取(受稳定性限制,可能截断长文本、省略重元数据)
    • chat.send:发送消息
    • chat.inject:向对话注入助手备注(无代理执行)
    • chat.abort:中止运行(保留部分输出可见)
    • 事件:chat、agent、presence、tick、health
  • 会话与路由
    • WebChat 使用与其它渠道一致的会话与路由规则;回复总是回到 WebChat
    • 默认主会话(main 或 global),支持切换
  • 认证与远程模式
    • 本地模式直连本地网关 WebSocket
    • 远程模式通过 SSH/Tailscale 隧道转发网关 WebSocket 控制端口
  • 媒体与自动回复
    • 自动回复心跳、媒体加载与优化、Web 入站/出站消息处理

架构总览

WebChat 的整体交互流程如下:客户端通过 WebSocket 连接到网关,使用 chat.* 方法进行历史拉取、消息发送与注入,同时订阅聊天事件以实现状态同步与实时更新。

sequenceDiagram
participant Client as "客户端(WebChat)"
participant WS as "网关 WebSocket"
participant Chat as "聊天通道"
participant Auth as "认证模块"
Client->>WS : 建立连接(携带 Origin/Token)
WS->>Auth : 校验认证(令牌/密码/反向代理)
Auth-->>WS : 认证结果
WS-->>Client : hello-ok
Client->>WS : chat.history(会话ID)
WS->>Chat : 查询历史
Chat-->>WS : 历史消息(可能截断/省略)
WS-->>Client : 历史消息
Client->>WS : chat.send(消息, 媒体, 投票)
WS->>Chat : 发送消息
Chat-->>WS : 确认
WS-->>Client : ack
WS-->>Client : 事件(chat/agent/presence/tick/health)
Client->>Client : 更新界面/状态

组件详解

WebSocket 连接与认证

  • 客户端连接时需设置 Origin 头,用于跨域与来源校验
  • 支持多种认证模式:令牌、密码、可信代理反向代理认证
  • 连接成功后收到 hello-ok,随后进入消息收发与事件订阅阶段

历史消息与状态同步

  • chat.history 从网关获取,受稳定性约束:长文本字段可能被截断、重元数据可能省略、超大条目替换为占位提示
  • chat.inject 可直接注入助手备注并广播至 UI(不触发代理执行)
  • 中止运行时,若存在缓冲输出,网关会持久化到历史并标记中止元数据;网关不可达时 UI 为只读

消息发送与媒体处理

  • 支持文本、媒体(图片等)、投票等消息类型
  • 媒体优化与加载由专用模块负责,确保传输效率与兼容性
  • 出站消息通过 sendMessageWhatsApp 调用,入站消息解析与占位符提取由 inbound 模块处理

会话与路由

  • WebChat 使用与其它渠道一致的会话与路由规则,回复总是回到 WebChat
  • 默认主会话(main 或 global),支持在 UI 中切换
  • 首次引导使用专用会话,避免与常规会话混淆

登录与会话生命周期

  • loginWeb 负责创建与等待 WhatsApp Web 连接,处理常见错误码(如 515 重启、登出)
  • 会话登录后保存凭据,后续发送无需重复扫码
  • 会话关闭前等待 Baileys 事件刷新,确保最终事件落盘

控制面板与工具面板

  • 控制面板的 Agents 工具面板通过 tools.catalog 获取运行时目录,标注 core 与 plugin:,并区分可选工具
  • 若 catalog 不可用,回退内置静态列表
  • 配置编辑影响展示与覆盖,但实际访问仍遵循策略优先级(allow/deny)

主题与响应式设计

  • UI 渲染层提供导航折叠、品牌区、状态指示等基础布局
  • 通过类名组合实现不同状态下的样式切换(如聊天焦点、导航折叠、引导态)

平台集成(macOS)

  • macOS 应用将 WebChat 视图为原生 SwiftUI 视图内嵌
  • 本地模式直连本地网关;远程模式通过 SSH 隧道转发控制端口
  • 日志子系统与分类便于调试

依赖关系分析

WebChat 的核心依赖围绕“网关 WebSocket + 会话/路由 + 认证 + 媒体处理”展开,模块间职责清晰、耦合度低,便于测试与扩展。

graph LR
Login["loginWeb<br/>登录与会话管理"] --> Session["createWaSocket/waitForWaConnection<br/>会话建立/等待"]
Session --> Outbound["sendMessageWhatsApp<br/>出站消息"]
Session --> Inbound["monitorWebInbox/extract*<br/>入站消息解析"]
Session --> Media["loadWebMedia/optimizeImageToJpeg<br/>媒体处理"]
Login --> Auth["认证配置(gateway.auth.*)"]
UI["WebChat UI"] --> WS["chat.history/chat.send/chat.inject<br/>事件(chat/agent/presence/tick/health)"]
WS --> Auth
WS --> Session

性能与可扩展性

  • 历史消息截断与元数据省略:chat.history 返回受限,避免内存与带宽压力
  • 媒体优化:图片 JPEG 优化与大小限制,降低传输成本
  • 事件驱动:chat/agent/presence/tick/health 事件按需推送,减少轮询开销
  • 远程隧道:SSH/Tailscale 隧道仅转发控制端口,降低网络复杂度
  • 可扩展点:工具目录 catalog 动态获取,支持插件生态扩展

安全与合规

  • 认证模式:支持令牌、密码、可信代理反向代理认证,满足不同部署场景
  • 远程模式:仅转发 WebSocket 控制端口,最小暴露面
  • Origin 校验:客户端连接时携带 Origin,防止跨域滥用
  • 会话隔离:默认主会话与首开引导会话分离,降低误操作风险
  • 平台侧:macOS 应用日志子系统与分类,便于审计与问题定位

故障排查

  • 连接失败
    • 检查网关认证配置(令牌/密码/可信代理)
    • 确认 Origin 设置正确
    • 查看 hello-ok 是否返回
  • 历史为空或被截断
    • 确认 chat.history 请求参数与会话 ID
    • 接受截断与省略策略,必要时调整消息长度
  • 媒体发送异常
    • 确认媒体尺寸与格式符合优化策略
    • 检查 loadWebMedia 与 optimizeImageToJpeg 流程
  • 登录问题
    • 错误码 515:会话重启后重试
    • 登出:清理缓存后重新扫码登录
  • 远程模式不可达
    • 检查 SSH/Tailscale 隧道是否建立
    • 确认网关端口与绑定地址

结论

WebChat 通过网关 WebSocket 提供统一的聊天体验,具备稳定的会话与路由、灵活的认证与远程模式、完善的事件驱动与媒体处理能力。其模块化设计便于扩展与维护,适合在多平台(macOS/iOS 原生视图、控制面板标签页)中复用同一套 UI 与协议。

附录:使用与定制指南

快速开始

  • 启动网关
  • 打开 WebChat UI(macOS/iOS 应用或控制面板聊天标签)
  • 确保网关认证已配置(即使本地回环也需认证)

配置参考(WebChat)

  • 无专用 webchat.* 配置块;WebChat 使用网关端点与认证设置
  • 关键项:gateway.port、gateway.bind、gateway.auth.、gateway.remote.

自定义开发建议

  • UI 层
    • 利用事件驱动更新界面,避免轮询
    • 导航折叠与品牌区可复用现有类名体系
  • 协议层
    • 严格遵循 chat.history/chat.send/chat.inject 语义
    • 对 chat.inject 的使用保持谨慎,避免与代理执行混淆
  • 认证层
    • 根据部署环境选择合适认证模式
    • Origin 校验与令牌/密码配置需一致
  • 媒体层
    • 使用优化后的 JPEG 与大小限制,提升传输效率
  • 平台集成
    • macOS 应用可参考 SwiftUI 内嵌视图与日志子系统

源码阅读地址