[Bug] QQ 审批按钮点击后无任何反应:qqbot 网关连接未启动,INTERACTION_CREATE 从未路由到审批处理器a
修正版 —— 初版(字段缺失假设)经实测已排除,根因在更底层。
环境
| 项 |
值 |
| OpenClaw 版本 |
2026.7.1-2 |
| 系统 |
Windows 10 / D:\nodejs\node.exe |
| 网关进程 |
D:\nodejs\node_modules\openclaw\dist\index.js gateway --port 18789(core 包,PID 41692,启动 2026-08-13 20:39:50) |
| 频道 |
qqbot(appId 1905295106,clientSecret 已配置,connected) |
| 扩展代码 |
用户级 C:\Users\LPLR\.openclaw\extensions\qqbot\dist/(即仓库 tencent-connect/openclaw-qqbot) |
| 全局审批策略 |
tools.exec.ask = "always"(保持不变,非本 bug 成因) |
现象
QQ 私聊中,需要执行 shell 命令时龙虾下发审批按钮卡(✅ 允许一次 / ❌ 拒绝)。用户点击「✅ 允许一次」后:
- 龙虾无任何反应,命令不执行;
- 对应 run 在审计表里以
agent.run.finished status=blocked 结束(exec 仅 tool.action.started,无 finished);
- 审批卡变成「死卡」——再点也无用。
同一审批若改在 OpenClaw 控制 UI(http://127.0.0.1:18789) 点击批准则正常执行。说明问题仅在 QQ 按钮路径,审批系统本身可用。
复现
tools.exec.ask = "always",QQ 频道 connected。
- 在 QQ 私聊让龙虾执行任意需审批命令(触发
exec)。
- 龙虾在 QQ 下发审批按钮卡。
- 在 QQ 里点击「✅ 允许一次」。
- 观察:龙虾沉默;run 最终
blocked。
诊断过程与证据(已实测)
在 qqbot 扩展的多处加了写文件诊断埋点(调试日志 zh-patches/qqbot-approval-debug.log),重启网关后观察:
| 埋点位置 |
含义 |
是否触发 |
gateway-pJQppxe4.js 模块顶层 MODULE_LOADED |
扩展模块被加载 |
✅ 触发(证明扩展已加载) |
index.js 顶层 INDEX_LOADED_USER |
扩展入口加载 |
✅ 触发 |
GatewayConnection.start() 首行 CONN_START |
扩展网关连接被启动 |
❌ 从未触发 |
ws.on("open") CONN_OPEN |
扩展 ws 连接建立 |
❌ 从未触发 |
ws.on("message") dispatch |
扩展收到任意网关事件 |
❌ 从未触发 |
createInteractionHandler() 顶部 interactionHandler |
审批交互处理器被调用 |
❌ 从未触发 |
handleMessage() 顶部 HANDLE_MESSAGE |
C2C 消息走扩展处理器 |
❌ 从未触发 |
同时,audit_events 显示:QQ 私聊消息能正常触发 run(C2C 路径工作),但点击审批按钮的 run 全部以 blocked 结束。
根因
qqbot 审批交互的处理链路由扩展的 GatewayConnection 承载:
qqbotPlugin.gateway.startAccount(ctx) // channel-D1UztsnG.js:1225
→ loadGatewayModule() // 动态加载 gateway-pJQppxe4.js
→ startGateway({ ..., onInteraction: handleInteraction, handleMessage })
→ new GatewayConnection({...}).start() // gateway-pJQppxe4.js:6563
→ ws 连接 QQ 网关
→ ws.on("message") → dispatchEvent → 若 action==="interaction"
→ this.ctx.onInteraction(event) // gateway-pJQppxe4.js:1583
→ createInteractionHandler → authorizeApprovalButtonActor → 授权
证据表明:核心网关(core dist/index.js)并没有调用 qqbotPlugin.gateway.startAccount,因此:
- 扩展的
GatewayConnection 从未 start()(CONN_START/CONN_OPEN 不触发)→ 扩展的 ws 从不连接、从不接收事件;
- 扩展注册在自身
GatewayConnection 上的 onInteraction(审批处理器)从未被核心接线;
- C2C 消息由核心的另一条路径处理(能正常触发 run),但按钮点击的
INTERACTION_CREATE 不被任何处理器接收 → 审批卡永远 pending/blocked。
即:qqbot 通道的交互(按钮审批)处理器在运行时从未被启动/接线,这是 OpenClaw 核心与 qqbot 插件之间的集成缺陷,而非单纯的字段解析问题。
附:初版假设「resolveApprovalActorSenderIds 读不到发送者字段」已被排除——该函数本身确实只读 user_openid/group_member_openid(对 INTERACTION_CREATE 为空),但更上游的 handler 根本没被调用,所以字段问题不是当前阻断点。该字段加固仍建议作为后续改进(见下)。
影响范围
- QQ 频道内无法就地批准任何 exec 审批卡(按钮必失败)。
- 用户被迫改用控制 UI 批准,移动端体验断裂。
tools.exec.ask=always 安全规则本身无问题,不应为此关闭。
建议修复(两层)
P0(核心集成,必须修才能恢复按钮审批):
- 核心网关在启动 qqbot 通道时应调用
qqbotPlugin.gateway.startAccount(或等价入口),确保 GatewayConnection 启动并把 onInteraction 接线到审批运行时(approval-handler-runtime 的 nativeRuntime.interactions 适配器)。
- 或:qqbot 插件改为通过
startAccount 收到的 ctx 向核心注册 onInteraction,而非仅挂在自身 GatewayConnection 上。
P1(字段加固,P0 修好后生效):
- 在
resolveApprovalActorSenderIds() 中,当 user_openid/group_member_openid 为空时,回退到 INTERACTION_CREATE 事件实际可用的发送者标识(event.openid、event.user_info.openid、event.data.user_openid、或递归扫描含 openid|user_id|sender_id 的键)。配合 channels.qqbot.allowFrom:["*"],事件一旦到达 handler 即可授权。
已尝试的本地补丁
- 已对用户级
extensions/qqbot/dist/gateway-pJQppxe4.js 应用 resolveApprovalActorSenderIds 字段加固 + 诊断埋点,并重启加载(MODULE_LOADED 已确认)。
- 因 P0(连接未启动)未解决,该加固尚无法被验证(handler 仍不被调用)。补丁本身无害,建议上游修复 P0 后保留。
临时绕过(可用)
- 控制 UI 批准:电脑打开
http://127.0.0.1:18789/ 或 ClawX 桌面端,审批卡可正常点击批准,不影响 tools.exec.ask=always 安全规则。
- 注:OpenClaw 的 exec 审批为全局策略(
tools.exec.ask),无「按频道」维度,不能仅对 QQ 关掉审批而不影响其他频道。
[Bug] QQ 审批按钮点击后无任何反应:qqbot 网关连接未启动,INTERACTION_CREATE 从未路由到审批处理器a
环境
D:\nodejs\node.exeD:\nodejs\node_modules\openclaw\dist\index.js gateway --port 18789(core 包,PID 41692,启动 2026-08-13 20:39:50)1905295106,clientSecret 已配置,connected)C:\Users\LPLR\.openclaw\extensions\qqbot\dist/(即仓库tencent-connect/openclaw-qqbot)tools.exec.ask = "always"(保持不变,非本 bug 成因)现象
QQ 私聊中,需要执行 shell 命令时龙虾下发审批按钮卡(✅ 允许一次 / ❌ 拒绝)。用户点击「✅ 允许一次」后:
agent.run.finished status=blocked结束(exec仅tool.action.started,无finished);同一审批若改在 OpenClaw 控制 UI(
http://127.0.0.1:18789) 点击批准则正常执行。说明问题仅在 QQ 按钮路径,审批系统本身可用。复现
tools.exec.ask = "always",QQ 频道 connected。exec)。blocked。诊断过程与证据(已实测)
在 qqbot 扩展的多处加了写文件诊断埋点(调试日志
zh-patches/qqbot-approval-debug.log),重启网关后观察:gateway-pJQppxe4.js模块顶层MODULE_LOADEDindex.js顶层INDEX_LOADED_USERGatewayConnection.start()首行CONN_STARTws.on("open")CONN_OPENws.on("message")dispatchcreateInteractionHandler()顶部interactionHandlerhandleMessage()顶部HANDLE_MESSAGE同时,
audit_events显示:QQ 私聊消息能正常触发 run(C2C 路径工作),但点击审批按钮的 run 全部以blocked结束。根因
qqbot 审批交互的处理链路由扩展的
GatewayConnection承载:证据表明:核心网关(core
dist/index.js)并没有调用qqbotPlugin.gateway.startAccount,因此:GatewayConnection从未start()(CONN_START/CONN_OPEN不触发)→ 扩展的 ws 从不连接、从不接收事件;GatewayConnection上的onInteraction(审批处理器)从未被核心接线;INTERACTION_CREATE不被任何处理器接收 → 审批卡永远 pending/blocked。即:qqbot 通道的交互(按钮审批)处理器在运行时从未被启动/接线,这是 OpenClaw 核心与 qqbot 插件之间的集成缺陷,而非单纯的字段解析问题。
影响范围
tools.exec.ask=always安全规则本身无问题,不应为此关闭。建议修复(两层)
P0(核心集成,必须修才能恢复按钮审批):
qqbotPlugin.gateway.startAccount(或等价入口),确保GatewayConnection启动并把onInteraction接线到审批运行时(approval-handler-runtime的nativeRuntime.interactions适配器)。startAccount收到的ctx向核心注册onInteraction,而非仅挂在自身GatewayConnection上。P1(字段加固,P0 修好后生效):
resolveApprovalActorSenderIds()中,当user_openid/group_member_openid为空时,回退到 INTERACTION_CREATE 事件实际可用的发送者标识(event.openid、event.user_info.openid、event.data.user_openid、或递归扫描含openid|user_id|sender_id的键)。配合channels.qqbot.allowFrom:["*"],事件一旦到达 handler 即可授权。已尝试的本地补丁
extensions/qqbot/dist/gateway-pJQppxe4.js应用resolveApprovalActorSenderIds字段加固 + 诊断埋点,并重启加载(MODULE_LOADED 已确认)。临时绕过(可用)
http://127.0.0.1:18789/或 ClawX 桌面端,审批卡可正常点击批准,不影响tools.exec.ask=always安全规则。tools.exec.ask),无「按频道」维度,不能仅对 QQ 关掉审批而不影响其他频道。