生成模型:Claude Opus 4.6 (anthropic/claude-opus-4-6) Token 消耗:输入 ~280,000 tokens,输出 ~20,000 tokens(本章合计)
OpenClaw 的核心价值之一是统一收件箱——无论消息来自 WhatsApp、Telegram、Discord 还是 Slack,Gateway 都能以统一的方式处理。要实现这一点,首先需要一个通道注册表(Channel Registry)来管理所有已知的消息通道。本节分析注册表的设计和通道能力声明机制。
src/channels/registry.ts 定义了 OpenClaw 的核心通道列表和元数据。
// src/channels/registry.ts
export const CHAT_CHANNEL_ORDER = [
"telegram",
"whatsapp",
"discord",
"googlechat",
"slack",
"signal",
"imessage",
] as const;
export type ChatChannelId = (typeof CHAT_CHANNEL_ORDER)[number];
export const DEFAULT_CHAT_CHANNEL: ChatChannelId = "whatsapp";
CHAT_CHANNEL_ORDER 不仅定义了所有核心通道的 ID,还通过数组顺序决定了它们在 UI 中的显示优先级——Telegram 排在最前面,因为它是"最简单的入门方式"。
每个通道都附带一份元数据(ChannelMeta),描述其显示名称、文档路径和简介:
为了用户输入的便利性,注册表支持通道别名:
这样用户在配置或命令行中输入 imsg、google-chat 或 gchat 都能被正确识别。normalizeChannelId() 函数统一处理这种映射:
对于通过插件系统注册的外部通道(如 Microsoft Teams、Matrix 等),normalizeAnyChannelId() 会进一步查询插件注册表:
每个通道的功能不尽相同——Telegram 支持原生斜杠命令,WhatsApp 支持投票和反应表情,Discord 支持线程——OpenClaw 通过能力声明(Channel Capabilities)让 Gateway 知道每个通道能做什么。
能力声明定义在通道的 Dock 层(详见 6.1.3)中:
Gateway 在处理消息时会检查目标通道的能力。例如,如果通道不支持 reactions,就不会尝试发送确认反应;如果不支持 threads,就不会在回复中包含线程相关的上下文。
14.1.3 通道 Dock 层
Dock(停靠层)是 OpenClaw 对通道行为的轻量级抽象。它在注册表和具体通道实现之间提供了一个统一的适配接口,使得共享代码(如消息分发、路由、命令处理)可以不依赖具体通道的重量级实现。
src/channels/dock.ts 中的 ChannelDock 类型定义了 Dock 的完整接口:
每个核心通道都在 DOCKS 对象中注册了自己的 Dock。以 WhatsApp 为例:
textChunkLimit 的值因通道而异:
对于通过插件系统注册的外部通道,buildDockFromPlugin() 函数会自动从插件的属性中构建 Dock:
listChannelDocks() 函数将核心通道和插件通道合并,按优先级排序后返回:
设计哲学:Dock 层的注释中强调了"保持轻量"的原则——不引入监控、Web 登录、Puppeteer 等重量级依赖。这是因为 Dock 层会被 Gateway 的各个子系统广泛引用,如果它间接加载了具体通道的全部实现,就会导致不必要的内存开销和启动延迟。具体通道的重量级逻辑应该放在各自的插件模块中。
OpenClaw 的通道注册表体系有以下核心特点:
双层注册:核心通道硬编码在 CHAT_CHANNEL_ORDER 中,外部通道通过插件注册表动态注册,两者最终合并为统一的列表
能力声明:每个通道显式声明自己支持的功能(聊天类型、反应、投票、线程等),Gateway 据此决定可用的交互方式
轻量 Dock 层:在注册表和具体实现之间提供统一的行为适配接口,保持共享代码路径不依赖重量级通道实现
别名系统:支持用户输入的多种缩写形式,降低配置门槛
下一节分析入站消息如何通过 Gateway 的处理流水线——从原始通道消息到统一的内部格式。