QQ 机器人
QQ Bot 通过官方 QQ Bot API(WebSocket gateway)连接到 OpenClaw。
C2C 私聊和群聊 @ 提及是主要聊天类型,支持富媒体(图片、语音、视频、文件)。Guild 频道消息仅支持文本和远程 URL 图片;语音、视频、文件上传以及本地/Base64 图片在 Guild 频道中不可用。表情回应和话题在任何地方都不支持。
状态:官方可下载插件。
安装¶
如果机器人曾以 @openclaw/qqbot 安装在插件 ID qqbot 下,
openclaw plugins update qqbot 和 openclaw update 会将其重写为
@tencent-connect/openclaw-qqbot,位于插件 ID openclaw-qqbot 下。频道
配置仍位于 channels.qqbot 下。
设置¶
- 前往 QQ Open Platform,使用手机 QQ 扫描二维码以注册 / 登录。
- 点击 创建机器人 以创建新的 QQ 机器人。
- 在机器人设置页面找到 AppID 和 AppSecret 并复制它们。
Note
在离开 QQ Open Platform 页面之前保存 AppSecret;否则,你将需要重新生成它。
- 添加频道:
- 检查
openclaw channels status --probe;如果 Gateway 离线,请启动 Gateway。配置更改遵循 热重载。
入站持久性¶
对于 QQ gateway 轮次事件,OpenClaw 会在推进已保存的 gateway 恢复序列之前持久化原始事件。待处理或可重试的轮次在 Gateway 重启后仍然保留,按会话保持串行化,并使用提供方事件 ID 在活动或保留的完成记录存在期间抑制重复队列条目。
如果持久化准入失败,OpenClaw 会终止当前 gateway 套接字,而不推进序列。重连/恢复路径随后可以再次请求未提交的事件。在队列到代理边界上,投递仍然是至少一次,因此交接期间的崩溃可能会重放一个轮次。
交互式设置:
向导还提供二维码绑定,作为手动输入 AppID/AppSecret 的替代方式:使用与目标 QQ Bot 关联的手机应用扫描二维码以完成绑定。OpenClaw 会在账户的配置作用域下持久化返回的凭据。
配置¶
最小配置:
{
channels: {
qqbot: {
enabled: true,
dmPolicy: "open",
allowFrom: ["openclaw:approval-disabled"],
appId: "YOUR_APP_ID",
clientSecret: "YOUR_APP_SECRET",
},
},
}
这些示例通过 dmPolicy: "open" 保持直接消息开放,同时
openclaw:approval-disabled 标记使原生审批操作保持禁用。
若要启用这些操作,请用具体的审批人 QQ OpenID 替换该标记。
默认账户环境变量(仅限顶层账户):
QQBOT_APP_IDQQBOT_CLIENT_SECRET
使用 SecretRef 将 AppSecret 保留在频道配置之外。对于基于环境的密钥:
{
channels: {
qqbot: {
enabled: true,
dmPolicy: "open",
allowFrom: ["openclaw:approval-disabled"],
appId: "YOUR_APP_ID",
clientSecret: {
source: "env",
provider: "default",
id: "QQBOT_CLIENT_SECRET",
},
},
},
}
对于基于文件的 AppSecret,请配置一个 singleValue 文件提供方:
{
secrets: {
providers: {
qqbot_secret: {
source: "file",
path: "/path/to/qqbot-secret.txt",
mode: "singleValue",
},
},
},
channels: {
qqbot: {
enabled: true,
dmPolicy: "open",
allowFrom: ["openclaw:approval-disabled"],
appId: "YOUR_APP_ID",
clientSecret: { source: "file", provider: "qqbot_secret", id: "value" },
},
},
}
注意:
openclaw channels add --channel qqbot --token-file ...仅设置 AppSecret;appId必须已在配置或QQBOT_APP_ID中设置。之后运行openclaw doctor --fix以迁移旧的文件设置。clientSecret接受明文或基于环境、文件、exec 或存储的 SecretRef。OpenClaw 会在将凭据交给 QQ Bot 插件之前解析该引用。clientSecretFile是仅用于迁移的旧设置。openclaw doctor --fix会将其替换为基于文件的clientSecretSecretRef。新配置应直接使用clientSecret。- 顶层凭据和环境回退仅属于默认账户。命名账户配置自己的
appId和clientSecret。
流式传输¶
{
channels: {
qqbot: {
streaming: {
mode: "partial", // block streaming: "partial" (default) or "off"
nativeTransport: true, // use QQ's official C2C stream_messages API for DMs
},
},
},
}
streaming.mode: "off"禁用该账户的块流式传输。streaming.nativeTransport: true通过 QQ 官方stream_messagesAPI 流式传输 C2C(DM)回复;群聊/频道目标不受影响。- 旧版
streaming: true|false标量和streaming.c2cStreamApi键 会通过openclaw doctor --fix迁移到此结构。 /bot-streaming on|off可从 DM 切换相同配置。
访问策略¶
allowFrom/groupAllowFrom控制谁可以在 C2C / 群聊上下文中与机器人聊天。dmPolicy/groupPolicy(open|allowlist|disabled) 控制执行模式。一旦allowFrom具有具体(非通配符)条目,dmPolicy默认为allowlist,否则为open。 一旦groupAllowFrom或allowFrom具有具体条目,groupPolicy默认为allowlist,否则为open。contextVisibility控制 QQ 作为补充上下文提供的 引用消息文本。默认值"all"会保留收到的引用文本。 设置"allowlist"可仅在引用发送者通过配置的发送者策略时包含引用正文, 或设置"allowlist_quote"以保留显式引用,同时过滤其他补充上下文。参见 群组。- “Auth: allowlist” 斜杠命令要求在
allowFrom(对于群聊调用则为groupAllowFrom)中显式包含非通配符条目, 无论dmPolicy/groupPolicy如何 — 参见 斜杠命令。
多账户设置¶
在单个 OpenClaw 实例下运行多个 QQ 机器人:
{
channels: {
qqbot: {
enabled: true,
dmPolicy: "open",
allowFrom: ["openclaw:approval-disabled"],
appId: "111111111",
clientSecret: { source: "env", provider: "default", id: "QQBOT_DEFAULT_SECRET" },
accounts: {
bot2: {
enabled: true,
dmPolicy: "open",
allowFrom: ["openclaw:approval-disabled"],
appId: "222222222",
clientSecret: { source: "env", provider: "default", id: "QQBOT_BOT2_SECRET" },
},
},
},
},
}
每个账户拥有独立的 WebSocket 连接、API 客户端和 token 缓存,并以 appId 作为键。日志行会标记所属账户 id,因此在同一个 Gateway 下运行多个机器人时,诊断信息仍可区分。
启动时,缺失的 SecretRef 值只会使其所属账户不可用;健康的同级账户和 Gateway 仍保持可用。显式失败的引用不会回退到环境变量或插件备份凭据。格式错误的引用和未知的密钥提供程序仍会导致启动或重新加载失败。重新加载时,未更改的账户可以保留其最后已知良好的凭据;参见 密钥运行时模型。
通过 CLI 添加第二个机器人:
群聊¶
群聊支持使用 QQ 群 OpenID,而不是显示名称。将机器人添加到群中,然后提及它,或配置群聊以无需提及即可运行。
{
channels: {
qqbot: {
groupPolicy: "allowlist",
groupAllowFrom: ["member_openid"],
groups: {
"*": {
requireMention: true,
commandLevel: "all",
historyLimit: 50,
tools: { deny: ["exec", "read", "write"] },
},
GROUP_OPENID: {
name: "Release room",
requireMention: false,
ignoreOtherMentions: true,
commandLevel: "safety",
historyLimit: 20,
prompt: "Keep replies short and operational.",
},
},
},
},
}
groups["*"] 为所有群设置默认值;具体的 groups.GROUP_OPENID 条目会覆盖某个群的这些默认值。群设置:
| 字段 | 默认值 | 说明 |
|---|---|---|
requireMention |
true |
在机器人回复前要求 @ 提及。 |
commandLevel |
all |
哪些内置斜杠命令可以在群中运行(见下文)。 |
ignoreOtherMentions |
false |
丢弃提及他人但未提及机器人的消息。 |
historyLimit |
50 |
保留最近的未提及消息,作为下一次被提及回合的上下文。0 禁用历史。 |
tools |
— | 允许/拒绝整个群使用的工具。 |
toolsBySender |
— | 按发送者的工具覆盖;参见 群组。 |
name |
openid 前缀 | 用于日志和群上下文的友好标签。 |
prompt |
内置默认值 | 追加到代理上下文的按群行为提示。 |
commandLevel 接受:
| 级别 | 行为 |
|---|---|
all |
现有内置命令保持可用。部分命令仍从菜单中隐藏,但授权用户仍可在群中运行它们。 |
safety |
/help、/btw、/stop 在群中保持可见;敏感命令(/config、/tools、/bash 等)必须在私聊中运行。 |
strict |
仅允许严格运行所需的群会话控制。/stop 仍然有效,授权发送者可以中断正在运行的任务。 |
旧的 QQBot toolPolicy 条目已弃用。运行 openclaw doctor --fix 将它们迁移到 tools。
激活模式为 mention 和 always。requireMention: true 映射到 mention;requireMention: false 映射到 always。如果存在会话级激活覆盖,则优先于配置。
入站队列按对端划分。群对端拥有更大的队列上限(50,而直接对端为 20),队列满时会先驱逐机器人发送的消息,再驱逐人类消息,并将普通群消息突发合并为一个带归属的回合。斜杠命令逐条运行,独立于任何合并批次。
语音(STT / TTS)¶
STT 和 TTS 支持两级配置,并带有优先级回退:
| 设置 | 插件特定 | 框架回退 |
|---|---|---|
| STT | channels.qqbot.stt |
第一个支持音频的 tools.media.models[] 条目 |
| TTS | channels.qqbot.tts、channels.qqbot.accounts.<id>.tts |
tts |
{
channels: {
qqbot: {
stt: {
provider: "your-provider",
model: "your-stt-model",
},
tts: {
provider: "your-provider",
model: "your-tts-model",
voice: "your-voice",
},
accounts: {
"qq-main": {
tts: {
providers: {
openai: { voice: "shimmer" },
},
},
},
},
},
},
}
将任一配置项设置为 enabled: false 即可禁用。账户级 TTS 覆盖使用与 tts 相同的结构,并深度合并到频道/全局 TTS 配置之上。
STT 请求默认在 60 秒后超时。插件特定的 STT 使用所选 models.providers.<id>.timeoutSeconds 覆盖。框架音频 STT 使用所选支持音频的 tools.media.models[] 条目的 timeoutSeconds,然后使用所选提供商覆盖。
传入的 QQ 语音附件会以音频媒体元数据的形式暴露给代理,同时避免将原始语音文件放入通用 MediaPaths。在纯文本回复中使用 [[audio_as_voice]] 会在已配置 TTS 时合成 TTS 并发送原生 QQ 语音消息。
出站音频上传/转码行为也可以通过 channels.qqbot.audioFormatPolicy 进行调整:
sttDirectFormatsuploadDirectFormatstranscodeEnabled
目标格式¶
| 格式 | 描述 |
|---|---|
qqbot:c2c:OPENID |
私聊 (C2C) |
qqbot:group:GROUP_OPENID |
群聊 |
qqbot:channel:CHANNEL_ID |
频道 |
Note
每个机器人都有自己的一组用户 OpenID。Bot A 接收到的 OpenID 不能用于通过 Bot B 发送消息。
斜杠命令¶
在 AI 队列之前拦截的内置命令:
| 命令 | 认证 | 范围 | 描述 |
|---|---|---|---|
/bot-ping |
— | 任意 | 延迟测试 |
/bot-help |
— | 任意 | 列出所有命令 |
/bot-me |
— | 仅私聊 | 显示发送者的 QQ 用户 ID(openid),用于配置 allowFrom / groupAllowFrom |
/bot-version |
— | 仅私聊 | 显示 OpenClaw 框架版本和插件版本 |
/bot-upgrade |
— | 仅私聊 | 显示 QQBot 升级指南链接 |
/bot-approve |
允许列表 | 仅私聊 | 管理命令执行审批配置(on / off / always / reset / status) |
/bot-logs |
允许列表 | 仅私聊 | 将最近的网关日志导出为文件 |
/bot-clear-storage |
允许列表 | 仅私聊 | 删除 QQBot 媒体目录下的缓存下载 |
/bot-streaming |
允许列表 | 仅私聊 | 切换 C2C 流式回复 |
/bot-group-allways |
允许列表 | 仅私聊 | 切换默认群激活模式(需要提及 vs. 始终开启) |
在任何命令后追加 ? 可获取使用帮助(例如 /bot-upgrade ?)。
“认证:允许列表”命令还要求发送者的 openid 位于显式的非通配符 allowFrom 列表中(对于群内发出的命令,groupAllowFrom 优先,回退到 allowFrom)。通配符 allowFrom: ["*"] 允许聊天,但不允许这些命令。在私聊之外运行其中任一命令,或未获得授权时,会返回提示,而不是静默丢弃消息。
/bot-me、/bot-version 和 /bot-upgrade 仅限私聊,但不需要允许列表——任何 C2C 发送者都可以运行它们。
当 QQ Bot 执行审批使用默认的同一聊天回退时,原生审批按钮点击遵循相同的显式非通配符命令允许列表。若要仅授予审批权限而不授予更广泛的命令权限,请配置 channels.qqbot.execApprovals.approvers。原生执行审批默认启用。
媒体与存储¶
- 传入、出站以及网关桥接媒体共享位于
~/.openclaw/media/qqbot下的同一载荷根目录(设置OPENCLAW_HOME时遵循该变量),因此上传、下载和转码缓存都保留在一个受保护的目录中。 - 面向 C2C 和群目标的富媒体投递通过同一条
sendMedia路径进行。大小达到 5 MiB 或更大的本地文件和内存缓冲区使用 QQ 的分块上传端点;较小的载荷以及远程 URL/Base64 源使用一次性上传 API。 - 如果热升级在 Gateway 完成写入
openclaw.json之前中断,插件会在下次启动时从内部快照恢复该账户最后已知的appId/clientSecret(绝不覆盖有意进行的配置更改),因此无需重新扫描二维码。
故障排查¶
- Gateway 无法启动 / 没有传入消息: 请确认
appId和clientSecret正确,并且机器人已在 QQ 开放平台上启用。缺少凭据会显示为“QQBot not configured (missing appId or clientSecret)”。 - 使用
--token-file设置后仍显示未配置:--token-file仅设置 AppSecret。仍需在配置或QQBOT_APP_ID中设置appId。 - 突发群回复发生冲突: 当某个对端的队列填满时,传入队列会优先移除机器人发送的消息,而不是人类消息,并将突发的大量普通(非命令)群消息合并为一个归属轮次,因此大量机器人消息不应导致人类消息被饿死。
- 主动消息未送达: 如果用户最近未进行交互,QQ 可能会阻止机器人发起的消息。
- 语音未转写: 请确保已配置 STT,并且提供商可访问。
相关¶
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw