OpenClaw + QQ Plugin Integration and Extra-Long Troubleshooting Postmortem (End-to-End)
Note: This postmortem is organized according to the steps actually executed, focusing on the full process from integration and joint debugging to locating the core issue, as well as each key conclusion.
I. Background and Goals
The goal this time was to connect OpenClaw to the QQ channel (based on NapCat + the openclaw_qq plugin) and achieve:
- Normal send/receive for QQ private chats and group chats
- Conversation routing and WebUI records visible
- Admin/blacklist policies controllable (to prevent Token abuse)
- Configuration can be stably saved in Control UI
II. Environment and Timeline (Rough)
Based on gateway log timestamps, this investigation spanned multiple phases, with continuous high-intensity troubleshooting for several hours (about 4+ hours).
III. Main Workflow (By Phase)
1) QQ Channel Integration and Basic Joint Debugging
I first completed the basic deployment of the QQ plugin and NapCat:
- Install and enable the
openclaw_qqplugin - Deploy NapCat using Docker
- Fix the NapCat connection mode to Forward WS Server (OpenClaw connects in as the client)
- After aligning the OneBot Token and account, the QQ channel status returned to
OK
2) Conversation and Routing Issue Fixes
During joint debugging, there was a phenomenon where “QQ conversations got mixed into the main conversation/TG conversation”, so I fixed routing:
- Fix QQ group/direct route parsing
- Prevent QQ writes from overwriting main conversation metadata
- Ensure QQ and TG conversations can be separated and traced
Result: QQ conversation visibility in the WebUI improved significantly.
3) Context and Duplicate Message Policy Adjustments
To address the issue of “QQ bringing a long history every time causing noise”:
- Change the default
historyLimitto0 - Document clearly: by default rely on the OpenClaw conversation system, do not force concatenating the group original text
- Only enable history concatenation when the user explicitly needs it
At the same time, I fixed logic related to repeated triggers and repeated prompts:
- Adjust the admin restriction check order to: trigger conditions first (@/keywords) and then authorization
- Add cooldown debouncing to non-admin prompts (default 10 seconds)
- Fix a possible prompt loop in reply-to-bot scenarios
4) Admin/Blacklist Capability Enhancements
To prevent abuse, I added and strengthened capabilities:
adminOnlyChatnotifyNonAdminBlockednonAdminBlockedMessageblockedNotifyCooldownMs
The blacklist logic was ultimately confirmed as:
- Messages from users that hit
blockedUsersare ignored directly (no reply, no prompt)
5) Control UI and Configuration Saving Issue (Key)
The most time-consuming and most critical issue was:
- On the
/configpage, changing only the QQ allow/deny list still reportsinvalid config - The error points to
models.providers.*.models[0].maxTokens
Final conclusions after locating the issue:
/configsaves the whole package, not just submittingchannels.qq- During whole-package validation, if any field is abnormal, the entire save fails
maxTokensis incorrectly processed in some paths (stringified / false-positive redaction), causing whole-package validation to fail- So it looks like “changing the QQ number causes a model error”, but in essence it is “whole-package validation collateral damage”
IV. Why It Looks Like “Changing the QQ Number Drags in maxTokens”
In one sentence: not business coupling, but save-mechanism coupling.
- You change the QQ fields
- It triggers writing back the entire configuration
- In the full configuration, the model field type drifts (e.g.,
maxTokensbecomes a string/invalid) - Validation fails, and the error bubbles up to the frontend
V. Repo and Local Sync Actions
I continuously fixed issues in the plugin repository and pushed multiple times, including:
- Admin policy fixes
- Conversation routing fixes
- Default value adjustments for history injection
- Frontend schema compatibility improvements
- Documentation enhancements (Chinese examples)
- Added NapCat docker deployment files
- Ignored runtime directories to prevent repo pollution
At the same time, local .openclaw/extensions/qq was kept in sync with the remote main branch.
VI. About “Can This Be Fully Solved by Only Changing the QQ Plugin”
Conclusion:
- It can solve the QQ plugin’s internal behavior and most usability issues
- But it cannot彻底 fix OpenClaw Core’s whole-package save pipeline problem from the plugin layer
- Because
models.*validation belongs to OpenClaw Core and is outside the QQ plugin’s scope
VII. Actionable Recommendations (Final)
Short-term Usable (No Core Changes)
- Use the CLI to modify QQ allow/deny lists to avoid the
/configwhole-package save path:
openclaw config set channels.qq.admins '"1838552185"' --json
openclaw config set channels.qq.blockedUsers '"342571216"' --json
openclaw gateway restart
Mid-term Recommendation (Root Fix)
- Wait for / follow up on OpenClaw’s official fix for this type of issue (
maxTokens+ redaction + config save) - Or submit a minimal reproduction and a patch PR to the official repo
VIII. Lessons Learned
- When troubleshooting the
/configpage, always think in terms of “whole-package validation”; don’t stare only at the changed item - If configuration redaction uses broad matching (e.g.,
/token/i), it can false-positive matchmaxTokens - For chat plugins, the authorization order (trigger first, then authorize) is critical; otherwise it will cause noise in groups
- Debouncing and deduplication must be enabled by default; otherwise group chats will quickly amplify issues