WeCom¶
Receive and reply via a WeCom (企业微信) intelligent bot in API mode. This is not the custom-app callback mode — Maven implements only the AI bot v1 contract: encrypted webhook in, response_url reply out.
Reactive-only
WeCom is a reactive-only channel. Outbound delivery uses a short-lived response_url from the most recent inbound. Cron jobs with deliver: true skip WeCom and log a warning. Use another channel for proactive notifications.
Supported scope¶
| Capability | Status |
|---|---|
Inbound text |
Yes |
Inbound voice |
Yes (voice.content field) |
Inbound image |
Yes (URL download as multimodal block, ≤10 MB) |
Inbound mixed |
Yes (extracts only text items) |
Outbound markdown via response_url |
Yes (capped 20480 bytes) |
| Streaming | No |
| Template cards | No |
media_id image download |
No (would require access token) |
1. Create the bot¶
- WeCom admin → Security & management → Admin tools → Create bot.
- Choose API mode.
- Save the Token and EncodingAESKey (43 chars).
- Optional: note the ReceiveID for strict decrypt validation.
2. Configure the callback¶
In the bot's WeCom settings, set:
- URL:
https://your-domain.com/wecom/bot - Token and EncodingAESKey matching Maven config.
WeCom calls the URL with verification; Maven handles it automatically.
3. Configure Maven¶
{
"channels": {
"wecom": {
"enabled": true,
"token": "your-token",
"encodingAESKey": "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG",
"receiveId": "",
"port": 9886,
"allowFrom": ["zhangsan"],
"proxy": ""
}
}
}
| Field | Required | Description |
|---|---|---|
enabled |
yes | Master toggle. |
token |
yes | Callback signing token. |
encodingAESKey |
yes | Encrypt/decrypt key. Must be exactly 43 characters. |
receiveId |
no | Optional; enables strict receiver-ID checks on decrypt. |
port |
no | Callback HTTP port. Default 9886. |
allowFrom |
no | Allowed sender user IDs. Empty means all. |
proxy |
no | Per-channel proxy URL. |
4. Run¶
Inbound message flow¶
- WeCom POSTs
{ "encrypt": "…base64…" }to/wecom/botwithmsg_signature,timestamp,noncequery params. - Maven verifies the signature, decrypts to JSON, checks
msgidfor dedup, appliesallowFrom, parses content, and publishes to the bus. - Maven returns a HTTP 200 with an encrypted
{"encrypt": "…", "msgsignature": "…", …}envelope wrapping"success".
Outbound flow¶
When the agent reply is published:
- Maven looks up the cached
response_urlkeyed by chat (1 hour TTL). - POSTs
{"msgtype":"markdown","markdown":{"content":"…"}}to that URL. - Retries up to 3 times on transient errors (
errcode -1,6000, HTTP 5xx). Payload errors (44004etc.) do not retry. - Content exceeding 20480 bytes is truncated at a UTF-8 boundary.
response_url caveats¶
- Short-lived. Often single-use. Delayed or repeated sends may fail.
- Per-chat. Bound to the latest inbound from that user/group.
- No
media_idupload. Maven only supports markdown payloads via this endpoint.
Image downloads¶
When inbound carries image.url, Maven fetches it (≤10 MB), detects the MIME type (or uses the Content-Type), and attaches a base64 multimodal block. If only media_id is present, Maven logs a warning — fetching by media_id requires the corp access token flow not implemented in API-mode bots.
Troubleshooting¶
| Symptom | Check |
|---|---|
| Callback verification fails | token matches console. encodingAESKey is exactly 43 chars. Signature query params present. |
| 401 on POST | msg_signature mismatch — usually a token typo. |
| Duplicate messages | msgid dedup is in-memory; if your deployment is multi-replica behind a load balancer, prefer a single replica or implement shared dedup. |
| Reply not delivered | response_url cache may have expired (1h TTL) or been consumed. The user must send something new to refresh it. |
| Cron delivery skipped | Expected. WeCom is reactive-only; pick another channel for proactive delivery. |
| 44004 from WeCom | Content too large. The truncation is 20480 bytes; verify your model isn't returning more in one chunk. |