上一篇我们看完了地基——应用如何被组装、任务如何被托管。从这一篇开始,进入全系列的「主线剧情」:一条用户消息从 IM 平台进来、到机器人回复发出去的全过程。第一站是平台层(pkg/platform),它要解决一个看似简单实则棘手的问题:让 QQ、微信、Discord、Telegram 这 18+ 个长相完全不同的平台,在 LangBot 内部说同一种「语言」。

一、这一层解决什么问题

每个 IM 平台的消息格式、事件模型、回复方式都不一样:QQ 有「群/私聊」,Discord 有「频道/DM」,企业微信还有「客服会话」。如果让上层的流水线直接面对这种差异,代码会瞬间失控。

平台层的职责就是做一层归一化:

  1. 入站归一——把各平台五花八门的消息事件,统一成 FriendMessage / GroupMessage 等标准事件,再进一步抽成统一的 Query 对象。
  2. 路由——根据可配置的规则,决定「这条消息该交给哪条流水线处理」。
  3. 出站归一——上层只管产出一个 MessageChain(消息链),由适配器负责翻译成具体平台的 API 调用。

这一层的核心抽象有两个:管理所有机器人的 PlatformManager,和代表单个机器人运行实例的 RuntimeBot。

二、核心抽象

2.1 适配器:来自外部 SDK 的统一契约

值得先点明一件事:平台适配器的抽象基类 AbstractMessagePlatformAdapter 并不在 LangBot 主仓库里,而是来自外部的 langbot-plugin SDK(第一篇提过的那个被精确钉版本的独立仓库):

# src/langbot/pkg/platform/botmgr.py:20
import langbot_plugin.api.entities.builtin.provider.session as provider_session
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter

这是一个重要的架构决策:消息实体(事件、消息链、会话类型)和适配器契约都定义在 SDK 里,这样插件、适配器、主程序三方共享同一套数据模型,不会各说各话。LangBot 主仓库里的适配器实现则放在 src/langbot/pkg/platform/sources/ 下,每个平台一个文件。

适配器统一约定了几个关键方法(由 SDK 定义、各平台实现):

2.2 PlatformManager:机器人注册表

PlatformManager(botmgr.py:402)是平台层的总管,挂在「上帝对象」ap 上。它干三件事: