@dingxiang-me/openclaw-wechat 1.7.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +162 -0
- package/README.en.md +379 -11
- package/README.md +626 -15
- package/docs/channels/wecom.md +186 -6
- package/openclaw.plugin.json +148 -5
- package/package.json +9 -5
- package/src/core/delivery-router.js +2 -0
- package/src/core/stream-manager.js +13 -2
- package/src/core.js +96 -6
- package/src/wecom/account-config-core.js +2 -0
- package/src/wecom/account-config.js +12 -3
- package/src/wecom/agent-context.js +7 -1
- package/src/wecom/agent-dispatch-executor.js +13 -1
- package/src/wecom/agent-dispatch-fallback.js +23 -0
- package/src/wecom/agent-inbound-dispatch.js +1 -1
- package/src/wecom/agent-inbound-processor.js +33 -2
- package/src/wecom/agent-late-reply-runtime.js +31 -1
- package/src/wecom/agent-runtime-context.js +3 -0
- package/src/wecom/agent-webhook-handler.js +5 -0
- package/src/wecom/api-client-core.js +1 -1
- package/src/wecom/bot-context.js +7 -1
- package/src/wecom/bot-dispatch-fallback.js +34 -3
- package/src/wecom/bot-dispatch-handlers.js +47 -4
- package/src/wecom/bot-inbound-dispatch-runtime.js +10 -0
- package/src/wecom/bot-inbound-executor-helpers.js +51 -5
- package/src/wecom/bot-inbound-executor.js +34 -0
- package/src/wecom/bot-long-connection-manager.js +971 -0
- package/src/wecom/bot-reply-runtime.js +36 -6
- package/src/wecom/bot-runtime-context.js +3 -0
- package/src/wecom/bot-state-store.js +4 -5
- package/src/wecom/bot-webhook-dispatch.js +5 -0
- package/src/wecom/bot-webhook-handler.js +5 -0
- package/src/wecom/callback-health-diagnostics.js +86 -0
- package/src/wecom/channel-config-schema.js +242 -0
- package/src/wecom/channel-plugin.js +162 -4
- package/src/wecom/channel-status-state.js +150 -0
- package/src/wecom/command-handlers.js +6 -0
- package/src/wecom/command-status-text.js +35 -8
- package/src/wecom/doc-client.js +537 -0
- package/src/wecom/doc-schema.js +380 -0
- package/src/wecom/doc-tool.js +833 -0
- package/src/wecom/outbound-active-stream.js +17 -10
- package/src/wecom/outbound-delivery.js +49 -0
- package/src/wecom/plugin-account-policy-services.js +4 -1
- package/src/wecom/plugin-composition.js +2 -0
- package/src/wecom/plugin-constants.js +1 -1
- package/src/wecom/plugin-delivery-inbound-services.js +4 -0
- package/src/wecom/plugin-processing-deps.js +5 -0
- package/src/wecom/plugin-route-runtime-deps.js +2 -0
- package/src/wecom/plugin-services.js +37 -0
- package/src/wecom/register-runtime.js +20 -1
- package/src/wecom/request-parsers.js +1 -0
- package/src/wecom/route-registration.js +4 -1
- package/src/wecom/session-reset.js +168 -0
- package/src/wecom/text-format.js +22 -5
- package/src/wecom/text-inbound-scheduler.js +1 -1
- package/src/wecom/thinking-parser.js +74 -0
- package/src/wecom/voice-transcription-process.js +80 -8
- package/src/wecom/voice-transcription.js +11 -0
package/README.en.md
CHANGED
|
@@ -6,23 +6,64 @@ OpenClaw-Wechat is an OpenClaw channel plugin for Enterprise WeChat (WeCom), wit
|
|
|
6
6
|
|
|
7
7
|
- `Agent mode`: WeCom custom app callback (XML)
|
|
8
8
|
- `Bot mode`: WeCom intelligent bot API callback (JSON + native stream)
|
|
9
|
+
- `Webhook outbound targets`: push messages to group webhooks or named webhook endpoints
|
|
9
10
|
|
|
10
11
|
## Table of Contents
|
|
11
12
|
|
|
13
|
+
- [Major Update (v2.0.0)](#major-update-v200)
|
|
12
14
|
- [Highlights](#highlights)
|
|
13
15
|
- [Mode Comparison](#mode-comparison)
|
|
14
16
|
- [5-Minute Quick Start](#5-minute-quick-start)
|
|
15
17
|
- [Requirements](#requirements)
|
|
16
18
|
- [Install and Load](#install-and-load)
|
|
19
|
+
- [Config Paths and Ownership](#config-paths-and-ownership)
|
|
17
20
|
- [Configuration Reference](#configuration-reference)
|
|
18
21
|
- [Capability Matrix](#capability-matrix)
|
|
19
22
|
- [Commands and Session Policy](#commands-and-session-policy)
|
|
20
23
|
- [Environment Variables](#environment-variables)
|
|
24
|
+
- [Public Callbacks and Gateway Auth](#public-callbacks-and-gateway-auth)
|
|
25
|
+
- [Webhook and Heartbeat Ops](#webhook-and-heartbeat-ops)
|
|
21
26
|
- [Coexistence with Other Channels](#coexistence-with-other-channels)
|
|
22
27
|
- [Troubleshooting](#troubleshooting)
|
|
23
28
|
- [Development](#development)
|
|
24
29
|
- [FAQ](#faq)
|
|
25
30
|
|
|
31
|
+
## Major Update (v2.0.0)
|
|
32
|
+
|
|
33
|
+
This is a real capability update, not a minor patch.
|
|
34
|
+
`OpenClaw-Wechat` now has **working WeCom Bot long-connection support** in real gateway runtime.
|
|
35
|
+
|
|
36
|
+
### WeCom Bot long connection
|
|
37
|
+
|
|
38
|
+
| Item | Result |
|
|
39
|
+
|---|---|
|
|
40
|
+
| Official endpoint | `wss://openws.work.weixin.qq.com` |
|
|
41
|
+
| Inbound commands | `aibot_msg_callback` / `aibot_event_callback` |
|
|
42
|
+
| Outbound command | `aibot_respond_msg` |
|
|
43
|
+
| Runtime | switched to `ws`, no longer blocked by built-in Node WebSocket `1006` failures |
|
|
44
|
+
| Public Bot callback required | no, not in long-connection mode |
|
|
45
|
+
| Verification command | `npm run wecom:bot:longconn:probe -- --json` |
|
|
46
|
+
|
|
47
|
+
### Control UI and operations
|
|
48
|
+
|
|
49
|
+
This release also keeps the earlier operations improvements: **WeCom supports visual configuration in Control UI**, so you no longer need to rely on manual JSON edits only.
|
|
50
|
+
|
|
51
|
+
### Visual config in Control UI
|
|
52
|
+
|
|
53
|
+
| Item | Status | Notes |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| WeCom config form | ✅ | `channels.wecom` can be edited/saved directly from UI |
|
|
56
|
+
| Localized labels | ✅ | Common fields are now clearly labeled in Chinese for ops teams |
|
|
57
|
+
| Sensitive-field hints | ✅ | secret/token/aesKey fields are marked as sensitive |
|
|
58
|
+
| Runtime status clarity | ✅ | `Connected` is no longer stuck at `n/a`; default account display name is localized |
|
|
59
|
+
| Inbound activity tracking | ✅ | `Last inbound` is updated after webhook callbacks (`n/a` before first inbound after restart is expected) |
|
|
60
|
+
|
|
61
|
+
### Practical impact
|
|
62
|
+
|
|
63
|
+
- Configure WeCom directly in `Channels -> WeCom` without hand-editing large config files.
|
|
64
|
+
- Better readability for day-to-day ops and handover.
|
|
65
|
+
- More accurate runtime status display reduces false alarm on “plugin not working”.
|
|
66
|
+
|
|
26
67
|
## Highlights
|
|
27
68
|
|
|
28
69
|
| Feature | Status | Notes |
|
|
@@ -30,6 +71,7 @@ OpenClaw-Wechat is an OpenClaw channel plugin for Enterprise WeChat (WeCom), wit
|
|
|
30
71
|
| WeCom inbound message handling | ✅ | text/image/voice/link/file/video (Agent + Bot) |
|
|
31
72
|
| AI auto-reply via OpenClaw runtime | ✅ | routed by session key |
|
|
32
73
|
| Native WeCom Bot stream protocol | ✅ | `msgtype=stream` refresh flow |
|
|
74
|
+
| Bot thinking display | ✅ | parses `<think>/<thinking>/<thought>` into native `thinking_content` |
|
|
33
75
|
| Bot card replies | ✅ | `markdown/template_card` with automatic text fallback |
|
|
34
76
|
| Multi-account support | ✅ | `channels.wecom.accounts.<id>` |
|
|
35
77
|
| Sender allowlist and admin bypass | ✅ | `allowFrom` + `adminUsers` |
|
|
@@ -50,21 +92,46 @@ OpenClaw-Wechat is an OpenClaw channel plugin for Enterprise WeChat (WeCom), wit
|
|
|
50
92
|
| Default callback path | `/wecom/callback` | `/wecom/bot/callback` |
|
|
51
93
|
| Reply mechanism | WeCom send APIs | stream response + refresh polling |
|
|
52
94
|
| Streaming UX | simulated via multiple messages | native stream protocol |
|
|
95
|
+
| Thinking display | not applicable | native `thinking_content` from `<think>` tags |
|
|
53
96
|
| Outbound media | full support (image/voice/video/file) | image/file supported (`active_stream msg_item(image)` first, then `response_url` mixed / webhook fallback) |
|
|
54
97
|
|
|
55
98
|
## 5-Minute Quick Start
|
|
56
99
|
|
|
57
100
|
### 1) Install plugin
|
|
58
101
|
|
|
102
|
+
```bash
|
|
103
|
+
openclaw plugins install @dingxiang-me/openclaw-wechat
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Recommended minimum package version: `2.0.0`. If `plugins.installs.openclaw-wechat` in `openclaw.json` still reports `1.7.x`, upgrade or reinstall first; those older npm packages do not expose the current WeCom channel metadata.
|
|
107
|
+
|
|
108
|
+
For local development or direct source-path loading, use:
|
|
109
|
+
|
|
59
110
|
```bash
|
|
60
111
|
git clone https://github.com/dingxiang-me/OpenClaw-Wechat.git
|
|
61
112
|
cd OpenClaw-Wechat
|
|
62
113
|
npm install
|
|
63
114
|
```
|
|
64
115
|
|
|
65
|
-
### 2)
|
|
116
|
+
### 2) Enable plugin in OpenClaw
|
|
66
117
|
|
|
67
|
-
|
|
118
|
+
If you installed via `openclaw plugins install`, add this to `~/.openclaw/openclaw.json`:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"plugins": {
|
|
123
|
+
"enabled": true,
|
|
124
|
+
"allow": ["openclaw-wechat"],
|
|
125
|
+
"entries": {
|
|
126
|
+
"openclaw-wechat": {
|
|
127
|
+
"enabled": true
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
If you are loading from source path instead, use the version below with `load.paths`:
|
|
68
135
|
|
|
69
136
|
```json
|
|
70
137
|
{
|
|
@@ -90,14 +157,16 @@ Add to `~/.openclaw/openclaw.json`:
|
|
|
90
157
|
| Agent | `corpId`, `corpSecret`, `agentId`, `callbackToken`, `callbackAesKey` |
|
|
91
158
|
| Bot | `bot.enabled=true`, `bot.token`, `bot.encodingAesKey` |
|
|
92
159
|
|
|
160
|
+
> Agent-mode note (important): configure **Trusted IP** in the WeCom self-built app settings and include the real egress IP of your OpenClaw gateway. Otherwise you may see "messages received but no reply".
|
|
161
|
+
|
|
93
162
|
### 4) Restart and verify
|
|
94
163
|
|
|
95
164
|
```bash
|
|
96
165
|
openclaw gateway restart
|
|
97
166
|
openclaw gateway status
|
|
98
167
|
npm run wecom:selfcheck -- --all-accounts
|
|
99
|
-
npm run wecom:agent:selfcheck -- --
|
|
100
|
-
npm run wecom:bot:selfcheck -- --
|
|
168
|
+
npm run wecom:agent:selfcheck -- --all-accounts
|
|
169
|
+
npm run wecom:bot:selfcheck -- --all-accounts
|
|
101
170
|
```
|
|
102
171
|
|
|
103
172
|
## Requirements
|
|
@@ -113,7 +182,17 @@ npm run wecom:bot:selfcheck -- --account default
|
|
|
113
182
|
|
|
114
183
|
## Install and Load
|
|
115
184
|
|
|
116
|
-
###
|
|
185
|
+
### OpenClaw-managed installation (recommended)
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
openclaw plugins install @dingxiang-me/openclaw-wechat
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
If your installed runtime still shows `1.7.x`, reinstall before debugging config; old packages can fail with `unknown channel id: wecom`.
|
|
192
|
+
|
|
193
|
+
This installs the package under `~/.openclaw/extensions/openclaw-wechat/`. Treat that directory as installed runtime package content, not as your primary business configuration surface.
|
|
194
|
+
|
|
195
|
+
### Local path loading (development mode)
|
|
117
196
|
|
|
118
197
|
```bash
|
|
119
198
|
git clone https://github.com/dingxiang-me/OpenClaw-Wechat.git
|
|
@@ -123,11 +202,36 @@ npm install
|
|
|
123
202
|
|
|
124
203
|
Configure plugin load path in `~/.openclaw/openclaw.json`.
|
|
125
204
|
|
|
126
|
-
|
|
205
|
+
## Config Paths and Ownership
|
|
127
206
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
207
|
+
The paths raised in issue #25 serve different purposes:
|
|
208
|
+
|
|
209
|
+
| Path | Edit manually? | Purpose |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| `~/.openclaw/openclaw.json` | **Yes** | Main OpenClaw config. Put `plugins.*`, `channels.wecom.*`, `bindings`, and `env.vars` here |
|
|
212
|
+
| `~/.openclaw/extensions/openclaw-wechat/package.json` | Usually no | Installed package metadata |
|
|
213
|
+
| `~/.openclaw/extensions/openclaw-wechat/openclaw.plugin.json` | Usually no | Plugin manifest/schema used by OpenClaw |
|
|
214
|
+
| `~/.openclaw/extensions/openclaw-wechat/package-lock.json` | No | Dependency lockfile |
|
|
215
|
+
| `~/.openclaw/agents/<id>/sessions/sessions.json` | No | Runtime session index |
|
|
216
|
+
| `~/.openclaw/agents/<id>/sessions/*.jsonl` | No | Runtime transcripts/state |
|
|
217
|
+
|
|
218
|
+
Windows example mapping:
|
|
219
|
+
|
|
220
|
+
| Windows path | Meaning |
|
|
221
|
+
|---|---|
|
|
222
|
+
| `D:\\Win\\AppData\\LocalLow\\.openclaw\\openclaw.json` | Main config file; this is where parameters belong |
|
|
223
|
+
| `D:\\Win\\AppData\\LocalLow\\.openclaw\\extensions\\openclaw-wechat\\openclaw.plugin.json` | Plugin schema; not a business config file |
|
|
224
|
+
| `D:\\Win\\AppData\\LocalLow\\.openclaw\\agents\\main\\sessions\\sessions.json` | Runtime state; do not use it as config |
|
|
225
|
+
|
|
226
|
+
Recommended placement:
|
|
227
|
+
|
|
228
|
+
| Parameter type | Where to put it |
|
|
229
|
+
|---|---|
|
|
230
|
+
| Plugin load / enable flags | `plugins.*` in `openclaw.json` |
|
|
231
|
+
| WeCom business config | `channels.wecom.*` |
|
|
232
|
+
| Multi-account settings | `channels.wecom.accounts.<id>.*` |
|
|
233
|
+
| Account-to-agent routing | OpenClaw root `bindings` |
|
|
234
|
+
| Secrets / environment-specific overrides | `env.vars.*` or system environment variables |
|
|
131
235
|
|
|
132
236
|
## Configuration Reference
|
|
133
237
|
|
|
@@ -144,6 +248,7 @@ openclaw plugins install @dingxiang-me/openclaw-wechat
|
|
|
144
248
|
| `webhookPath` | string | `/wecom/callback` | Agent callback path (auto `/wecom/<accountId>/callback` when non-default account leaves it empty) |
|
|
145
249
|
| `agent` | object | - | legacy layout: `agent.corpId/corpSecret/agentId` (equivalent to top-level Agent fields) |
|
|
146
250
|
| `outboundProxy` | string | - | WeCom API proxy |
|
|
251
|
+
| `defaultAccount` | string | - | preferred default account for tool usage and runtime fallback |
|
|
147
252
|
| `webhooks` | object | - | named webhook target map (`{ "ops": "https://...key=xxx" }`) |
|
|
148
253
|
| `accounts` | object | - | multi-account map (supports `accounts.<id>.bot` overrides) |
|
|
149
254
|
|
|
@@ -213,6 +318,31 @@ When multi-account is enabled, each account can override Bot callback credential
|
|
|
213
318
|
| Agent streaming | `streaming.enabled`, `streaming.minChars`, `streaming.minIntervalMs` |
|
|
214
319
|
| Observability | `observability.enabled`, `observability.logPayloadMeta` |
|
|
215
320
|
|
|
321
|
+
### OpenClaw bindings for account-level routing
|
|
322
|
+
|
|
323
|
+
Use OpenClaw core `bindings` for stable account-to-agent routing. The plugin exposes `channel=wecom` and `accountId=<id>` to the core router.
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
{
|
|
327
|
+
"bindings": [
|
|
328
|
+
{
|
|
329
|
+
"match": {
|
|
330
|
+
"channel": "wecom",
|
|
331
|
+
"accountId": "sales"
|
|
332
|
+
},
|
|
333
|
+
"agentId": "sales"
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"match": {
|
|
337
|
+
"channel": "wecom",
|
|
338
|
+
"accountId": "support"
|
|
339
|
+
},
|
|
340
|
+
"agentId": "support"
|
|
341
|
+
}
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
216
346
|
## Capability Matrix
|
|
217
347
|
|
|
218
348
|
### Agent mode
|
|
@@ -250,7 +380,9 @@ Quoted reply context in Bot mode is also supported (`quote` is prepended into cu
|
|
|
250
380
|
| `/reset` | reset conversation |
|
|
251
381
|
| `/compact` | compact session (runtime-supported) |
|
|
252
382
|
|
|
253
|
-
Session key policy:
|
|
383
|
+
Session key policy:
|
|
384
|
+
- default account: `wecom:<userid>`
|
|
385
|
+
- non-default accounts: `wecom:<accountId>:<userid>`
|
|
254
386
|
|
|
255
387
|
Outbound target formats:
|
|
256
388
|
- `user`: `wecom:alice` / `user:alice`
|
|
@@ -316,6 +448,201 @@ Outbound target formats:
|
|
|
316
448
|
|---|---|
|
|
317
449
|
| `WECOM_VOICE_TRANSCRIBE_*` | local whisper/whisper-cli settings |
|
|
318
450
|
|
|
451
|
+
## Public Callbacks and Gateway Auth
|
|
452
|
+
|
|
453
|
+
### Goal
|
|
454
|
+
|
|
455
|
+
WeCom must reach the OpenClaw webhook route directly.
|
|
456
|
+
The callback path must not be intercepted by:
|
|
457
|
+
|
|
458
|
+
- Gateway auth / token walls
|
|
459
|
+
- SSO or login redirects
|
|
460
|
+
- frontend/WebUI routing
|
|
461
|
+
- the wrong upstream service
|
|
462
|
+
|
|
463
|
+
### Recommended layout
|
|
464
|
+
|
|
465
|
+
| Scenario | Recommendation |
|
|
466
|
+
|---|---|
|
|
467
|
+
| Single domain | Route `/wecom/*`, legacy `/webhooks/app*`, and `/webhooks/wecom*` directly to the OpenClaw gateway port |
|
|
468
|
+
| Gateway Auth / Zero Trust enabled | Exempt those webhook paths from auth; no Authorization/Cookie/login should be required |
|
|
469
|
+
| Shared frontend + gateway domain | Keep frontend routes separate; do not let `/wecom/*` fall into the SPA |
|
|
470
|
+
| Most stable setup | Use a dedicated subdomain for WeCom callbacks |
|
|
471
|
+
|
|
472
|
+
### Minimum checks
|
|
473
|
+
|
|
474
|
+
| Probe | Expected result |
|
|
475
|
+
|---|---|
|
|
476
|
+
| `curl -i http://127.0.0.1:8885/wecom/callback` | `200` + `wecom webhook ok` |
|
|
477
|
+
| `curl -i http://127.0.0.1:8885/wecom/bot/callback` | `200` + `wecom bot webhook ok` |
|
|
478
|
+
| `curl -i https://your-domain/wecom/callback` | same as local; no HTML, no `401/403`, no redirect |
|
|
479
|
+
| `curl -i https://your-domain/wecom/bot/callback` | same as local; no HTML, no `401/403`, no redirect |
|
|
480
|
+
|
|
481
|
+
### What common responses mean
|
|
482
|
+
|
|
483
|
+
| Response | Meaning | Fix |
|
|
484
|
+
|---|---|---|
|
|
485
|
+
| `200` + `wecom webhook ok` / `wecom bot webhook ok` | webhook route is healthy | continue with URL verification and WeCom-side setup |
|
|
486
|
+
| `200` + HTML | request hit frontend/WebUI | proxy `/wecom/*` directly to the gateway |
|
|
487
|
+
| `401/403` | callback path is auth-gated | bypass auth for webhook paths |
|
|
488
|
+
| `301/302/307/308` | callback path is redirected to login/SSO/frontend | remove redirect and proxy directly to OpenClaw |
|
|
489
|
+
| `502/503/504` | gateway upstream is down/unreachable | fix gateway health/upstream first |
|
|
490
|
+
| `404` | wrong path or webhook route not registered | verify `webhookPath`, plugin load state, and legacy aliases |
|
|
491
|
+
|
|
492
|
+
### Nginx example
|
|
493
|
+
|
|
494
|
+
```nginx
|
|
495
|
+
server {
|
|
496
|
+
listen 443 ssl http2;
|
|
497
|
+
server_name wecom.example.com;
|
|
498
|
+
|
|
499
|
+
location /wecom/ {
|
|
500
|
+
proxy_pass http://127.0.0.1:8885;
|
|
501
|
+
proxy_http_version 1.1;
|
|
502
|
+
proxy_set_header Host $host;
|
|
503
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
504
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
location /webhooks/app {
|
|
508
|
+
proxy_pass http://127.0.0.1:8885;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
location /webhooks/wecom {
|
|
512
|
+
proxy_pass http://127.0.0.1:8885;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Cloudflare Tunnel example
|
|
518
|
+
|
|
519
|
+
```yaml
|
|
520
|
+
ingress:
|
|
521
|
+
- hostname: wecom.example.com
|
|
522
|
+
service: http://127.0.0.1:8885
|
|
523
|
+
- service: http_status:404
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
### Self-check
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
npm run wecom:selfcheck -- --all-accounts
|
|
530
|
+
npm run wecom:agent:selfcheck -- --all-accounts
|
|
531
|
+
npm run wecom:bot:selfcheck -- --all-accounts
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
Self-check now distinguishes:
|
|
535
|
+
|
|
536
|
+
- `route-not-found`
|
|
537
|
+
- `html-fallback`
|
|
538
|
+
- `gateway-auth`
|
|
539
|
+
- `redirect-auth`
|
|
540
|
+
- `gateway-unreachable`
|
|
541
|
+
|
|
542
|
+
## Webhook and Heartbeat Ops
|
|
543
|
+
|
|
544
|
+
### Typical use cases
|
|
545
|
+
|
|
546
|
+
| Need | Recommended path |
|
|
547
|
+
|---|---|
|
|
548
|
+
| Send a one-off group notice | `openclaw message send --channel wecom --target webhook:<name>` |
|
|
549
|
+
| Deliver an agent result into a WeCom group | `openclaw agent --deliver --reply-channel wecom --reply-to webhook:<name>` |
|
|
550
|
+
| Send periodic summaries/checks | OpenClaw `agents.defaults.heartbeat` with `target: "wecom"` and `to: "webhook:<name>"` |
|
|
551
|
+
|
|
552
|
+
### Configure named webhook targets
|
|
553
|
+
|
|
554
|
+
```json
|
|
555
|
+
{
|
|
556
|
+
"channels": {
|
|
557
|
+
"wecom": {
|
|
558
|
+
"webhooks": {
|
|
559
|
+
"ops": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx",
|
|
560
|
+
"dev": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=yyy"
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
For multi-account setups you can also place them under `channels.wecom.accounts.<id>.webhooks`.
|
|
568
|
+
|
|
569
|
+
### Direct send
|
|
570
|
+
|
|
571
|
+
```bash
|
|
572
|
+
openclaw message send --channel wecom --target webhook:ops --message "Service has recovered"
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Deliver an agent turn into the group
|
|
576
|
+
|
|
577
|
+
```bash
|
|
578
|
+
openclaw agent \
|
|
579
|
+
--message "Summarize today's alerts" \
|
|
580
|
+
--deliver \
|
|
581
|
+
--reply-channel wecom \
|
|
582
|
+
--reply-to webhook:ops
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### Heartbeat delivery to WeCom webhook
|
|
586
|
+
|
|
587
|
+
On this machine, OpenClaw `2026.3.2` supports heartbeat delivery by channel and target.
|
|
588
|
+
For a WeCom webhook target:
|
|
589
|
+
|
|
590
|
+
```json
|
|
591
|
+
{
|
|
592
|
+
"channels": {
|
|
593
|
+
"wecom": {
|
|
594
|
+
"webhooks": {
|
|
595
|
+
"ops": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
},
|
|
599
|
+
"agents": {
|
|
600
|
+
"defaults": {
|
|
601
|
+
"heartbeat": {
|
|
602
|
+
"every": "30m",
|
|
603
|
+
"target": "wecom",
|
|
604
|
+
"to": "webhook:ops",
|
|
605
|
+
"prompt": "Check gateway health, recent alerts, and WeCom channel status; if all is healthy, reply in three lines or less.",
|
|
606
|
+
"ackMaxChars": 300
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
Multi-account webhook delivery can add:
|
|
614
|
+
|
|
615
|
+
```json
|
|
616
|
+
{
|
|
617
|
+
"agents": {
|
|
618
|
+
"defaults": {
|
|
619
|
+
"heartbeat": {
|
|
620
|
+
"target": "wecom",
|
|
621
|
+
"to": "webhook:ops",
|
|
622
|
+
"accountId": "sales"
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
Notes:
|
|
630
|
+
|
|
631
|
+
- `target: "wecom"` selects the WeCom channel.
|
|
632
|
+
- `to: "webhook:ops"` selects the named webhook target inside that channel.
|
|
633
|
+
- `accountId` is only needed for multi-account routing.
|
|
634
|
+
- If `target` is omitted, heartbeat still runs but does not deliver externally.
|
|
635
|
+
|
|
636
|
+
Useful ops commands:
|
|
637
|
+
|
|
638
|
+
```bash
|
|
639
|
+
openclaw system heartbeat last
|
|
640
|
+
openclaw config get agents.defaults.heartbeat
|
|
641
|
+
openclaw status --deep
|
|
642
|
+
openclaw logs --follow
|
|
643
|
+
openclaw system event --mode now --text "Run the next ops heartbeat now"
|
|
644
|
+
```
|
|
645
|
+
|
|
319
646
|
## Coexistence with Other Channels
|
|
320
647
|
|
|
321
648
|
Recommended hardening for Telegram/Feishu/WeCom together:
|
|
@@ -331,11 +658,15 @@ See [`docs/troubleshooting/coexistence.md`](./docs/troubleshooting/coexistence.m
|
|
|
331
658
|
| Symptom | Check first | Typical root cause |
|
|
332
659
|
|---|---|---|
|
|
333
660
|
| Callback verification failed | callback URL reachability | URL/Token/AES mismatch |
|
|
661
|
+
| Public `curl` returns `200`, but WeCom admin still says callback verification failed | WeCom console validation | temporary tunnel domain, untrusted public domain, or enterprise-side validation rejects the callback chain | use a stable public domain; do not use temporary domains such as `trycloudflare.com` as the formal Agent callback |
|
|
334
662
|
| `curl /wecom/callback` returns WebUI page | reverse-proxy path routing | `/wecom/*` path is forwarded to frontend/static site instead of OpenClaw gateway |
|
|
663
|
+
| `curl https://your-domain/wecom/callback` returns `401/403` | gateway auth / zero-trust auth | webhook path requires login or token |
|
|
664
|
+
| `curl https://your-domain/wecom/callback` returns `301/302/307/308` | login redirect / SSO / frontend route | webhook path is redirected away from OpenClaw |
|
|
335
665
|
| Inbound received but no reply | gateway logs + dispatch status | timeout, queueing, policy block |
|
|
336
666
|
| Bot image parse failed | `wecom(bot): failed to fetch image url` | expired URL/non-image stream |
|
|
337
667
|
| Voice transcription failed | local command/model path | whisper/ffmpeg environment issue |
|
|
338
668
|
| Startup logs show `wecom: account diagnosis ...` | diagnosis code + account list | multi-account token/agent/path conflict risk |
|
|
669
|
+
| `wecom:selfcheck -- --all-accounts` reports `account '<id>' not found or incomplete` | account layout | older selfcheck logic did not fully recognize nested `agent` blocks or legacy inline accounts, or the account is actually incomplete |
|
|
339
670
|
| gettoken failed | WeCom API result | wrong credentials or network/proxy |
|
|
340
671
|
|
|
341
672
|
Useful commands:
|
|
@@ -345,6 +676,7 @@ openclaw gateway status
|
|
|
345
676
|
openclaw status --deep
|
|
346
677
|
openclaw logs --follow
|
|
347
678
|
npm run wecom:selfcheck -- --all-accounts
|
|
679
|
+
npm run wecom:agent:selfcheck -- --all-accounts
|
|
348
680
|
npm run wecom:bot:selfcheck -- --all-accounts
|
|
349
681
|
```
|
|
350
682
|
|
|
@@ -358,12 +690,15 @@ npm run wecom:bot:selfcheck -- --all-accounts
|
|
|
358
690
|
| `npm run test:e2e:prepare-browser` | check remote browser sandbox readiness (optional Chromium auto-install) |
|
|
359
691
|
| `npm run test:e2e:collect-pdf` | collect browser-generated PDFs from remote sandbox to local artifacts |
|
|
360
692
|
| `npm run wecom:selfcheck -- --all-accounts` | config/network self-check |
|
|
361
|
-
| `npm run wecom:agent:selfcheck -- --account <id>` | Agent E2E self-check (URL verify + encrypted POST) |
|
|
693
|
+
| `npm run wecom:agent:selfcheck -- --account <id>` | single-account Agent E2E self-check (URL verify + encrypted POST) |
|
|
694
|
+
| `npm run wecom:agent:selfcheck -- --all-accounts` | multi-account Agent E2E self-check (runs URL verify + encrypted POST per account) |
|
|
362
695
|
| `npm run wecom:bot:selfcheck -- --account <id>` | Bot E2E self-check (URL verify/signature/encryption/stream-refresh, supports multi-account) |
|
|
696
|
+
| `npm run wecom:callback:matrix -- --agent-url <public-agent-callback> --bot-url <public-bot-callback>` | public callback matrix probe (optionally include legacy alias URLs) |
|
|
363
697
|
| `npm run wecom:remote:e2e -- --mode all --agent-url <public-agent-callback> --bot-url <public-bot-callback>` | remote matrix verification (Agent + Bot) |
|
|
364
698
|
| `npm run wecom:remote:e2e -- --mode all --agent-url <public-agent-callback> --bot-url <public-bot-callback> --prepare-browser --collect-pdf` | remote matrix with browser sandbox prepare + PDF artifact collection |
|
|
365
699
|
| `WECOM_E2E_BOT_URL=<...> WECOM_E2E_AGENT_URL=<...> npm run wecom:remote:e2e -- --mode all` | env-driven remote E2E (also compatible with legacy `E2E_WECOM_*`) |
|
|
366
700
|
| `npm run wecom:e2e:scenario -- --scenario full-smoke --agent-url <public-agent-callback> --bot-url <public-bot-callback>` | scenario-based E2E (preset smoke/queue workflows) |
|
|
701
|
+
| `npm run wecom:e2e:scenario -- --scenario callback-matrix --agent-url <public-agent-callback> --bot-url <public-bot-callback>` | callback-health-only scenario |
|
|
367
702
|
| `npm run wecom:e2e:scenario -- --scenario compat-smoke --agent-url <new-agent-url> --agent-legacy-url <legacy-agent-url> --bot-url <new-bot-url> --bot-legacy-url <legacy-bot-url>` | compatibility matrix run across new + legacy webhook endpoints |
|
|
368
703
|
| `npm run wecom:e2e:scenario -- --scenario matrix-smoke --bot-url <public-bot-callback>` | bot protocol matrix checks (signature/negative requests/stream-refresh/dedupe; requires `WECOM_BOT_TOKEN/WECOM_BOT_ENCODING_AES_KEY`) |
|
|
369
704
|
| `npm run wecom:e2e:compat -- --agent-url <new-agent-url> --agent-legacy-url <legacy-agent-url> --bot-url <new-bot-url> --bot-legacy-url <legacy-bot-url>` | compatibility matrix shortcut command (same as `--scenario compat-smoke`) |
|
|
@@ -381,6 +716,12 @@ Most likely the bot was created in non-API mode. Re-create as **API mode**.
|
|
|
381
716
|
### Why can image recognition fail intermittently?
|
|
382
717
|
WeCom image URLs can return non-standard content type or encrypted media stream. The plugin now includes content sniffing and decrypt fallback.
|
|
383
718
|
|
|
719
|
+
### The app can receive messages but never replies (logs look normal). Why?
|
|
720
|
+
Check whether **Trusted IP** is configured for the WeCom self-built app.
|
|
721
|
+
If trusted IP is missing, WeCom may silently block part of the send/callback chain and it looks like “received but no reply”.
|
|
722
|
+
|
|
723
|
+
Fix: add the actual egress IP of your OpenClaw gateway to the app's Trusted IP list, then retry.
|
|
724
|
+
|
|
384
725
|
### Can Telegram and WeCom affect each other?
|
|
385
726
|
They are logically independent, but can conflict via shared webhook paths, multi-process gateway races, or loose plugin loading policy.
|
|
386
727
|
|
|
@@ -403,6 +744,33 @@ Quick checks:
|
|
|
403
744
|
2. Public: `curl -i https://<domain>/wecom/callback`
|
|
404
745
|
3. Proxy rules: route `/wecom/*` to OpenClaw gateway port, not WebUI.
|
|
405
746
|
|
|
747
|
+
### Why does WeCom admin still say `openapi callback verification failed` even though both local and public `curl` return `200 wecom webhook ok`?
|
|
748
|
+
That only proves your route is reachable. It does **not** prove the WeCom admin console will accept the callback URL.
|
|
749
|
+
|
|
750
|
+
Common causes:
|
|
751
|
+
1. You are using a temporary public tunnel domain such as `trycloudflare.com`
|
|
752
|
+
2. The tenant requires a more stable/trusted public domain
|
|
753
|
+
3. Your callback chain still gets rewritten by auth, redirects, frontend fallback, or edge middleware during the real WeCom-side check
|
|
754
|
+
|
|
755
|
+
Recommended action:
|
|
756
|
+
1. Use your own stable public domain for the self-built app callback
|
|
757
|
+
2. Do not use `trycloudflare.com` as the formal Agent callback URL
|
|
758
|
+
3. Re-check that `/wecom/callback` is free from auth, redirects, frontend fallback, and caching layers
|
|
759
|
+
|
|
760
|
+
### Why do two WeCom accounts seem to share one agent/session?
|
|
761
|
+
This is a multi-account routing problem, not expected channel interference.
|
|
762
|
+
|
|
763
|
+
Current behavior:
|
|
764
|
+
1. Agent session keys are account-aware.
|
|
765
|
+
2. `npm run wecom:selfcheck -- --all-accounts` recognizes `accounts.<id>`, nested `agent` blocks, and legacy inline accounts.
|
|
766
|
+
3. Stable account-to-agent mapping should be expressed with OpenClaw `bindings`.
|
|
767
|
+
|
|
768
|
+
Recommended verification order:
|
|
769
|
+
1. Run `npm run wecom:selfcheck -- --all-accounts`
|
|
770
|
+
2. Ensure every account shows `config.account :: OK`
|
|
771
|
+
3. Add explicit `bindings` for each WeCom `accountId`
|
|
772
|
+
4. Verify session keys are `wecom:<userid>` for default account and `wecom:<accountId>:<userid>` for non-default accounts
|
|
773
|
+
|
|
406
774
|
### How to enable self-built app group chat without requiring `@`?
|
|
407
775
|
First, separate the two WeCom integration types:
|
|
408
776
|
1. **Webhook Bot**: can be added into normal WeCom groups directly (best for group chat).
|