上一篇我们看完了地基——应用如何被组装、任务如何被托管。从这一篇开始,进入全系列的「主线剧情」:一条用户消息从 IM 平台进来、到机器人回复发出去的全过程。第一站是平台层(
pkg/platform),它要解决一个看似简单实则棘手的问题:让 QQ、微信、Discord、Telegram 这 18+ 个长相完全不同的平台,在 LangBot 内部说同一种「语言」。
每个 IM 平台的消息格式、事件模型、回复方式都不一样:QQ 有「群/私聊」,Discord 有「频道/DM」,企业微信还有「客服会话」。如果让上层的流水线直接面对这种差异,代码会瞬间失控。
平台层的职责就是做一层归一化:
FriendMessage / GroupMessage 等标准事件,再进一步抽成统一的 Query 对象。MessageChain(消息链),由适配器负责翻译成具体平台的 API 调用。这一层的核心抽象有两个:管理所有机器人的 PlatformManager,和代表单个机器人运行实例的 RuntimeBot。
值得先点明一件事:平台适配器的抽象基类 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 定义、各平台实现):
run_async()——连接平台、进入事件循环监听消息。register_listener(event_type, callback)——注册某类事件的回调。reply_message(...) / send_message(...)——把回复发回平台。kill()——断开连接。PlatformManager(botmgr.py:402)是平台层的总管,挂在「上帝对象」ap 上。它干三件事: