Skip to content

How to Integrate AstrBot with WeChat and QQ: Multi-platform Chatbot Setup

Problem

I wanted to deploy a single chatbot instance that works across QQ, WeChat Work, and WeChat Official Accounts. But when I tried to connect NapCatQQ to AstrBot, I got connection refused errors:

connection error
[ERROR] WebSocket connection failed: Connection refused
[ERROR] Failed to connect to ws://localhost:6199/ws

And when I configured WeChat Work webhooks, messages weren’t reaching AstrBot at all. The multi-platform setup seemed impossible.

Environment

  • AstrBot (latest version via Docker)
  • NapCatQQ for QQ integration
  • WeChat Work (企业微信) enterprise account
  • Docker and Docker Compose
  • Ubuntu 22.04 server

What Happened?

I was building a customer service bot for a Chinese company. They needed the same bot to work on QQ groups, WeChat Work internal groups, and their WeChat Official Account.

Here’s what I tried first - running AstrBot and NapCatQQ separately:

initial setup
# Started AstrBot
docker run -d -p 6185:6185 -p 6199:6199 --name astrbot soulter/astrbot:latest
# Started NapCatQQ separately
docker run -d --name napcat mlikiowa/napcat-docker:latest

Then I configured AstrBot’s OneBot v11 adapter in the WebUI:

AstrBot OneBot v11 config
id: "qq-bot-1"
enabled: true
reverse_ws_host: "0.0.0.0"
reverse_ws_port: 6199
reverse_ws_token: ""

In NapCatQQ’s web UI, I set the reverse WebSocket URL to:

websocket-url-initial.txt
ws://localhost:6199/ws

But when I sent a message on QQ, nothing happened. No response from the bot.

Understanding the Architecture

AstrBot uses a modular adapter system. Each platform gets its own adapter type:

architecture diagram
┌─────────────────┐
│ AstrBot Core │
│ (Event Bus + │
│ LLM Provider) │
└────────┬────────┘
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ AIOCQHTTP │ │ GEWECHAT │ │ QQOFFIC │
│ (QQ via │ │ (WeChat │ │ (WeChat │
│ NapCat) │ │ Work) │ │ Official)│
└───────────┘ └───────────┘ └───────────┘
│ │ │
▼ ▼ ▼
QQ NT Client Webhook URL Server Config
+ NapCatQQ (HTTPS) (Token + Encoding)

The key insight: all adapters can run simultaneously, sharing the same LLM provider and plugins.

How I Solved QQ Integration

The connection refused error had two causes:

  1. Docker networking: localhost doesn’t work between containers
  2. Port binding: I needed the reverse WebSocket port exposed

I found that NapCat provides a pre-configured compose file for AstrBot:

docker compose setup
mkdir astrbot && cd astrbot
wget https://raw.githubusercontent.com/NapNeko/NapCat-Docker/main/compose/astrbot.yml
sudo docker compose -f astrbot.yml up -d

This puts both containers on the same network automatically.

Solution 2: Manual Network Configuration

Since I already had containers running, I created a shared network:

manual network setup
sudo docker network create astrbot-net
sudo docker network connect astrbot-net astrbot
sudo docker network connect astrbot-net napcat
sudo docker restart astrbot
sudo docker restart napcat

Configuring the WebSocket URL

The URL depends on your deployment:

WebSocket URL scenarios
# Both AstrBot and NapCat in Docker (same network)
ws://astrbot:6199/ws
# Only NapCat in Docker, AstrBot on host
ws://host.docker.internal:6199/ws
# Both on host (no Docker)
ws://localhost:6199/ws
# NapCat on host, AstrBot in Docker
ws://<server-ip>:6199/ws

In NapCatQQ’s configuration, I set:

napcat-websocket-config.json
{
"Type": "ReverseWebSocket",
"Host": "astrbot",
"Port": 6199,
"Suffix": "/ws",
"ReconnectInterval": 5000,
"HeartBeatInterval": 5000,
"AccessToken": ""
}

Now when I restart NapCatQQ, I see the connection succeed:

connection success
[INFO] WebSocket connected to ws://astrbot:6199/ws
[INFO] OneBot v11 adapter registered: qq-bot-1

WeChat Work Integration

WeChat Work uses webhooks instead of WebSocket. This is simpler but has its own quirks.

Step 1: Create the Robot

In WeChat Work admin console:

  1. Go to Application Management > Robots
  2. Create a new robot in an internal group
  3. Copy the webhook URL

Step 2: Configure AstrBot Adapter

In AstrBot WebUI, I added a GEWECHAT adapter:

WeChat Work adapter config
id: "wecom-bot"
enabled: true
webhook_url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR-KEY"

But there’s a problem: WeChat Work robots can only send messages, not receive them through webhooks.

Step 3: Enable Webhook-Only Mode

For bidirectional communication, I needed to use AstrBot’s unified webhook mode:

platform-specific-settings.json
{
"platform_specific": {
"wecom_bot": {
"enable": true,
"streaming": true,
"webhook_only": true
}
}
}

The webhook_only setting bypasses WeChat Work’s single-bubble limitation. The trade-off: no typing animation, but complex messages (cards, images) work.

Step 4: Set Up the Webhook Endpoint

AstrBot generates a webhook URL when you create a GEWECHAT adapter:

generated-webhook-url.txt
https://your-server.com/webhook/astrbot-uuid-here

I pointed my reverse proxy (nginx) to AstrBot’s port 6185:

nginx config
location /webhook/ {
proxy_pass http://127.0.0.1:6185;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

Important: WeChat requires HTTPS. I used Let’s Encrypt for the SSL certificate.

WeChat Official Account Setup

WeChat Official Accounts are more complex. They use a server configuration push/pull model.

Prerequisites

  • Verified WeChat Official Account (not personal)
  • Server with public IP and domain
  • SSL certificate (HTTPS required)

Configuration in AstrBot

I added another adapter for the Official Account:

WeChat Official Account config
id: "wechat-official"
enabled: true
adapter_type: "GEWECHAT"
token: "my-secret-token"
encoding_aes_key: "generated-43-char-key"

Then in WeChat Official Account admin console:

  1. Go to Settings > Basic Configuration
  2. Set Server URL: https://your-domain.com/webhook/wechat-official
  3. Set Token: my-secret-token
  4. Set EncodingAESKey: generated-43-char-key
  5. Enable message encryption

The verification request from WeChat will hit your endpoint. AstrBot handles the signature validation automatically.

Managing Multiple Platforms

Now I had three adapters running. But I needed to handle platform-specific behavior.

Platform-Specific Settings

AstrBot stores platform settings in platform_specific:

full-platform-config.json
{
"platform_specific": {
"qq_bot_1": {
"pre_ack_emoji": {
"enable": true,
"emoji": "👀"
}
},
"wecom_bot": {
"streaming": true,
"webhook_only": true
},
"wechat_official": {
"rate_limit": {
"max_messages_per_minute": 5
}
}
}
}

The pre_ack_emoji sends a reaction before the LLM responds - useful for QQ where users expect immediate feedback.

Rate Limiting Differences

Each platform has different limits:

PlatformLimitNotes
QQ (NapCat)~20 msg/minPer group
WeChat Work~30 msg/minPer robot
WeChat Official5 msg/secGlobal

I configured this in AstrBot’s main settings:

rate limit config
rate_limit:
enabled: true
default_limit: 20
platform_overrides:
wechat_official: 5

Event Filtering in Plugins

When writing plugins, I needed to filter by platform:

multi-platform-plugin.py
from astrbot.api.event import filter, AstrMessageEvent, PlatformAdapterType
from astrbot.api.star import Context, Star, register
@register("multi_platform_greeting", "author", "Greeting plugin", "1.0.0", "repo")
class MultiPlatformGreeting(Star):
def __init__(self, context: Context):
super().__init__(context)
@filter.command("hello")
async def hello(self, event: AstrMessageEvent):
# Different response per platform
if event.platform_meta.platform_name == "GEWECHAT":
yield event.plain_result("您好!我是您的专属助手。")
elif event.platform_meta.platform_name == "AIOCQHTTP":
yield event.plain_result("你好!我是你的QQ机器人。")
else:
yield event.plain_result("Hello! I'm your chatbot.")
@filter.platform(PlatformAdapterType.GEWECHAT)
@filter.command("wechat_help")
async def wechat_help(self, event: AstrMessageEvent):
# This only triggers on WeChat platforms
yield event.plain_result("WeChat帮助信息...")

The @filter.platform() decorator ensures the command only works on specific platforms.

Common Issues I Encountered

Issue 1: NapCat Connection Refused

Symptoms: AstrBot shows no incoming messages from QQ.

Causes:

  • Wrong WebSocket URL (using localhost in Docker)
  • Port not exposed
  • Different Docker networks

Fix:

check-network-connectivity.sh
# Check if NapCat can reach AstrBot
docker exec napcat ping astrbot
# Verify port is listening
docker exec astrbot netstat -tlnp | grep 6199

Issue 2: WeChat Work Messages Not Received

Symptoms: Webhook tests work, but group messages don’t reach AstrBot.

Cause: WeChat Work robots don’t receive messages through webhooks by default.

Fix: Use the robot in “at” mode - users must @mention the robot for it to respond.

Issue 3: WeChat Official Account Verification Failed

Symptoms: WeChat admin console shows “Token verification failed”.

Cause: Signature mismatch or wrong endpoint.

Fix:

debug-wechat-endpoint.sh
# Check AstrBot logs
docker logs astrbot | grep -i wechat
# Verify endpoint is accessible
curl -v https://your-domain.com/webhook/wechat-official

The endpoint should return the echostr parameter for GET requests.

Deployment Best Practices

Running as a Service

I created a systemd service for AstrBot:

/etc/systemd/system/astrbot.service
[Unit]
Description=AstrBot Multi-Platform Chatbot
After=docker.service
Requires=docker.service
[Service]
Type=simple
User=astrbot
WorkingDirectory=/opt/astrbot
ExecStart=/usr/bin/docker compose -f astrbot.yml up
ExecStop=/usr/bin/docker compose -f astrbot.yml down
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target

Security Considerations

  1. Access tokens: Never commit tokens to git. Use environment variables.
  2. HTTPS: Required for WeChat webhooks.
  3. IP whitelisting: WeChat allows IP restrictions for Official Accounts.
  4. Rate limiting: Prevents bot abuse.
environment setup
# Create .env file
echo "NAPCAT_TOKEN=$(openssl rand -hex 16)" > .env
echo "WECHAT_TOKEN=$(openssl rand -hex 16)" >> .env

The Reason for These Issues

The core problem is that each Chinese IM platform uses different protocols:

  • QQ: OneBot v11 over WebSocket (community standard)
  • WeChat Work: Proprietary webhooks with rate limits
  • WeChat Official: Server configuration with signature validation

AstrBot abstracts these differences through adapter types. The AIOCQHTTP type handles OneBot v11 (QQ), while GEWECHAT handles WeChat variants.

The Docker networking issue is common: containers on different networks can’t communicate via localhost. Either use Docker Compose (automatic network) or manually connect containers.

Summary

In this post, I showed how to integrate AstrBot with QQ, WeChat Work, and WeChat Official Accounts simultaneously. The key points are:

  1. Use Docker Compose for QQ integration to avoid network issues
  2. WeChat Work requires webhook-only mode for bidirectional messaging
  3. WeChat Official Accounts need HTTPS and proper token configuration
  4. Platform-specific settings handle differences in rate limits and features
  5. Event filtering in plugins enables platform-aware behavior

The unified architecture means one LLM provider and one plugin system serves all platforms. This reduces maintenance overhead and ensures consistent behavior across channels.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments