QClaw客户端架构与Queue Guard排队机制探索
腾讯安全管家推出的Qclaw,每天送4000万免费Tokens,基本上每天都在更新,目前支持多Agent,界面美观实用方便,是目前本地部署openclaw的最佳选择。
以下为探索记录:
“当前为高峰期,已为您暂停任务。” 的问题- 配置的覆盖机制和自定义配置的实现
一、架构关系
| |
二、关键机制
1. 启动顺序
| |
2. 配置管控
| 配置层级 | 谁管控 | 示例 |
|---|---|---|
| 客户端管控字段 | QClaw Electron | messages.queue.mode、channels、models.baseUrl |
| Agent 可修改字段 | OpenClaw / AI | skills.entries、session.maintenance |
| 共享字段 | 双方都可写 | Electron 启动时会重新同步 |
3. 认证链
| |
4. 资源调度
| |
5. 日志机制
- 浏览器日志在
C:\Users\you\.qclaw\browser\openclaw\user-data\Default\LOG(Chromium 日志)
| |
6. 修改失败的原因
| |
7. 总结
- QClaw Electron = 管理者(壳),负责 UI、认证、资源调度、配置同步
- OpenClaw Gateway = 执行者(引擎),负责 AI 对话、工具调用、插件运行
- Electron 对 Gateway 拥有最终控制权,包括配置覆盖和进程生命周期
要修改
messages.queue.mode,需要在 **QClaw 客户端设置** 里改,而不是通过 OpenClaw API。
三、默认配置文件
QClaw 的客户端默认配置文件在:
| |
这就是 QClaw Electron 启动时用来同步/覆盖用户配置的模板文件。
对比
| 字段 | 默认模板 | 你的用户配置 | 说明 |
|---|---|---|---|
messages.queue.mode | followup | followup | 被模板覆盖回来了 |
queue-guard.enabled | true | true | 两者一致 |
models.providers.qclaw.baseUrl | ${QCLAW\_LLM\_BASE\_URL} | ${QCLAW\_LLM\_BASE\_URL} | 模板占位符 |
channels.wechat-access.guid | ${QCLAW\_USER\_GUID} | 实际值 | Electron 启动时替换 |
channels.wechat-access.token | "" (空) | 实际值 | Electron 启动时填入 |
session.maintenance | 365d/100万/1gb | 同左 | 一致 |
机制
| |
结论
messages.queue.mode: "followup" 硬编码在默认模板里,每次 QClaw 启动都会强制写回。要通过 AI 修改这个值,需要同时修改默认模板文件,但那个文件在 Program Files 下,需要管理员权限,且 QClaw 更新后会被还原。
正确的修改方式是在 QClaw 客户端的设置界面里操作,这样 Electron 会在自己的管理层记录这个变更,启动时不会再覆盖。
四、queue-guard(模型排队守卫)
定位
L2 中间件层插件,不注册 Channel/Route/Command,只拦截 globalThis.fetch。
解决什么问题
QClaw 使用共享模型资源,高峰期请求过多时直接发出去会被拒。queue-guard 在请求发出前先排队,等资源空闲再放行,避免无意义的失败请求。
工作流程
| |
拦截范围
- 拦截:model 包含
modelroute的请求(QClaw 默认路由模型) - 放行:自定义模型(如
deepseek-chat、本地模型)直接通过,不排队 - 放行:所有非 LLM 请求(GET、无 body、不含
messages数组的)
4 个源码模块
| 文件 | 作用 |
|---|---|
index.ts | 插件入口,注册钩子、HTTP endpoint、Gateway Method |
src/interceptor.ts | fetch 拦截器核心,识别 LLM 请求并触发排队 |
src/queue-api.ts | 排队状态管理、轮询逻辑、会话-排队状态关联 |
src/aes-decrypt.ts | AES-128-CBC 解密用户 JWT token |
src/jprx-sign.ts | JPrx 防重放签名 |
可配置参数
跨插件通信
通过 globalThis 上的 EventBus 广播事件:
queue-guard:state— 排队状态变更(排队中/就绪/超时)queue-guard:notify— 排队进度通知,钉钉/微信插件监听此事件向用户展示排队提示
关键设计原则
- fail-open — 排队接口异常或超时时直接放行,绝不阻塞用户
- 不侵入其他插件 — 纯 fetch 拦截,不修改任何其他插件源码
- 全渠道统一生效 — 主会话、微信、钉钉等所有渠道的 LLM 请求都会经过排队
遇到的问题
“当前为高峰期,已为您暂停任务。” 就是 interceptor.ts 里硬编码的伪造响应文本,在排队被用户中止时返回。
这不是 AI 生成的,而是插件的兜底行为。
五、问题分析
原因是两个机制叠加:
直接原因
queue-guard 排队 + followup 模式冲突
配置:
followup 模式下,新消息进来会自动取消上一个未完成的请求。
流程是这样的:
| |
为什么没中断
session 一条条发,没有重复发送,所以请求能正常完成。
根本问题
高峰期 + followup 模式 = 容易互相取消请求
六、建议
如果中断频繁,有两个思路:
- 发完消息等一等(不要重复发送),排队最多 2 分钟会自动放行
- 把 queue mode 改成其他模式
queue mode 模式说明
| 模式 | 说明 |
|---|---|
followup | 新消息取消上一个未完成的请求 |
steer | 新消息转发给当前运行中的 agent(不取消) |
steer-backlog | steer + 消息积压 |
steer+backlog | 同上 |
collect | 收集一批消息后一起处理 |
queue | 先进先出排队 |
interrupt | 中断当前请求 |