OpenClaw on QQ Bot
The official plugin, AppID and AppSecret setup, group OpenIDs and command levels, streaming over the native C2C API, voice, and the per-bot OpenID rule
QQ Bot connects OpenClaw to QQ through the official QQ Bot API over a WebSocket gateway. Private chat and group mentions are the primary chat types, with rich media, images, voice, video and files, while guild channels take text and remote-URL images only; reactions and threads are not supported anywhere. It ships as an official downloadable plugin from Tencent Connect, and an older install under the previous package name is rewritten to the new one on update while the channel config stays where it was. Here is the setup, durability, secrets, streaming, access policy, groups and their command levels, voice, targets, built-in commands, storage, and troubleshooting.
Setup and durability
- Register on the QQ Open Platform by scanning the QR code with the phone app, create a bot, and copy the AppID and AppSecret from its settings page; the secret is not stored in plaintext there, so leaving the page without saving it means regenerating a new one.
- Add the channel with a token made of the AppID and AppSecret joined by a colon, or run the interactive add command, which also offers QR-code binding with the phone app tied to the bot and persists the returned credentials under the account’s config scope; then probe the channel status and start the Gateway if it is offline.
- For gateway turn events OpenClaw persists the raw event before advancing the saved resume sequence, so pending or retryable turns survive a Gateway restart, stay serialised per conversation, and use the provider event id to suppress duplicate queue entries; if durable admission fails, the socket is terminated without advancing the sequence so the resume path can request the uncommitted event again. Delivery is at least once across the queue-to-agent boundary.
- Secrets come from the config as a plaintext string or a file path, or from default-account environment variables for the top-level account only; the token-file flag sets only the AppSecret, so the AppID must already exist, and the external package does not support structured secret references, so a config that uses one must move the secret to the environment variable or a file before upgrading.
Each bot has its own set of user OpenIDs. An OpenID received by Bot A cannot be used to send messages via Bot B.
Streaming, access, groups
Block streaming is on by default in partial mode and can be switched off per account, and a native-transport flag streams private-chat replies through QQ’s official stream-messages API without affecting group or channel targets; legacy scalar settings migrate through the doctor fix, and a bot-streaming command toggles the same setting from a DM. Access is gated by allow-from lists for private and group contexts with open, allowlist or disabled policies that default to allowlist once a concrete entry exists, a context-visibility setting decides whether quoted text QQ supplies as supplemental context is kept, filtered by the sender policy, or limited to explicit quotes, and several bots can run under one Gateway as named accounts, each with an isolated WebSocket connection, API client and token cache keyed by AppID and tagged in logs. Groups are addressed by OpenID rather than display name: a wildcard entry sets defaults and a concrete entry overrides one group, with a mention requirement on by default, a command level, an ignore-other-mentions flag, a history limit of fifty recent non-mention messages kept as context, tool allow and deny lists per group or per sender, a friendly name and a per-group prompt. Command levels are all, safety, which keeps help, btw and stop visible while sensitive commands must run in private chat, and strict, which allows only the group-session controls while stop keeps working; the inbound queue is per peer, with a larger cap for groups, eviction of bot-authored messages before human ones when full, and bursts of ordinary group messages merged into one attributed turn.
Voice, targets, commands, storage
- Speech-to-text and text-to-speech have two-level configuration with priority fallback, a plugin-specific provider and model or the framework’s first audio-capable media model and the global TTS config, with account-level TTS overrides deep-merged on top; STT requests time out after sixty seconds by default, inbound voice reaches the agent as audio metadata while raw files stay out of generic media paths, an audio-as-voice marker in a plain-text reply sends a native voice message, and an audio format policy tunes direct formats and transcoding.
- Targets are a private OpenID, a group OpenID or a guild channel id under the qqbot prefix. Built-in commands intercepted before the AI queue include ping, help, me to show the sender’s OpenID for allowlist setup, version, upgrade, approve for command-execution approval config, logs export, clear-storage, streaming and the group activation toggle; the allowlist-gated ones require an explicit non-wildcard entry, a wildcard permits chat but not those commands, and native exec-approval button clicks follow the same allowlist unless dedicated approvers are configured.
- Inbound, outbound and bridge media share one guarded payload root under the state directory, files of five mebibytes or more use QQ’s chunked upload endpoints while smaller ones use the one-shot API, and if a hot upgrade interrupts the Gateway before the config is fully written, the plugin restores the last-known AppID and secret from an internal snapshot on the next start without overwriting an intentional change.
OpenClaw on Feishu and Lark and OpenClaw on WeChat are the other China-centred channels in the catalogue, each with its own plugin and credential shape.
On Diali
QQ is not among the channels Diali connects today: WhatsApp, Telegram, Discord, Slack, Mattermost, Matrix, SMS and voice. Connect your first channel in five minutes explains how those are linked, and Diali security the boundary that applies to each.
Troubleshooting
A Gateway that does not start or receives nothing usually has a wrong AppID or secret or a bot not enabled on the platform, and a missing credential surfaces as a not-configured message; a token-file setup that still shows unconfigured is missing the AppID; colliding bursty group replies are handled by the queue’s eviction and merge rules; proactive messages can be blocked by QQ when the user has not interacted recently; and untranscribed voice means STT is not configured or reachable. Hosted OpenClaw on Diali is the assistant and OpenClaw plugins the surface this channel installs through.
- AppID plus AppSecret, joined by a colon.
- Groups by OpenID; three command levels.
- One bot’s OpenIDs never work for another.
Stop reading about it, build one
Set up an agent, pick a channel, and have it working inside the app you already keep open.
