OpenClaw 统一接入 QQ 与飞书:多平台消息网关实战指南

发布时间:2026/10/16 4:01:14
OpenClaw 统一接入 QQ 与飞书:多平台消息网关实战指南 聊点实在的。最近忙完的一件事是把我自己维护的那套 OpenClaw AI 助手网关同时接进了 QQ-Bot 和飞书。原本 QQ 助手和飞书助手是两套互相独立的代码一个跑在定时脚本里一个挂在群机器人上技能逻辑七零八落改个提示词都要动两处。折腾完这次接入之后同一个大脑、同一套工具函数两个入口直接共用省了差不多一半的维护量。OpenClaw 本身做的事情很简单它不负责写对话也不负责跑模型而是一个消息网关。QQ 来一个事件飞书来一个事件它统一翻译成内部的会话消息再交给你的智能体逻辑去处理。对不熟悉这套结构的朋友来说你完全可以把它想象成一块转接板左边插着各种聊天平台右边插着你的 Agent 核心。这篇文章就围绕我从零把 OpenClaw 接入 QQ 和飞书的完整过程展开重点不是复读文档而是把我在配置、调试、处理回调、踩坑过程中觉得最值得记录的细节写出来。如果你正准备给团队或自己搭一个多平台可用的机器人这篇应该能帮你少走不少弯路。1. OpenClaw 是什么以及我为什么非要同时接 QQ 和飞书1.1 从一个助手两个入口说起很多人的 AI 机器人都是按平台分开养的QQ 上一个脚本飞书上一个机器人两边各自维护一套提示词和工具调用。我最初也是这个状态因为 QQ 和飞书的开放接口差异很大事件结构不一样消息类型不一样就连最简单的发送一条文本消息调用的接口都完全不同。结果是每次想加点新能力比如查天气、查数据库、生成周报都得在两边各写一遍甚至因为两边工具封装不一致跑出来的结果格式都对不上。后来我意识到一个很朴素的道理智能体本身和消息平台应该是解耦的。用户从哪个聊天窗口发消息不该影响我如何处理这条消息机器人要具备哪些工具也不该因为平台不同就重写一套。所以我需要一个中间层把平台差异挡在外面让核心逻辑只关心收到了一段文本需要返回一段文本或者触发一个动作。OpenClaw 就是这个中间层的落地实现。它安装好之后每个平台对应一个 adapter比如qq适配器和feishu适配器。这些 adapter 负责监听平台的回调、解析消息、调用鉴权、发送回复。我的业务代码只需要注册一个handle_message函数OpenClaw 会自己判断消息从哪来、应该怎么回。这样我就有了一个只在核心层写一遍、同时服务于两个平台的统一入口。1.2 OpenClaw 在消息平台接入中的角色如果你之前用过类似的消息网关可能对Webhook 事件上报这套模型不陌生。OpenClaw 在每个平台侧都扮演两个角色对外是回调接收端对内是事件分发器。以 QQ-Bot 为例QQ 平台把群消息、私聊消息、好友添加等事件通过 HTTP 回调推送到你配置的 URLOpenClaw 在收到后先做签名校验再转成标准化的内部事件对象。飞书一侧也是同样的思路只不过飞书的回调机制更繁琐一点需要先通过 URL 验证再按事件类型订阅。直接说结论用 OpenClaw 接两个平台你的业务代码只需要面对两种输入。一种是InternalMessage包含platform、chat_id、user_id、text等统一字段另一种是InternalActionResult代表工具执行之后的反馈。你不需要关心 QQ 的sender.openid和飞书的sender.sender_id.open_id到底有什么不同因为 OpenClaw 在 adapter 层已经把它们映射成了同样的结构。这样设计还有一个隐藏好处智能体的上下文管理可以和平台无关。我在 OpenClaw 上配置了基于 Redis 的会话存储session key 是平台前缀 用户 ID 会话场景。QQ 私聊和飞书私聊各自独立但底层用的是同一套上下文管理代码。也就是说模型该记住什么、该遗忘什么完全由核心逻辑决定不会因为今天从 QQ 进来还是从飞书进来就有差异。2. 接入前的准备账号、协议、环境三件套2.1 QQ 侧的两种接入路线怎么选QQ 的机器人接入路径比较特殊因为市面上实际有两类方案在并行使用。一类是 QQ 官方机器人开放平台走的是正规的开发者审核流程申请应用拿到app_id和app_secret然后配置回调地址。这类方案接起来干净接口稳定但限制也比较多比如私聊消息的获取需要特定权限部分类目需要企业主体认证个人开发者能申请到的接口范围有限。另一类是社区协议实现比如常见的 go-cqhttp 以及它的各种现代分支。它们的原理是模拟一个客户端登录然后把消息事件通过正向或反向 WebSocket 转发给你。这套方案功能更全能发文件、能主动拉取历史消息、能执行更多群管理操作但对账号来说存在一定风险而且紧跟协议变化需要经常更新。我这次的选择比较务实主用社区协议做内部群的自用机器人同时保留了官方通道的适配器配置备选。如果你是为了给外部用户提供正式服务我不建议走社区协议账号安全和被封禁风险都是实打实的但如果你只是给自己所在的小团队用社区协议的便捷性非常明显。OpenClaw 里这两种可以通过type: qq-official和type: qq-community切换底层 adapter 不同但上行业务逻辑完全不用改。2.2 飞书自建应用的创建与权限预分配飞书这边的准备工作相对标准。在飞书开放平台里创建一个企业自建应用然后在应用能力里开通机器人能力。你需要记下App ID和App Secret这两个值在后续配置里要填到 OpenClaw 的feishu适配器里。权限这块我要单独提醒一句尽量遵循最小权限原则。我最初图省事一次性申请了十几个权限结果后台审核直接把我拦住要求说明用途。后来收敛到三个核心权限接收消息、发送消息、读取用户基本信息。注意飞书不同的权限范围对应不同的事件订阅比如想接收群消息就得订阅im.message.receive_v1想读取用户组织信息就得再加contact:user.base:readonly。OpenClaw 的飞书 adapter 会帮你检查事件订阅是否匹配但权限申请还是要自己动手。还有一个小细节飞书应用创建之后默认是测试版需要先发布版本才能被非开发者成员使用。如果你只是自己调试可在版本管理与发布里创建一个测试版本然后在可用成员里添加测试成员即可。否则你拿小号发消息给机器人机器人根本收不到。2.3 本机环境的依赖与回环地址准备OpenClaw 本身是用 Node.js 写的运行时我在部署前先确认了两件事Node.js 版本高于 18Redis 已经可用。Redis 在这里不是可选项因为 OpenClaw 的会话锁、事件去重都用到了它。我用的是系统自带的redis-server配置文件里指向localhost:6379就够用。最麻烦的是回调地址的连通性。QQ 和飞书都要求回调地址是公网可访问的 HTTPS 地址开发阶段我没法直接上生产环境就用内网穿透工具把本机的7000端口映射到了一个临时域名。这个环节有个很容易踩的坑QQ 后台和飞书后台在保存回调地址时都会主动发起一次请求验证如果你的本地服务还没启动后台会提示URL 验证失败。所以正确顺序是先把 OpenClaw 拉起来确认日志里显示 adapter 在监听再去后台填 URL。生产环境我直接用 Nginx 反代到本机端口同时把 TLS 证书配好。OpenClaw 本身也支持直接配置证书但我不太建议让应用进程直接持有证书文件交给 Nginx 统一管理重启服务时不用操心 443 端口的权限问题。3. QQ-Bot 接入实操Webhook 与事件上报的完整走读3.1 生成密钥与配置回调地址QQ 这头的配置写起来比较直白。我的claw.yaml里大概是这样的platforms: qq: type: qq-community nickname: helper-bot reverse_ws_url: ws://127.0.0.1:8080/ws access_token: your-access-token message_timeout: 30如果你用的是官方通道配置略有不同platforms: qq: type: qq-official app_id: 1023xxxx app_secret: xxxxxxxx token: callback-sign-token callback_url: https://bot.example.com/openclaw/qq/callback重点解释下token和app_secret的区别。token是回调签名用的QQ 服务器在推送事件时会把token、timestamp、nonce三个值拼接后算 SHA1放在X-Tencent-Signature请求头里。OpenClaw 收到请求后会自己复算一遍用来确认事件确实来自 QQ。而app_secret是业务接口签名用的比如主动调 QQ 的接口发消息时需要用它生成 JSAPISignature。这两个值在概念上不能混我在刚开始配置时一度把token填成了app_secret结果回调校验一直失败日志里全是signature mismatch。社区协议通道相对省事一点。OpenClaw 作为客户端去连 go-cqhttp 的 WebSocket 服务不需要关心 HTTP 回调的签名只需要在access_token里配置一个双方约定好的口令。这个口令同样不能随意填必须在 go-cqhttp 的配置文件中保持一致不然握手阶段就会被拒绝。3.2 把 OpenClaw 的 QQ 适配器跑起来启动命令比我想象中简单openclaw start --config claw.yaml看到日志输出类似下面几行基本说明 QQ 适配器已经就绪[openclaw] starting adapter: qq [openclaw] qq adapter connected to ws://127.0.0.1:8080/ws [openclaw] session manager connected to redis [openclaw] agent core loaded: my-assistant这里我额外强调一个容易被忽略的点如果连的是社区协议的 WebSocketOpenClaw 默认是客户端模式也就是 OpenClaw 主动去连 go-cqhttp。此时 go-cqhttp 的post-message-format最好设置成array因为string格式下 CQ 码解析容易出错而array格式会把消息拆成一段段结构化的消息段OpenClaw 解析起来更准确。改完这个配置记得重启 go-cqhttp否则你发的图片、消息都可能在解析层丢失。3.3 本地联调私聊、群聊、触发一次打通适配器起来之后我最先做的是拿小号给机器人发一条私聊消息。这里有一个很实用的调试习惯我一开始不会直接让 OpenClaw 调用任何外部工具而是先注册一个简单的echo命令让它原样返回消息内容。这样可以快速验证消息链路是通的而不是一上来就排查模型调用的报错。echo通了之后再去群里测试 触发。QQ 群的机器人只有在被 或者设置了关键词触发的情况下才会收到事件这是我最初没预料到的。OpenClaw 内部有个配置项叫mention_only默认是true。如果你希望机器人在群里主动响应所有消息得显式把这个值改成false。但我不建议这么做群消息的噪声远大于有效指令保持只响应 或前缀指令对用户体验更友好。联调通过后还有一件容易被忽略的事记录群聊和用户的 OpenID。OpenClaw 日志里会把每条消息对应成一个 session key比如qq:group_xxxx:user_yyyy。后面要让机器人定时往特定群推消息需要用到这个 key建议提前在配置里做好映射别等要用的时候满日志找。4. 飞书接入实操事件订阅、卡片消息与租户隔离4.1 应用凭证与事件订阅 URL 配置飞书这边的配置结构跟 QQ 有些差异但理念一致。在飞书开放平台后台的事件订阅页面先添加订阅事件比如im.message.receive_v1然后把请求地址 URL 填成https://bot.example.com/openclaw/feishu/callback。对应的claw.yaml配置是这样platforms: feishu: type: lark app_id: cli_xxxxxxxxx app_secret: xxxxxxxxx verification_token: xxxxxxxxx encrypt_key: callback_url: https://bot.example.com/openclaw/feishu/callback这里有个很容易误解的地方飞书的事件订阅配置里有Verification Token和Encrypt Key两个概念。Verification Token是明文请求用来验证身份的OpenClaw 收到请求后会比对它和后台配置是否一致不一致直接拒绝。Encrypt Key只有在你开启了加密回调才需要填。如果你在后台开启了加密选项但 OpenClaw 配置里encrypt_key留空那回调请求会解不开日志里会一直报decrypt failed。我的建议是开发阶段先不开加密通了以后再加上这样可以少一个变量。4.2 处理飞书特有的 challenge 校验飞书最大的特点或者说考验是在你保存事件订阅 URL 时会先执行一次 URL 验证。后台会随机生成一个challenge参数通过 HTTP 请求发给你的回调地址。你的服务必须原样返回{challenge: xxx}并且状态码为 200后台才认为 URL 可用。第一次配置的时候我犯了个错我把 challenge 当成一个固定值写死在代码里了。结果后台保存时返回URL 验证失败。原因是飞书的每个 challenge 都是临时生成的后一次永远不等于前一次必须动态读取请求 body 里的值然后返回。OpenClaw 的适配器已经内置了这个处理逻辑所以我最终没有手动实现。但如果你哪天需要自己写入口请一定记住这点。有一个相关的细节是飞书验证 URL 时往往同时发送 GET 和 POST 两种请求虽然标准文档里写的是 POST但我在实测中遇到过 GET 类型的挑战请求所以你的路由需要同时接受两种方法或者至少不要对 GET 直接返回 404。4.3 消息卡片与文本消息的格式差异飞书的富文本能力强于 QQ代价是格式转换更麻烦。QQ 那边基本发纯文本和图片就够了而飞书群里大家习惯看卡片消息带标题、带分割线、带按钮那种。OpenClaw 内部维护了一个消息输出的抽象层插件返回一个普通字符串时飞书 adapter 会包成简单的text消息发出去如果插件返回的是结构化 JSON适配器可以按模板转成interactive卡片。这是功能上的自由度但也带来了麻烦。同样的消息内容在 QQ 里是一行朴素的文本在飞书里如果你不做处理就只是一行更朴素的文本看起来不够精致。我后来写了一个小函数专门判断当前平台是不是飞书是的话就把 Markdown 风格的段落转成飞书卡片结构在关键信息上用lark_md标签修饰。需要注意飞书卡片消息的发送接口和普通文本消息不一样OpenClaw 会自动选择但你如果自己在飞书后台测试时需要明确POST 到/im/v1/messages时msg_type为text或interactive这个字段决定了消息渲染方式填错了会报参数错误。5. 统一大脑分散入口多平台消息路由与状态同步5.1 平台 ID 到 OpenClaw 会话的映射两块平台接入都跑通后我做的第一件事不是加新功能而是检查会话映射是否正确。OpenClaw 的会话 key 规则在日志里很容易看清QQ 私聊qq:user_openid:privateQQ 群聊qq:group_id:user_openid飞书私聊feishu:ou_xxx:private飞书群聊feishu:oc_xxx:ou_xxx默认情况下每个平台、每个用户、每个会话场景都是独立的 session。就是说同一个用户先去 QQ 私聊机器人又跑去飞书私聊机器人OpenClaw 默认不会把这两段对话混在一起。这个设计很合理因为两个平台的使用场景不同历史上下文混在一起容易造成误导。但是如果你确实希望一个人在两个平台共享同一份记忆OpenClaw 的配置里有个session_merge_rules可以控制。我试过这个功能最后没有生产使用因为跨平台合并要求两边用户 ID 有对应关系实际很难维护。我给自己的结论是不做合并但让用户主动用/remind这类指令把关键信息存进长期记忆需要的时候再调出来。5.2 消息去重与多播问题多平台接入之后有一个问题会变得非常突出消息重复触发。这里有两个来源。第一个来源是平台本身的重发机制比如飞书在没收到 200 响应时会重试推送事件第二个来源是业务侧的多播比如你在 QQ 群里让机器人同步发送到飞书那么同一条指令可能会在两个平台各执行一次。我的处理办法是引入一个去重 ID。OpenClaw 的 adapter 在收到事件时会为每个事件生成一个event_idQQ 社区协议通常用message_id飞书用message_id也可以。我在核心逻辑里加了一层 Redis 锁import redis r redis.Redis(hostlocalhost, port6379, db0) def acquire_event_lock(event_id, ttl5): return r.set(fevent_lock:{event_id}, 1, nxTrue, exttl)只有拿到锁的那个分支才继续执行有副作用的操作比如调数据库、发 API 请求其余分支直接丢弃。这样做以后飞书重试导致的重复消息明显减少。有一点要特别注意锁的 TTL 不能设太短否则一个真正耗时超过 5 秒的工具调用执行到一半锁就过期了平台的重试又进来还是会造成重复。我把 TTL 设成 30 秒足够了。5.3 机器人主动推送的权限差异接入之后我还需要让机器人具备主动推送能力比如每天早上向指定群里汇报一次线上状态。这里就发现了多平台之间很大的不对等。QQ 社区协议可以比较自由地主动发私聊和群消息但官方 QQ 开放平台对主动消息有严格的频次限制单日单用户最多几次超出会被处罚。飞书这边相对宽松只要机器人有发文权限主动发消息给用户是常见操作。OpenClaw 里配置一个定时触发的工具后我额外加了一个platform_quota字段用它来限制主动推送的频率。举个具体的例子我的定时周报任务同时配置了 QQ 群和飞书群但飞书群里可以完整发卡片周报QQ 群只能发文本摘要且每天最多推两次。这个限制写在一个很薄的配置层里notify: qq: max_per_day: 2 format: text feishu: max_per_day: 10 format: card别觉得这是过度设计实际跑起来你会发现平台规则不是写在文档里给你看看的而是你推送多了真会受到限制到时候排查问题的时间远超一开始写好配置的时间。6. 踩坑清单事件回调重复、超时换签、卡片权限不足6.1 腾讯回调的签名头到底校验哪几个第一轮排查耗时最久的坑是 QQ 官方回调的签名校验。我用社区协议时没有这个问题一切正常切到qq-official后回调 URL 后台保存成功但事件推送过来OpenClaw 日志一直报签名失败。后来我抓了完整的请求头发现 QQ 回调带了三个关键 HeaderX-Tencent-Timestamp、X-Tencent-Nonce、X-Tencent-Signature。签名计算的规则是把token、timestamp、nonce三个字符串拼接后做 SHA1。我一开始漏掉了token在拼接中的位置只用了timestamp nonce自然对不上。还有一个隐患是重放攻击。就算签名是对的如果不去校验timestamp的新鲜度攻击者可以把很久以前的回调原样重发OpenClaw 仍然会当作新事件处理。我在自己的中间件里加了一个五分钟的超时窗口超过当前时间五分钟的一律丢弃。OpenClaw 自带配置项里也有max_ts_skew建议把它设成 300。6.2 飞书 URL 验证与事件重放飞书这边最折磨人的是事件重放机制。我在调试一个耗时较长的 Agent 任务时飞书后台因为没在 1.5 秒内收到 200就把同一个事件重发了三次结果任务被重复执行了三次。这个坑的直接解法是先收下再异步处理。OpenClaw 的 adapter 其实已经做了这件事它在收到回调后会立刻返回 200然后把事件放入内部队列让 Worker 慢慢处理。但如果你绕过 OpenClaw自己写了一个同步调用模型的接口就很容易踩这个超时红线。另外飞书的重试事件带有相同的event_id业务代码里必须做幂等判断。我刚才提到的 Redis 锁在这里再次派上用场。除此之外我建议把飞书的日志打开记录每条事件的event_id和处理状态否则一旦出现重复很难定位是哪一次请求造成的副作用。6.3 我最后保留的生产配置模板折腾完一圈我最想给后来者看的是一份我目前还在用的精简配置。它不代表所有场景最优但至少避开了大多数坑server: port: 7000 auth_token: openclaw-server-token session: storage: redis redis_host: localhost redis_port: 6379 ttl_seconds: 3600 platforms: qq: type: qq-community nickname: helper-bot reverse_ws_url: ws://127.0.0.1:8080/ws access_token: your-access-token mention_only: true feishu: type: lark app_id: cli_xxxxxxxx app_secret: xxxxxxxx verification_token: xxxxxxxx encrypt_key: callback_url: https://bot.example.com/openclaw/feishu/callback dedupe: enabled: true redis_prefix: dedupe:event ttl_seconds: 30 notify: qq: max_per_day: 2 format: text feishu: max_per_day: 10 format: card这份配置跑了好几个星期稳定性还可以。中间只因为 go-cqhttp 的 WebSocket 连接断开重启过一次OpenClaw 会自动重连但重启间隔内收到的消息会丢所以我在部署脚本里加了守护进程保证服务异常退出时能快速拉起。如果再让我重新选一次我仍然会优先把核心逻辑放在 OpenClaw 的平台无关层而不是直接调两个平台的 SDK。原因很简单平台 SDK 是在变的回调协议偶尔微调接口字段也可能升级而 OpenClaw 把这些变化挡在了 adapter 后面。我只要守住claw.yaml和业务层大多数平台变动发生时我只需要更新一下 OpenClaw 版本业务代码几乎不用动。最后分享一个实际操作中的小建议。在跑通第一个 Echo 指令之前别急着接模型、别急着配工具先把收到消息 - 返回固定文本 - 两边平台都能看到这条链路稳定跑起来。因为多平台调试的复杂度是叠加的QQ 和飞书任何一个环节出问题都会让你的排查范围翻倍。把链路切成一小段一小段地验证比一次性全部接通要可靠得多。这套工程习惯值得在你自己接入新平台时同样坚持。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询