一、问题的提出

OpenClaw 支持多种 IM 通道(微信、QQ、Telegram),它们共享同一个 AI 引擎,但通信协议和认证方式完全不同。一个自然的疑问是:

微信 Bot 是怎么和微信服务器通信的?登录票据存在哪里?消息是怎么流转的?和 QQBot 有什么区别?

本文从源码出发,完整拆解微信 Bot 的通信链路,并与 QQBot 进行对比。

二、整体架构

2.1 微信 Bot 通信架构

消息流转步骤

  1. 用户发消息 — 微信 App 发送消息到微信服务器
  2. 长轮询拉取 — 微信插件通过 HTTP 长轮询 (getUpdates) 从服务器拉取新消息
  3. 消息解析 — 插件解析消息格式,提取发送者、内容、附件等
  4. 会话路由 — Gateway 根据「通道 + 用户」匹配或创建对应的 Session
  5. AI 推理 — Session 加载 workspace 上下文,调用 GLM-5 生成回复
  6. 格式转换 — 插件将 Markdown 回复转为纯文本(微信不支持 Markdown)
  7. 发送回复 — 通过 HTTP POST (sendMessage) 将回复发回微信服务器
  8. 用户收到 — 微信 App 收到 Bot 回复
flowchart TB
    subgraph User["① 用户侧"]
        WXApp["📱 微信 App"]
    end

    subgraph WeChat["② 微信服务端"]
        ILINK["ilinkai.weixin.qq.com"]
    end

    subgraph Local["③ 本地 OpenClaw"]
        subgraph PluginLayer["插件层"]
            WXPlugin["微信插件
openclaw-weixin"] end subgraph CoreLayer["核心层"] GW["Gateway
会话路由"] Session["Session Manager
上下文管理"] end subgraph ModelLayer["模型层"] Model["GLM-5
AI 推理"] end end WXApp -- "❶ 用户发消息" --> ILINK ILINK -- "❷ getUpdates 长轮询" --> WXPlugin WXPlugin -- "❸ 消息解析" --> GW GW -- "❹ 会话路由" --> Session Session -- "❺ AI 推理" --> Model Model -- "❻ 生成回复" --> Session Session -- "❼ 路由回复" --> GW GW -- "❽ 交付消息" --> WXPlugin WXPlugin -- "❾ 格式转换
Markdown → 纯文本" --> WXPlugin WXPlugin -- "❿ sendMessage
HTTP POST" --> ILINK ILINK -- "⓫ 投递回复" --> WXApp style User fill:#228B22,color:#fff style WeChat fill:#B22222,color:#fff style PluginLayer fill:#E65100,color:#fff style CoreLayer fill:#1565C0,color:#fff style ModelLayer fill:#5E35B1,color:#fff

2.2 QQBot 通信架构

消息流转步骤

  1. 用户发消息 — QQ App 发送消息到 QQ 服务器
  2. WebSocket 推送 — QQ 服务器通过 WebSocket 实时推送事件到插件
  3. 事件解析 — 插件解析 C2C_MESSAGE_CREATE 等事件,提取消息内容
  4. 会话路由 — Gateway 根据「通道 + 用户」匹配或创建对应的 Session
  5. AI 推理 — Session 加载 workspace 上下文,调用 GLM-5 生成回复
  6. 格式保持 — QQBot 支持原生 Markdown,无需格式转换
  7. 发送回复 — 通过 HTTP REST API 将 Markdown 回复发回 QQ 服务器
  8. 用户收到 — QQ App 收到 Bot 回复(支持流式显示)
flowchart TB
    subgraph User["① 用户侧"]
        QQApp["📱 QQ App"]
    end

    subgraph QQ["② QQ 服务端"]
        QQAPI["bots.qq.com
Bot API"] QQWS["WebSocket
Gateway"] end subgraph Local["③ 本地 OpenClaw"] subgraph PluginLayer["插件层"] QQPlugin["QQBot 插件
openclaw-qqbot"] end subgraph CoreLayer["核心层"] GW["Gateway
会话路由"] Session["Session Manager
上下文管理"] end subgraph ModelLayer["模型层"] Model["GLM-5
AI 推理"] end end QQApp -- "❶ 用户发消息" --> QQAPI QQAPI -- "❷ WebSocket 推送
C2C_MESSAGE_CREATE" --> QQWS QQWS -- "❸ 实时事件流" --> QQPlugin QQPlugin -- "❹ 事件解析" --> GW GW -- "❺ 会话路由" --> Session Session -- "❻ AI 推理" --> Model Model -- "❼ 生成回复" --> Session Session -- "❽ 路由回复" --> GW GW -- "❾ 交付消息" --> QQPlugin QQPlugin -- "❿ POST
/v2/users/:openid/messages
(原生 Markdown)" --> QQAPI QQAPI -- "⓫ 投递回复" --> QQApp style User fill:#228B22,color:#fff style QQ fill:#5E35B1,color:#fff style PluginLayer fill:#E65100,color:#fff style CoreLayer fill:#1565C0,color:#fff style ModelLayer fill:#5E35B1,color:#fff

2.3 架构差异速览

维度微信 BotQQBot
消息接收HTTP 长轮询 (getUpdates)WebSocket 实时推送
消息发送HTTP POST (sendMessage)HTTP REST API
认证方式扫码授权 → Bot TokenappId + clientSecret → access_token
票据类型长期有效,手动刷新有效期约 2 小时,自动刷新
协议基础iLink 私有协议QQ Bot 开放平台 API
连接模式无状态,每次请求独立WebSocket 持久连接 + HTTP 发送

三、登录与授权

3.1 微信 Bot 登录流程

微信 Bot 采用扫码授权模式,用户需要用微信扫描二维码完成 Bot 的身份绑定。

sequenceDiagram
    participant CLI as OpenClaw CLI
    participant Plugin as 微信插件
    participant WX as ilinkai.weixin.qq.com
    participant App as 微信 App

    CLI->>Plugin: openclaw channels login
--channel openclaw-weixin Plugin->>WX: GET ilink/bot/get_bot_qrcode?bot_type=3 WX-->>Plugin: {qrcode, qrcode_img_content} Plugin-->>CLI: 显示二维码 + 扫码链接 Note over CLI,App: 二维码有效期 5 分钟 App->>WX: 扫码 → 确认授权 Plugin->>WX: GET ilink/bot/get_qrcode_status
(长轮询 35s) WX-->>Plugin: {status: "scaned"} Plugin->>WX: 继续轮询 WX-->>Plugin: {status: "confirmed",
bot_token, ilink_bot_id,
baseurl, ilink_user_id} Plugin->>Plugin: 保存凭据到
~/.openclaw/openclaw-weixin/accounts/ Plugin-->>CLI: 登录成功 ✅

关键参数说明

参数说明
bot_type=3iLink Bot 类型标识
qrcode服务端生成的会话标识(非二维码图片本身)
bot_token授权后获得的 API 调用凭证
ilink_bot_idBot 的唯一标识(如 863fc8fa1527-im-bot
ilink_user_id授权用户的微信 ID
baseurlAPI 基础 URL(可能因 IDC 调度而变化)

3.2 QQBot 登录流程

QQBot 采用 appId + clientSecret 配置模式,无需扫码。

sequenceDiagram
    participant Config as 配置文件
    participant Plugin as QQBot 插件
    participant API as bots.qq.com

    Config->>Plugin: 读取 appId + clientSecret
    Plugin->>API: POST /app/getAppAccessToken
{appId, clientSecret} API-->>Plugin: {access_token, expires_in: 6022} Plugin->>Plugin: 缓存 Token
启动后台刷新 Plugin->>API: GET /gateway
Authorization: Bearer {token} API-->>Plugin: {url: wss://...} Plugin->>API: WebSocket 连接
Identify + Intents API-->>Plugin: Ready Event ✅ Note over Plugin,API: Token 约 2 小时过期
插件自动后台刷新

3.3 登录方式对比

对比项微信 BotQQBot
初始化方式扫码授权配置文件写入 appId + Secret
用户交互需要手机扫码无需用户操作
凭据获取服务端下发 bot_token客户端换取 access_token
凭据有效期长期有效(直到被撤销)~2 小时,需定期刷新
多账号支持多次扫码,每个一个 token多组 appId + Secret

3.4 跨通道协作:QQBot 渲染微信登录二维码

在 OpenClaw 2026.3.24 中,一个有趣的跨通道协作场景成为可能:通过 QQBot 完成微信 Bot 的扫码登录

传统流程要求用户在终端执行 openclaw channels login --channel openclaw-weixin,然后查看终端中的 ASCII 二维码或复制链接到浏览器。但当用户不方便访问终端时(比如只有手机),这个流程就不太友好。

借助 OpenClaw 的跨通道能力,AI Agent 可以:

sequenceDiagram
    participant User as 用户 (QQ)
    participant QQ as QQBot
    participant AI as OpenClaw Agent
    participant CLI as 本地 CLI
    participant WX as 微信服务器

    User->>QQ: 帮我登录微信 Bot
    QQ->>AI: 路由消息
    AI->>CLI: exec: openclaw channels login
--channel openclaw-weixin CLI->>WX: 请求二维码 WX-->>CLI: 返回二维码 + 扫码链接 CLI-->>AI: 输出扫码链接 AI->>AI: Python qrcode 库生成二维码图片 AI->>QQ: 发送二维码图片 QQ-->>User: 显示二维码图片 📱 Note over User,WX: 用户用微信扫码授权 User->>AI: 扫码完成 AI->>CLI: 检查登录结果 CLI-->>AI: 登录成功 ✅ AI->>QQ: 登录成功!

实现细节

步骤技术手段
1. 触发登录Agent 通过 exec 工具执行 openclaw channels login
2. 获取链接从 CLI 输出中提取 https://liteapp.weixin.qq.com/q/... 链接
3. 生成图片使用 Python qrcode 库将链接转为 PNG 图片
4. 发送图片通过 QQBot 的 <qqmedia> 标签发送本地图片

这个场景体现了 OpenClaw 的一个核心优势:Agent 具备本地执行能力。Agent 不只是一个聊天机器人,它可以执行命令、生成文件、跨通道传递内容。用户甚至不需要直接接触服务器,只需要在 QQ 上说一句话,Agent 就能完成整个登录流程。

⚠️ 注意:二维码有效期约 5 分钟。如果用户扫码不及时,Agent 需要重新启动登录流程获取新的二维码。

四、票据管理与安全

4.1 微信 Bot 票据存储

flowchart LR
    subgraph Storage["本地存储"]
        AcctJSON["accounts.json
账号 ID 列表"] AcctDir["accounts/"] Token["863fc8fa1527-im-bot.json
token + baseUrl + userId"] CtxToken["...context-tokens.json
会话上下文 token"] SyncBuf["...sync.json
消息同步游标"] end AcctJSON --> AcctDir AcctDir --> Token AcctDir --> CtxToken AcctDir --> SyncBuf style Storage fill:#1565C0,color:#fff style Token fill:#B22222,color:#fff style CtxToken fill:#E65100,color:#fff style SyncBuf fill:#228B22,color:#fff

凭据文件内容(脱敏后):

1
2
3
4
5
6
{
  "token": "863fc8fa1527@im.bot:06000026...",
  "savedAt": "2026-03-28T02:33:59.776Z",
  "baseUrl": "https://ilinkai.weixin.qq.com",
  "userId": "o9cq809tV7az43yhXtAXyRi24mo8@im.wechat"
}

4.2 QQBot 票据存储

QQBot 的票据不落盘,完全在内存中管理:

flowchart LR
    Config["openclaw.json
appId + clientSecret
(明文配置)"] Memory["内存 Token 缓存
tokenCacheMap"] API["QQ API"] Config -->|"启动时读取"| Memory Memory -->|"Token 过期"| API API -->|"新 Token"| Memory style Config fill:#B22222,color:#fff style Memory fill:#1565C0,color:#fff style API fill:#5E35B1,color:#fff

4.3 安全对比

安全维度微信 BotQQBot
凭据存储本地文件 (600 权限)内存缓存(不落盘)
敏感配置token 在独立目录appId + Secret 在主配置文件
SecretRef 支持❌ 不支持❌ 不支持(clientSecret 明文)
凭据轮换需重新扫码自动刷新 access_token
泄露风险文件读取配置文件读取 + 内存 dump

⚠️ 注意:两者的凭据都存在被本地进程读取的风险。微信 Bot 的 token 明文存储在磁盘上,QQBot 的 clientSecret 明文写在 openclaw.json 中。如果对安全性有更高要求,建议使用文件权限控制和全盘加密。

五、消息收发流程

5.1 微信 Bot 消息收发

sequenceDiagram
    participant User as 微信用户
    participant WX as 微信服务器
    participant Plugin as 微信插件
    participant GW as Gateway
    participant AI as GLM-5

    Note over Plugin,WX: 1. 消息接收(长轮询)
    loop 循环轮询
        Plugin->>WX: POST getupdates
(长轮询,等待新消息) WX-->>Plugin: {message_list: [...]} end Note over Plugin,AI: 2. 消息处理 Plugin->>GW: inbound message
from=userId@im.wechat GW->>GW: 路由到对应 session GW->>AI: 推理请求
(携带 workspace 上下文) AI-->>GW: 生成回复 GW-->>Plugin: outbound message
to=userId@im.wechat Note over Plugin,WX: 3. 消息发送 Plugin->>Plugin: Markdown → 纯文本转换
(微信不支持 Markdown) Plugin->>WX: POST sendmessage
{to_user_id, item_list, context_token} WX-->>Plugin: 发送确认 WX-->>User: 收到回复 ✅

关键细节

  1. 长轮询机制:插件持续向 getupdates 端点发送请求,微信服务器会 hold 住连接直到有新消息或超时
  2. 消息格式转换:微信不支持 Markdown,插件会将 AI 生成的 Markdown 回复转换为纯文本(去代码块、去图片语法、表格转空格分隔)
  3. context_token:微信使用上下文 token 来关联请求-响应对,确保消息的顺序性
  4. 消息同步游标sync-buf 文件记录上次拉取位置,避免重复处理

5.2 QQBot 消息收发

sequenceDiagram
    participant User as QQ 用户
    participant QQ as QQ 服务器
    participant Plugin as QQBot 插件
    participant GW as Gateway
    participant AI as GLM-5

    Note over QQ,Plugin: 1. WebSocket 实时推送
    User->>QQ: 发送消息
    QQ-->>Plugin: WS: C2C_MESSAGE_CREATE
(主动推送,无需轮询) Note over Plugin,AI: 2. 消息处理 Plugin->>GW: inbound message GW->>GW: 路由到对应 session GW->>AI: 推理请求 AI-->>GW: 生成回复 GW-->>Plugin: outbound message Note over Plugin,QQ: 3. 消息发送(支持 Markdown) Plugin->>QQ: POST /v2/users/:openid/messages
msg_type=2, markdown={content} QQ-->>Plugin: 发送确认 QQ-->>User: 收到回复 ✅ Note over Plugin,QQ: 4. 流式输出(可选) loop 流式分片 Plugin->>QQ: POST (partial markdown) QQ-->>User: 逐步显示 end

5.3 消息收发对比

对比项微信 BotQQBot
消息接收HTTP 长轮询 (getUpdates)WebSocket 实时推送
接收延迟取决于轮询间隔(秒级)近实时(毫秒级)
消息格式纯文本(自动去 Markdown)Markdown(支持富文本)
流式输出❌ 不支持✅ 支持 partial streaming
打字提示sendTyping APIsendC2CInputNotify
主动推送❌ 仅限回复用户消息✅ 支持主动发送

六、会话管理

6.1 会话隔离模型

OpenClaw 对所有通道采用统一的会话隔离策略:

flowchart TB
    subgraph Sessions["会话管理"]
        QQSession["agent:main:qqbot:direct:{userId}"]
        WXSession["agent:main:openclaw-weixin:direct:{userId}@im.wechat"]
        TGSession["agent:main:telegram:direct:{userId}"]
    end

    subgraph Shared["共享资源"]
        Soul["SOUL.md"]
        User["USER.md"]
        Memory["MEMORY.md"]
        Tools["TOOLS.md"]
    end

    QQSession --> Shared
    WXSession --> Shared
    TGSession --> Shared

    style Sessions fill:#1565C0,color:#fff
    style Shared fill:#228B22,color:#fff

每个 通道 + 用户 组合对应一个独立的 session,但共享同一份 workspace 上下文(SOUL.md、MEMORY.md 等)。

6.2 会话存储结构

1
2
3
4
5
~/.openclaw/agents/main/sessions/
├── sessions.json                        # 会话索引(所有通道)
├── {session-uuid-1}.jsonl               # QQBot 会话记录
├── {session-uuid-2}.jsonl               # 微信会话记录
└── {session-uuid-3}.jsonl               # Telegram 会话记录

JSONL 记录格式

type说明
session会话元数据(ID、工作目录、时间戳)
message用户消息或 AI 回复(含完整内容)
model_change模型切换记录
thinking_level_change推理级别变更
custom自定义事件(如模型快照)

6.3 跨通道会话可见性

默认配置下,会话的可见性限制为当前会话树tools.sessions.visibility=tree),即:

  • QQBot 会话无法访问微信会话的历史
  • 微信会话无法访问 Telegram 会话的历史
  • 但都可以访问共享的 workspace 文件(MEMORY.md 等)

这意味着通过 MEMORY.md,不同通道之间可以间接共享记忆,但对话历史是隔离的。

七、插件生命周期

7.1 微信 Bot 启动流程

flowchart TB
    Start["Gateway 启动"] --> LoadPlugin["加载 openclaw-weixin 插件"]
    LoadPlugin --> Compat{"版本兼容检查
OpenClaw >= 2026.3.22?"} Compat -->|"✅"| LoadAcct["读取 accounts.json
加载已保存的凭据"] Compat -->|"❌"| Fail["拒绝加载"] LoadAcct --> SetRuntime["设置 WeixinRuntime"] SetRuntime --> StartPoll["启动 getUpdates 长轮询"] StartPoll --> Ready["✅ 就绪,等待消息"] style Start fill:#228B22,color:#fff style Ready fill:#228B22,color:#fff style Fail fill:#B22222,color:#fff

7.2 QQBot 启动流程

flowchart TB
    Start["Gateway 启动"] --> LoadPlugin["加载 openclaw-qqbot 插件"]
    LoadPlugin --> ReadConfig["读取 appId + clientSecret"]
    ReadConfig --> GetToken["获取 access_token"]
    GetToken --> GetGateway["获取 WebSocket URL"]
    GetGateway --> WSConnect["建立 WebSocket 连接"]
    WSConnect --> Identify["发送 Identify + Intents"]
    Identify --> Ready["✅ Ready Event,等待消息"]
    GetToken -->|"失败"| Retry["后台重试"]

    style Start fill:#228B22,color:#fff
    style Ready fill:#228B22,color:#fff
    style Retry fill:#E65100,color:#fff

八、完整数据流总结

flowchart LR
    subgraph Input["消息输入"]
        WXIn["微信用户消息"]
        QQIn["QQ 用户消息"]
    end

    subgraph Protocol["协议层"]
        WXHTTP["HTTP 长轮询
getUpdates"] QQWS["WebSocket 推送
C2C_MESSAGE_CREATE"] end subgraph Plugin["插件层"] WXP["微信插件
消息解析 + 格式转换"] QQP["QQBot 插件
消息解析 + @处理"] end subgraph Core["OpenClaw 核心"] Router["会话路由器"] Session["Session
(上下文管理)"] LLM["LLM 推理
(GLM-5)"] end subgraph Output["消息输出"] WXOut["HTTP POST
sendMessage"] QQOut["HTTP REST
/v2/users/:id/messages"] end WXIn --> WXHTTP --> WXP QQIn --> QQWS --> QQP WXP --> Router QQP --> Router Router --> Session --> LLM LLM --> Session --> Router Router --> WXOut Router --> QQOut style Input fill:#228B22,color:#fff style Protocol fill:#E65100,color:#fff style Plugin fill:#5E35B1,color:#fff style Core fill:#1565C0,color:#fff style Output fill:#B22222,color:#fff

九、关键发现与思考

9.1 协议选择的权衡

HTTP 长轮询(微信)WebSocket(QQ)
优点实现简单,无需维护连接状态实时性好,服务端主动推送
缺点延迟较高,资源浪费连接管理复杂,需处理重连
适用消息量小的场景消息频繁、需实时响应

微信选择长轮询可能是因为 iLink 协议的设计历史——微信的 Bot 系统基于「微信读书」的 iLink 基础设施,而非专门为 Bot 场景设计。

9.2 凭据安全的矛盾

两个通道都存在凭据明文存储的问题:

  • 微信:bot_token 明文存储在 ~/.openclaw/openclaw-weixin/accounts/ 目录
  • QQ:clientSecret 明文写在 openclaw.json 主配置文件

OpenClaw 的 SecretRef 机制可以保护 API Key 等凭据(通过 Vault 引用),但 IM 通道的凭据目前不支持 SecretRef——这是插件实现层面的限制,而非框架限制。

9.3 会话隔离与记忆共享

OpenClaw 的会话设计体现了一个有趣的平衡:

  • 对话隔离:不同通道的对话历史互相不可见(visibility=tree
  • 记忆共享:所有通道共享 MEMORY.md,可以间接传递上下文

这意味着在 QQ 上讨论的内容,如果写入了 MEMORY.md,微信 Bot 也能"记得"。但这种共享是显式的——需要 AI 主动决定写入什么内容。


本文基于 OpenClaw 2026.3.24 + openclaw-weixin 2.1.1 + openclaw-qqbot 1.6.6 的源码分析。