news 2026/5/8 11:25:13

【OpenClaw】源码剖析(四):Channel 与 Skills——连接 25+ 平台的适配魔法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【OpenClaw】源码剖析(四):Channel 与 Skills——连接 25+ 平台的适配魔法

OpenClaw 源码剖析(四):Channel 与 Skills——连接 25+ 平台的适配魔法

写在前面:前三篇我们拆完了 OpenClaw 的骨架(全局架构)、神经中枢(Gateway)和大脑(Agent Loop)。今天进入两个最"接地气"的子系统——ChannelSkills。Channel 解决的问题是:如何让同一个 AI 助手同时跑在 Telegram、Discord、微信、飞书、Slack、WhatsApp、iMessage 等 25+ 个平台上,而且消息不串、格式不错、能力不丢?Skills 解决的问题是:如何让 AI 助手的能力无限扩展,而不需要改一行框架代码?这两个系统看似独立,实则共享同一个设计哲学——适配器模式 + 插件化架构。理解了它们,你就理解了 OpenClaw 为什么能"一套框架,多个通道,无限技能"。


📑 文章目录

  • 📌 一、Channel 系统:25+ 平台,一套抽象
  • 🏗️ 二、三层架构:Agent → 抽象层 → 平台实现
  • 🪶 三、Dock vs Plugin:轻量注册与重量加载
  • 📨 四、消息管道:Inbound 与 Outbound 的完整旅程
  • 📊 五、平台能力矩阵:不是所有通道都生而平等
  • ⚡ 六、Skills 系统:AI 的"技能树"是怎么长的
  • 📦 七、SKILL.md 详解:一个技能的完整解剖
  • 🏪 八、ClawHub:从开发到发布的完整闭环
  • 🧩 九、源码导航
  • 🔮 十、系列预告

📌 一、Channel 系统:25+ 平台,一套抽象

1.1 问题的本质

让 AI 助手接入一个消息平台不难——写个 Telegram Bot,调几个 API,半天搞定。难的是接入 25+ 个平台,而且每个平台的 API 风格、消息格式、能力集、速率限制、认证方式都完全不同。如果每个平台都写一套独立的消息处理逻辑,代码会变成一个巨大的 if-else 地狱,维护成本指数级增长。

OpenClaw 的解法是经典的适配器模式(Adapter Pattern)——定义一套统一的 Channel 抽象接口,每个平台实现自己的适配器。上层代码(Gateway、Agent)只依赖抽象接口,不依赖任何平台特定代码。新增一个平台?写一个适配器,注册到 PluginRegistry,完事。

1.2 Channel 系统的设计目标

目标实现方式
平台无关统一的 ChannelPlugin 接口,上层代码零平台依赖
按需加载Dock 轻量注册 + Plugin 懒加载,不用的平台不占内存
能力声明capabilities 显式声明每个平台支持什么,Agent 据此调整行为
安全隔离每个 Channel 有独立的 allowlist、mention 规则、DM 策略
热插拔通道可以运行时启停,不影响其他通道

🏗️ 二、三层架构:Agent → 抽象层 → 平台实现

OpenClaw 的 Channel 系统采用经典的三层架构,每一层都有明确的职责边界:

2.1 顶层:Agent / LLM 层

这是消息的"消费者"。Agent Loop 接收到标准化的MsgContext后,不关心消息来自哪个平台——它只看到一个统一的对话上下文。同样,Agent 生成回复时,也不需要知道回复会发到哪个平台——它只输出标准文本,由下层负责格式化。

这种设计的好处是显而易见的:Agent 的代码完全不需要if (platform === 'telegram')这样的分支判断。你换一个平台,Agent 的行为完全不变。

2.2 中间层:Channel 抽象层

这是整个系统的"翻译官"。它定义了三个核心抽象:

  • ChannelPlugin 接口:每个平台必须实现的标准方法集(outbound、security、status 等)
  • MsgContext:统一的消息上下文,封装了文本、媒体、元信息、平台 ID
  • ChannelOutboundAdapter:出站消息的统一发送接口,处理分块、格式化、发送

抽象层还负责"能力协商"——通过capabilities字段,每个平台声明自己支持什么(DM、群组、线程、反应、图片、音频、文档、投票、流式输出)。Agent 在生成回复时,会参考这些能力来决定输出格式。比如,如果平台不支持流式输出,Agent 就不会尝试逐 token 推送。

2.3 底层:平台实现层

每个平台一个独立模块,实现 ChannelPlugin 接口。这是唯一需要处理平台特定逻辑的地方——Telegram 用 grammY、Discord 用 discord.js、WhatsApp 用 Baileys、Slack 用 Bolt SDK、iMessage 用 BlueBubbles、Signal 用 signal-cli、飞书用 WebSocket API。

每个平台实现都像一个"翻译官"——把平台特定的 API 调用翻译成统一的 MsgContext,把统一的 SendContext 翻译成平台特定的 API 调用。


🪶 三、Dock vs Plugin:轻量注册与重量加载

这是 OpenClaw Channel 系统中最精妙的设计之一——两级加载策略

3.1 为什么需要两级加载?

想象一下:你有 25 个 Channel 配置,但用户只启用了 Telegram 和 Discord。如果启动时就把所有 25 个平台的 SDK 都加载进来,不仅浪费内存(WhatsApp 的 Baileys 就很重),还会拖慢启动速度。OpenClaw 的解法是:先注册元信息(Dock),再按需加载实现(Plugin)

3.2 Dock:轻量注册

Dock(src/channels/dock.ts)在 Gateway 启动时运行,只注册每个通道的元信息:

// Dock 注册的内容(极轻量){id:'telegram',label:'Telegram',capabilities:{chatTypes:['direct','group'],threads:true,reactions:true,...},allowlistFormat:'comma-separated',mentionRules:{groupRequireMention:true},threadingDefaults:{enabled:true}}

Dock 不加载任何 SDK,不建立任何连接。它的唯一目的是让 Gateway 知道"有这个通道可用",以便在配置界面显示、在路由时查找。类比:电话簿里的名字——知道谁在,但不拨号。

3.3 Plugin:重量加载

Plugin(src/channels/plugins/*)在通道实际启动时才加载,包含完整的 ChannelPlugin 实现:

// Plugin 实现的内容(完整功能)interfaceChannelPlugin{meta:{id,label,selectionLabel,docsPath,blurb,aliases};capabilities:{chatTypes,media,threads,reactions};config:{listAccountIds,resolveAccount};outbound:{deliveryMode,sendText,sendMedia};setup?:SetupWizard;// 可选:配置向导security?:SecurityPolicy;// 可选:安全策略status?:HealthChecker;// 可选:健康检查gateway?:GatewayManager;// 可选:Gateway 守护进程mentions?:MentionHandler;// 可选:@提及处理threading?:ThreadingHandler;// 可选:线程管理streaming?:StreamingHandler;// 可选:流式输出actions?:MessageActions;// 可选:按钮/卡片}

Plugin 通过 PluginRegistry 注册,支持懒加载和缓存:

// 懒加载 + 缓存exportasyncfunctionloadChannelPlugin(id:ChannelId){constcached=cache.get(id);if(cached)returncached;// 命中缓存直接返回constentry=registry.channels.find(e=>e.plugin.id===id);if(entry){cache.set(id,entry.plugin);// 缓存供下次使用returnentry.plugin;}returnundefined;}

缓存会在 PluginRegistry 变更时自动失效(比如热重载),确保开发时的体验流畅。


📨 四、消息管道:Inbound 与 Outbound 的完整旅程

4.1 Inbound:平台事件 → Agent

每条消息从平台到达 Agent,都要经过一条标准化的管道:

Platform Event → Monitor/Handler → Normalize → Gate → Dispatch → Agent Loop

Step 1: Monitor/Handler— 平台特定的事件监听器捕获原始事件(Telegram Update、Discord Message Create 等)。

Step 2: Normalize— 将平台特定的事件格式转换为统一的MsgContext。这是适配器最核心的工作——提取文本内容、解析媒体附件、统一用户 ID 格式、识别消息类型(DM/群组/频道)。

Step 3: Gate— 三道安全门:

  • AllowList 检查:该用户/群组是否在白名单内?
  • Mention 检查:群组消息是否 @了机器人?(群组默认需要 @才响应)
  • Command 检查:是否是斜杠命令?(如/help/skill

Step 4: Dispatch— 通过resolveRoute确定目标 Agent 和 SessionKey,然后通过 Lane Queue 串行化投递(第二篇讲过的)。

4.2 Outbound:Agent 回复 → 平台

Agent 生成回复后,出站管道同样标准化:

Agent Response → resolveTarget → chunk text → format → send

Step 1: resolveTarget— 解析目标地址。每个平台的地址格式不同:Telegram 用telegram:<chatId>,Discord 用 Snowflake ID,WhatsApp 用 E.164 JID,Slack 用 Channel ID。

Step 2: chunk text— 将长文本按平台限制分块。Telegram 单条消息上限 4096 字符,Discord 2000 字符,WhatsApp 65536 字符。分块逻辑会尽量在句子边界切分,保持语义完整。

Step 3: format— 平台特定的格式化。Telegram 支持 MarkdownV2,Discord 支持 Markdown,WhatsApp 支持简单的加粗和斜体,Slack 有自己的 mrkdwn 格式。格式化器会做必要的转义和降级。

Step 4: send— 调用平台 API 发送。这里有三种投递模式:

模式说明使用平台
direct进程内直接调用 APITelegram、Discord、Slack、Signal、iMessage
gateway通过 Gateway 守护进程路由WhatsApp(Baileys 在 Gateway 内运行)
hybrid先 direct,失败回退 gateway预留,未来使用

WhatsApp 使用 gateway 模式是因为 Baileys(无头 WhatsApp Web)运行在 Gateway 守护进程内,出站消息必须通过它路由,而不是独立发起 API 调用。


📊 五、平台能力矩阵:不是所有通道都生而平等

这是 Channel 系统中最容易被忽视、却最影响用户体验的设计——能力声明(Capabilities)。每个平台支持的功能集差异巨大,OpenClaw 通过capabilities字段显式声明这些差异,Agent 据此调整行为。

5.1 关键能力差异

能力影响范围差异示例
线程回复是否以线程形式组织Telegram/Discord/Slack/飞书支持;WhatsApp/Signal/iMessage 不支持
反应用户能否对消息加表情大部分支持;iMessage 仅 Tapback(有限)
流式输出Agent 能否逐 token 推送Telegram 支持(编辑消息);WhatsApp/Signal 不支持
投票能否创建投票仅 Discord 和 WhatsApp 原生支持
媒体上限文件大小限制飞书 20MB > WhatsApp/iMessage 16MB > Telegram 5MB

5.2 Agent 如何适配能力差异

Agent 在生成回复时,会检查当前通道的 capabilities:

  • 不支持线程→ 所有回复以平铺消息发送,不使用 reply_to
  • 不支持流式→ 等完整回复生成后一次性发送,不做逐 token 推送
  • 媒体超限→ 自动压缩或转为链接分享
  • 不支持投票→ 用文本列表替代原生投票组件

这种"能力协商"的设计,确保了 AI 助手在每个平台上的体验都是该平台上的最佳体验,而不是"最低公分母"体验。


⚡ 六、Skills 系统:AI 的"技能树"是怎么长的

如果说 Channel 是 OpenClaw 的"手"(连接外部世界),那 Skills 就是 OpenClaw 的"技能"(决定能做什么)。Skills 系统的设计哲学和 Channel 一脉相承——插件化、声明式、按需加载

6.1 什么是 Skill?

Skill 是一个自包含的能力单元,由一个SKILL.md文件和可选的支撑脚本组成。它定义了 AI 助手的一项新能力——可以是"搜索网页"、“生成图片”、“操作 GitHub”、“发送邮件”、"转换文件格式"等任何你能想到的事情。

关键设计决策:Skill 不是代码插件,而是提示词插件。SKILL.md 告诉 AI “你能做什么、怎么做”,AI 通过已有的工具(bash、read_file、write_file 等)来执行。这意味着你不需要写复杂的 TypeScript 插件代码,只需要写一份清晰的 Markdown 说明文件。

6.2 Skill 的三层优先级

OpenClaw 的 Skill 加载遵循严格的三层优先级:

优先级位置说明
最高~/.openclaw/skills/用户自定义技能,覆盖一切
ClawHub 安装的技能社区技能,openclaw skill install安装
最低src/skills/OpenClaw 内置 49 个技能

如果用户自定义了一个与内置技能同名的 Skill,自定义版本会覆盖内置版本。这让用户可以轻松定制 AI 的行为,而不需要修改框架代码。

6.3 Skill 的生命周期

一个 Skill 从创建到被 Agent 使用,经历四个阶段:

1. 发现(Discover)— Gateway 启动时扫描技能目录,读取所有 SKILL.md,构建技能索引。技能快照在会话创建时固化——如果你在会话中途添加了新技能,需要重启会话才能生效。

2. 加载(Load)— 会话创建时,buildSkillsSection()将所有活跃技能的摘要信息拼装到 System Prompt 中。注意:这里只加载摘要,不加载完整内容,以节省 token。

3. 触发(Trigger)— Agent 在推理时,根据 System Prompt 中的技能描述,决定是否使用某个技能。触发方式有两种:

  • 斜杠命令:用户输入/weather 北京,直接触发 weather 技能
  • 自然语言:用户说"北京今天天气怎么样",Agent 自主判断应该调用 weather 技能

4. 执行(Execute)— Agent 读取 SKILL.md 的完整内容(通过read_file工具),按照其中的指令调用支撑脚本或工具。执行在沙箱中进行,受 Tool Policy 约束。


📦 七、SKILL.md 详解:一个技能的完整解剖

一个完整的 SKILL.md 包含以下 Section:

--- name: notebook-to-docx description: 将 Jupyter Notebook 转换为 Word 文档 trigger: /notebook-to-docx <notebook_path> --- # Notebook to DOCX 将 .ipynb 文件转换为格式化的 .docx 文档。 ## Features - 保留 Markdown 单元格的格式(标题、列表、链接、图片) - 代码单元格带语法高亮 - 输出单元格(文本、图片、表格)完整保留 - 自动生成目录 ## Usage 当用户要求转换 notebook 时,运行以下命令: \`\`\`bash python3 ~/.openclaw/skills/notebook-to-docx/notebook_to_docx.py <notebook_path> \`\`\` ## Requirements - Python 3.10+ - pip install nbformat python-docx pygments ## Notes - 输出文件默认与输入文件同目录 - 大型 notebook(>50MB)可能需要较长时间

7.1 Front Matter(元信息)

---包裹的 YAML 头部,定义技能的元信息:名称、描述、触发命令。这些信息会被buildSkillsSection()提取并注入 System Prompt,让 Agent 知道"有这个技能可用"。

7.2 正文(指令)

Markdown 正文是给 AI 看的"操作手册"。它告诉 AI:

  • 什么时候用:触发条件(用户要求转换 notebook)
  • 怎么用:具体命令(运行 Python 脚本)
  • 依赖什么:前置条件(Python 3.10+、pip 包)
  • 注意事项:边界情况(大型文件可能耗时)

7.3 支撑脚本

SKILL.md 可以引用同目录下的脚本文件(Python、Shell 等)。这些脚本在沙箱中执行,受 Tool Policy 约束。脚本负责实际的业务逻辑——调用 API、处理文件、执行计算等。


🏪 八、ClawHub:从开发到发布的完整闭环

ClawHub 是 OpenClaw 的官方技能市场,托管了 5700+ 个社区技能。它提供了从开发到发布的完整闭环:

8.1 开发流程

1. 创建技能目录:mkdir -p ~/.openclaw/skills/my-skill 2. 编写 SKILL.md:描述技能的功能、用法、依赖 3. 编写支撑脚本:实现具体业务逻辑 4. 本地测试:重启会话,用斜杠命令或自然语言触发

8.2 发布流程

1. 认证:clawhub auth login 2. 发布:clawhub publish ~/.openclaw/skills/my-skill 3. 审核:社区审核(自动 + 人工) 4. 上线:其他用户可以搜索和安装

8.3 安装流程

1. 搜索:openclaw skill search weather 2. 安装:openclaw skill install weather-forecast 3. 更新:openclaw skill update --all 4. 列表:openclaw skill list

8.4 安全考量

ClawHub 的技能是社区贡献的,OpenClaw 采取了多层安全措施:

  • 沙箱隔离:所有技能脚本在 Docker 沙箱中执行,无法访问宿主机的文件系统
  • Tool Policy:技能只能使用 Tool Policy 允许的工具
  • 元信息门控:SKILL.md 中可以声明需要的权限,用户在安装时可以看到
  • 社区审核:ClawHub 有自动化的安全扫描和人工审核流程
  • 用户控制:用户可以随时卸载技能,也可以覆盖社区技能

🧩 九、源码导航

Channel 核心文件

文件职责
src/channels/dock.ts轻量级 Dock 注册,定义通道元信息
src/channels/plugins/index.tsPluginRegistry,管理所有通道插件
src/channels/plugins/telegram/Telegram 适配器(grammY)
src/channels/plugins/discord/Discord 适配器(discord.js)
src/channels/plugins/whatsapp/WhatsApp 适配器(Baileys)
src/channels/plugins/slack/Slack 适配器(Bolt SDK)
src/channels/plugins/signal/Signal 适配器(signal-cli)
src/channels/plugins/bluebubbles/iMessage 适配器(BlueBubbles)
src/channels/plugins/feishu/飞书适配器(WebSocket API)
src/gateway/server-channels.tsChannel 生命周期管理(启停/状态)

Skills 核心文件

文件职责
src/agents/system-prompt.tsbuildSkillsSection()构建技能提示词
src/agents/skills/技能快照、提示词构建
src/skills/内置 49 个技能
src/plugins/registry.ts插件注册中心(含技能注册)
~/.openclaw/skills/用户自定义技能目录

🔟 十、系列预告

第五篇(也是最后一篇),我们将拆解 OpenClaw 的记忆与安全系统:

核心问题
Memory 的分层架构(短期/长期/工作记忆)是如何设计的?
MemoryIndexManager 如何用 SQLite + sqlite-vec 实现混合 BM25+向量检索?
PRISM 安全层如何实现零 Fork 的运行时安全防护?
生产部署的最佳实践有哪些?

关注我,不要错过最终篇!


🎁 总结速查卡

Channel 核心概念

概念一句话解释
三层架构Agent 层(消费)→ 抽象层(翻译)→ 平台层(实现)
Dock轻量注册元信息,Gateway 启动时加载,不占内存
Plugin重量加载完整实现,通道启动时懒加载,缓存复用
MsgContext统一消息上下文,封装平台差异
Capabilities能力声明,Agent 据此调整行为
三种投递模式direct(进程内)/ gateway(守护进程)/ hybrid(预留)

Skills 核心概念

概念一句话解释
SKILL.md技能的"身份证+操作手册",Markdown 格式
提示词插件Skill 不是代码插件,而是告诉 AI 怎么用现有工具
三层优先级用户自定义 > ClawHub 安装 > 内置
四阶段生命周期发现 → 加载 → 触发 → 执行
ClawHub官方技能市场,5700+ 社区技能
沙箱隔离技能脚本在 Docker 中执行,受 Tool Policy 约束

一句话总结

Channel 用适配器模式抹平了 25+ 平台的差异,Skills 用提示词插件实现了能力的无限扩展。两者共享同一个设计哲学——框架只定义契约,具体实现交给插件。这就是 OpenClaw "一套框架,多个通道,无限技能"的魔法所在。


参考链接

  • OpenClaw GitHub 仓库
  • OpenClaw Channel 插件开发文档
  • OpenClaw ClawHub 文档
  • Avasdream: Channel & Messaging Deep Dive
  • Datacamp: Building Custom OpenClaw Skills
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 11:24:52

终极RedwoodJS性能优化指南:服务器端渲染与静态生成实战技巧

终极RedwoodJS性能优化指南&#xff1a;服务器端渲染与静态生成实战技巧 【免费下载链接】redwood RedwoodGraphQL 项目地址: https://gitcode.com/gh_mirrors/re/redwood RedwoodJS作为现代全栈框架&#xff0c;提供了强大的服务器端渲染&#xff08;SSR&#xff09;和…

作者头像 李华
网站建设 2026/5/8 11:23:46

实战复盘:Claude Code 到底谁能用?程序员与学生场景全解

最近在 se.zzmax.cn 上直接跑 Claude 各型号处理日常开发任务&#xff0c;发现一个很现实的问题&#xff1a;不少同学装完 Claude Code 后&#xff0c;并不清楚它到底适不适合自己&#xff0c;结果用两次就吃灰了。其实&#xff0c;Claude Code 并不是“所有人上来都能爽”的工…

作者头像 李华
网站建设 2026/5/8 11:21:16

Anse会话管理技巧:如何高效保存和管理你的AI对话记录

Anse会话管理技巧&#xff1a;如何高效保存和管理你的AI对话记录 【免费下载链接】anse Supercharged experience for multiple models such as ChatGPT, DALL-E and Stable Diffusion. 项目地址: https://gitcode.com/gh_mirrors/an/anse Anse作为一款支持多模型的AI交…

作者头像 李华
网站建设 2026/5/8 11:20:49

Arduino电源管理库:低功耗物联网设备开发实战

1. Arduino电源管理库深度解析作为一名长期从事嵌入式开发的工程师&#xff0c;我最近在几个物联网项目中使用了Arduino新推出的电源管理库&#xff0c;实测效果远超预期。这个专为Arduino Pro模块设计的库&#xff0c;真正解决了电池供电设备的核心痛点——功耗优化。让我带你…

作者头像 李华
网站建设 2026/5/8 11:20:49

AMDVLK性能调优指南:10个关键设置优化游戏和图形应用

AMDVLK性能调优指南&#xff1a;10个关键设置优化游戏和图形应用 【免费下载链接】AMDVLK AMD Open Source Driver For Vulkan 项目地址: https://gitcode.com/gh_mirrors/am/AMDVLK AMDVLK作为AMD开源的Vulkan驱动程序&#xff0c;为游戏玩家和图形应用开发者提供了强大…

作者头像 李华