微信ClawBot来了
白天先是在x上看到微信官方发的post,后面才是在微信公帐号看到很多的文章,今天也算是终于跟微信结合起来了,肯定效率是更加高+便捷的。安装微信ClawBot的几个前置条件。
1、微信是国内版本,并且升级到Version 8.0.70,可惜美区的wechat、PC版本的不行。
2、更新后从设置➡️插件,第一次会出现看不到(可能有缓存,我跟群里的小伙伴都遇到了),重启微信就可以解决

安装微信ClawBot
1 | openclaw plugins install "@tencent-weixin/openclaw-weixin" |
剩下的就是扫描登录,这里注意的是它绑定的是main agent。
微信插件安装了些什么?

1 | . |
绑定多个微信如何做?
信息来自代码里的README,最后我放一份。
Adding More WeChat Accounts
1 | openclaw channels login --channel openclaw-weixin |
Each QR code login creates a new account entry, supporting multiple WeChat accounts online simultaneously.
Multi-Account Context Isolation
By default, all channels share the same AI conversation context. To isolate conversation context for each WeChat account:
1 | openclaw config set agents.mode per-channel-per-peer |
This gives each “WeChat account + message sender” combination its own independent AI memory, preventing context cross-talk between accounts.
完整 README.md
OpenClaw’s WeChat channel plugin, supporting login authorization via QR code scanning.
Prerequisites
OpenClaw must be installed (the openclaw CLI needs to be available).
Quick Install
npx -y @tencent-weixin/openclaw-weixin-cli install
Manual Installation
If the quick install doesn’t work, follow these steps manually:
1. Install the plugin
openclaw plugins install "@tencent-weixin/openclaw-weixin"
2. Enable the plugin
openclaw config set plugins.entries.openclaw-weixin.enabled true
3. QR code login
openclaw channels login --channel openclaw-weixin
A QR code will appear in the terminal. Scan it with your phone and confirm the authorization. Once confirmed, the login credentials will be saved locally automatically — no further action is needed.
4. Restart the gateway
openclaw gateway restart
Adding More WeChat Accounts
openclaw channels login --channel openclaw-weixin
Each QR code login creates a new account entry, supporting multiple WeChat accounts online simultaneously.
Multi-Account Context Isolation
By default, all channels share the same AI conversation context. To isolate conversation context for each WeChat account:
openclaw config set agents.mode per-channel-per-peer
This gives each “WeChat account + message sender” combination its own independent AI memory, preventing context cross-talk between accounts.
Backend API Protocol
This plugin communicates with the backend gateway via HTTP JSON API. Developers integrating with their own backend need to implement the following interfaces.
All endpoints use POST with JSON request and response bodies. Common request headers:
| Header | Description |
|---|---|
Content-Type |
application/json |
AuthorizationType |
Fixed value ilink_bot_token |
Authorization |
Bearer <token> (obtained after login) |
X-WECHAT-UIN |
Base64-encoded random uint32 |
Endpoint List
| Endpoint | Path | Description |
|---|---|---|
| getUpdates | getupdates |
Long-poll for new messages |
| sendMessage | sendmessage |
Send a message (text/image/video/file) |
| getUploadUrl | getuploadurl |
Get CDN upload pre-signed URL |
| getConfig | getconfig |
Get account config (typing ticket, etc.) |
| sendTyping | sendtyping |
Send/cancel typing status indicator |
getUpdates
Long-polling endpoint. The server responds when new messages arrive or on timeout.
Request body:
{
"get_updates_buf": ""
}
| Field | Type | Description |
|---|---|---|
get_updates_buf |
string |
Sync cursor from the previous response; empty string for the first request |
Response body:
{
"ret": 0, "msgs": [...], "get_updates_buf": "<new cursor>", "longpolling_timeout_ms": 35000
}
| Field | Type | Description |
|---|---|---|
ret |
number |
Return code, 0 = success |
errcode |
number? |
Error code (e.g., -14 = session timeout) |
errmsg |
string? |
Error description |
msgs |
WeixinMessage[] |
Message list (structure below) |
get_updates_buf |
string |
New sync cursor to pass in the next request |
longpolling_timeout_ms |
number? |
Server-suggested long-poll timeout for the next request (ms) |
sendMessage
Send a message to a user.
Request body:
{
"msg":
{
"to_user_id": "<target user ID>",
"context_token": "<conversation context token>",
"item_list":
[
{
"type": 1,
"text_item":
{
"text": "Hello"
}
}
]
}
}
getUploadUrl
Get CDN upload pre-signed parameters. Call this endpoint before uploading a file to obtain upload_param and thumb_upload_param.
Request body:
{
"filekey": "<file identifier>",
"media_type": 1,
"to_user_id": "<target user ID>",
"rawsize": 12345,
"rawfilemd5": "<plaintext MD5>",
"filesize": 12352,
"thumb_rawsize": 1024,
"thumb_rawfilemd5": "<thumbnail plaintext MD5>",
"thumb_filesize": 1040
}
| Field | Type | Description |
|---|---|---|
media_type |
number |
1 = IMAGE, 2 = VIDEO, 3 = FILE |
rawsize |
number |
Original file plaintext size |
rawfilemd5 |
string |
Original file plaintext MD5 |
filesize |
number |
Ciphertext size after AES-128-ECB encryption |
thumb_rawsize |
number? |
Thumbnail plaintext size (required for IMAGE/VIDEO) |
thumb_rawfilemd5 |
string? |
Thumbnail plaintext MD5 (required for IMAGE/VIDEO) |
thumb_filesize |
number? |
Thumbnail ciphertext size (required for IMAGE/VIDEO) |
Response body:
{
"upload_param": "<original image upload encrypted parameters>",
"thumb_upload_param": "<thumbnail upload encrypted parameters>"
}
getConfig
Get account configuration, including the typing ticket.
Request body:
{
"ilink_user_id": "<user ID>", "context_token": "<optional, conversation context token>"
}
Response body:
{
"ret": 0, "typing_ticket": "<base64-encoded typing ticket>"
}
sendTyping
Send or cancel the typing status indicator.
Request body:
{
"ilink_user_id": "<user ID>", "typing_ticket": "<obtained from getConfig>", "status": 1
}
| Field | Type | Description |
|---|---|---|
status |
number |
1 = typing, 2 = cancel typing |
Message Structure
WeixinMessage
| Field | Type | Description |
|---|---|---|
seq |
number? |
Message sequence number |
message_id |
number? |
Unique message ID |
from_user_id |
string? |
Sender ID |
to_user_id |
string? |
Receiver ID |
create_time_ms |
number? |
Creation timestamp (ms) |
session_id |
string? |
Session ID |
message_type |
number? |
1 = USER, 2 = BOT |
message_state |
number? |
0 = NEW, 1 = GENERATING, 2 = FINISH |
item_list |
MessageItem[]? |
Message content list |
context_token |
string? |
Conversation context token, must be passed back when replying |
MessageItem
| Field | Type | Description |
|---|---|---|
type |
number |
1 TEXT, 2 IMAGE, 3 VOICE, 4 FILE, 5 VIDEO |
text_item |
{ text: string }? |
Text content |
image_item |
ImageItem? |
Image (with CDN reference and AES key) |
voice_item |
VoiceItem? |
Voice (SILK encoded) |
file_item |
FileItem? |
File attachment |
video_item |
VideoItem? |
Video |
ref_msg |
RefMessage? |
Referenced message |
CDN Media Reference (CDNMedia)
All media types (image/voice/file/video) are transferred via CDN using AES-128-ECB encryption:
| Field | Type | Description |
|---|---|---|
encrypt_query_param |
string? |
Encrypted parameters for CDN download/upload |
aes_key |
string? |
Base64-encoded AES-128 key |
CDN Upload Flow
- Calculate the file’s plaintext size, MD5, and ciphertext size after AES-128-ECB encryption
- If a thumbnail is needed (image/video), calculate the thumbnail’s plaintext and ciphertext parameters as well
- Call
getUploadUrlto getupload_param(andthumb_upload_param) - Encrypt the file content with AES-128-ECB and PUT upload to the CDN URL
- Encrypt and upload the thumbnail in the same way
- Use the returned
encrypt_query_paramto construct aCDNMediareference, include it in theMessageItem, and send
For complete type definitions, see
src/api/types.ts. For API call implementations, seesrc/api/api.ts.