@sunnoy/wecom 1.8.0 → 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/README.md +392 -838
- package/image-processor.js +30 -27
- package/index.js +11 -39
- package/openclaw.plugin.json +4 -4
- package/package.json +6 -8
- package/think-parser.js +51 -11
- package/utils.js +51 -0
- package/wecom/accounts.js +323 -189
- package/wecom/channel-plugin.js +545 -746
- package/wecom/constants.js +57 -47
- package/wecom/dm-policy.js +91 -0
- package/wecom/group-policy.js +85 -0
- package/wecom/onboarding.js +117 -0
- package/wecom/runtime-telemetry.js +330 -0
- package/wecom/sandbox.js +60 -0
- package/wecom/state.js +33 -35
- package/wecom/workspace-template.js +62 -5
- package/wecom/ws-monitor.js +1487 -0
- package/wecom/ws-state.js +160 -0
- package/crypto.js +0 -135
- package/stream-manager.js +0 -358
- package/webhook.js +0 -469
- package/wecom/agent-inbound.js +0 -527
- package/wecom/http-handler-state.js +0 -23
- package/wecom/http-handler.js +0 -381
- package/wecom/inbound-processor.js +0 -550
- package/wecom/media.js +0 -192
- package/wecom/outbound-delivery.js +0 -435
- package/wecom/response-url.js +0 -33
- package/wecom/stream-utils.js +0 -163
- package/wecom/webhook-targets.js +0 -28
- package/wecom/xml-parser.js +0 -126
package/README.md
CHANGED
|
@@ -1,86 +1,76 @@
|
|
|
1
|
-
# OpenClaw
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
# OpenClaw 企业微信(WeCom)增强插件
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@sunnoy/wecom)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
`@sunnoy/wecom` 是 [OpenClaw](https://github.com/openclaw/openclaw) 企业微信渠道的**社区增强插件**,基于官方 [`@wecom/wecom-openclaw-plugin`](https://github.com/WecomTeam/wecom-openclaw-plugin) 的 WebSocket 长连接骨架,提供多账号管理、动态 Agent 隔离、Agent API / Webhook 增强出站、指令白名单、配额感知等企业级特性。
|
|
7
|
+
|
|
8
|
+
底层 SDK:[`@wecom/aibot-node-sdk`](https://github.com/WecomTeam/aibot-node-sdk) — 企业微信智能机器人 Node.js SDK。
|
|
9
|
+
|
|
10
|
+
> **⚠️ 从 HTTP 回调迁移到长连接:** 2.0 版本完全采用企业微信 [AI 机器人 WebSocket 长连接模式](https://open.work.weixin.qq.com/help2/pc/cat?doc_id=21657)。如果你之前使用 HTTP 回调(Token + EncodingAESKey + 回调 URL),需要在企业微信管理后台将机器人切换到长连接模式,然后删除旧的回调配置。切换后只需 `botId` 和 `secret` 即可接入。
|
|
11
|
+
|
|
12
|
+
## 相比官方插件的增强特性
|
|
13
|
+
|
|
14
|
+
下表列出了本插件相比 [官方 WeCom OpenClaw 插件](https://github.com/WecomTeam/wecom-openclaw-plugin)([npm](https://www.npmjs.com/package/@wecom/wecom-openclaw-plugin))额外提供的能力:
|
|
15
|
+
|
|
16
|
+
| 特性 | 官方插件 | 本插件 |
|
|
17
|
+
| --- | :---: | :---: |
|
|
18
|
+
| WebSocket 长连接 + 流式回复 | ✅ | ✅ |
|
|
19
|
+
| 私聊 / 群聊接收 | ✅ | ✅ |
|
|
20
|
+
| DM 准入策略(pairing / open / allowlist / disabled) | ✅ | ✅ |
|
|
21
|
+
| 群聊准入策略(open / allowlist / disabled) | ✅ | ✅ |
|
|
22
|
+
| 按群配置发送者白名单 | ✅ | ✅ |
|
|
23
|
+
| 思考占位(`<think>` 占位符) | ✅ | ✅ |
|
|
24
|
+
| CLI 交互式配置向导 | ✅ | ✅ |
|
|
25
|
+
| **多账号管理**(多 Bot 独立配置、共享字段继承) | ❌ | ✅ |
|
|
26
|
+
| **动态 Agent 路由**(按用户 / 群自动隔离会话与工作区) | ❌ | ✅ |
|
|
27
|
+
| **Workspace 模板**(自动为新 Agent 复制 AGENTS.md 等引导文件) | ❌ | ✅ |
|
|
28
|
+
| **Agent API 增强出站**(自建应用主动发送文本、图片、文件) | ❌ | ✅ |
|
|
29
|
+
| **部门 / 标签目标发送**(`party:` / `tag:` 寻址) | ❌ | ✅ |
|
|
30
|
+
| **Webhook Bot 群通知**(命名 webhook 映射,markdown / 图片 / 文件) | ❌ | ✅ |
|
|
31
|
+
| **指令白名单**(限制普通用户可执行的 slash 命令) | ❌ | ✅ |
|
|
32
|
+
| **管理员绕过**(命令白名单 + 动态 Agent 路由) | ❌ | ✅ |
|
|
33
|
+
| **运行时配额感知**(被动回复 24h 窗口 + 主动发送额度追踪与告警) | ❌ | ✅ |
|
|
34
|
+
| **Pending Reply 重试**(WS 断连后自动通过 Agent API 补发未送达回复) | ❌ | ✅ |
|
|
35
|
+
| **Reasoning 流式节流**(800ms 节流防止 SDK 队列溢出) | ❌ | ✅ |
|
|
36
|
+
| **`<think>` 标签规范化**(兼容 `<thinking>` / `<thought>` 等变体) | ❌ | ✅ |
|
|
37
|
+
| **Reply 媒体指令解析**(自动提取 LLM 输出中的 `MEDIA:` / `FILE:` 路径) | ❌ | ✅ |
|
|
38
|
+
| **出站代理**(`network.egressProxyUrl`) | ❌ | ✅ |
|
|
39
|
+
| **自定义 API 基础地址**(`network.apiBaseUrl` / `WECOM_API_BASE_URL`) | ❌ | ✅ |
|
|
40
|
+
| **Bindings 路由**(固定绑定企业微信账号到指定 Agent) | ❌ | ✅ |
|
|
41
|
+
| **消息去重**(reqId + msgId 去重,防止重复处理) | ❌ | ✅ |
|
|
42
|
+
| **入站图文混排**(`mixed` 消息拆解为文本 + 图片) | ❌ | ✅ |
|
|
43
|
+
| **入站语音转写**(`voice.content` 自动提取) | ❌ | ✅ |
|
|
44
|
+
| **入站引用消息**(`quote` 上下文透传) | ❌ | ✅ |
|
|
45
|
+
|
|
46
|
+
## 目录
|
|
47
|
+
|
|
48
|
+
- [相比官方插件的增强特性](#相比官方插件的增强特性)
|
|
9
49
|
- [前置要求](#前置要求)
|
|
10
50
|
- [安装](#安装)
|
|
51
|
+
- [从 HTTP 回调迁移](#从-http-回调迁移)
|
|
11
52
|
- [运行测试](#运行测试)
|
|
12
|
-
- [运行真实 E2E 测试(远程 OpenClaw)](#运行真实-e2e-测试远程-openclaw)
|
|
13
|
-
|
|
14
|
-
### 配置与接入
|
|
15
53
|
- [配置](#配置)
|
|
16
|
-
- [
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
-
|
|
22
|
-
### 能力与路由
|
|
23
|
-
- [三种模式消息能力对比](#三种模式消息能力对比)
|
|
24
|
-
- [支持的消息类型](#支持的消息类型)
|
|
25
|
-
- [流式回复能力](#流式回复能力)
|
|
26
|
-
- [管理员用户](#管理员用户)
|
|
27
|
-
- [动态 Agent 路由](#动态-agent-路由)
|
|
28
|
-
- [支持的目标格式](#支持的目标格式)
|
|
29
|
-
- [指令白名单](#指令白名单)
|
|
30
|
-
- [消息防抖合并](#消息防抖合并)
|
|
31
|
-
|
|
32
|
-
### 运维与参考
|
|
33
|
-
- [常见问题 (FAQ)](#常见问题-faq)
|
|
54
|
+
- [私聊与群聊准入策略](#私聊与群聊准入策略)
|
|
55
|
+
- [企业微信侧配置](#企业微信侧配置)
|
|
56
|
+
- [消息能力与投递策略](#消息能力与投递策略)
|
|
57
|
+
- [动态 Agent 与路由](#动态-agent-与路由)
|
|
58
|
+
- [常见问题](#常见问题)
|
|
34
59
|
- [项目结构](#项目结构)
|
|
35
|
-
- [贡献规范](#贡献规范)
|
|
36
|
-
- [开源协议](#开源协议)
|
|
37
|
-
- [配置示例参考](#配置示例参考)
|
|
38
60
|
- [自定义 Skills 配合沙箱使用实践](#自定义-skills-配合沙箱使用实践)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
### 消息模式支持
|
|
43
|
-
- **AI 机器人模式 (Bot Mode)**: 基于企业微信最新的 AI 机器人流式分片机制,实现流畅的打字机式回复体验。支持 JSON 格式的回调消息。
|
|
44
|
-
- **自建应用模式 (Agent Mode)**: 支持企业微信自建应用,可处理 XML 格式的回调消息,支持收发消息、上传下载媒体文件。
|
|
45
|
-
- **Webhook Bot 模式**: 支持通过 Webhook 发送消息到群聊,适用于群通知场景。
|
|
46
|
-
|
|
47
|
-
### 流式回复增强
|
|
48
|
-
- **Markdown 格式支持**: 流式回复的 `content` 字段支持常见 Markdown 格式,包括加粗、斜体、代码块、列表、标题、链接等,企业微信客户端会自动渲染。
|
|
49
|
-
- **思考过程展示**: 当 LLM 回复包含 `<think>...</think>` 标签时,插件自动解析并通过 `thinking_content` 字段在客户端展示可折叠的思考过程。
|
|
50
|
-
- **被动回复思考模式**: 首次被动回复即启用思考模式 UI(通过 `thinking_content` 字段),用户无需等待即可看到模型正在思考的状态。
|
|
51
|
-
- **图片混合回复**: 支持在最终回复(`finish=true`)时包含 `msgtype` 为 `image` 的 `msg_item`,流式过程中图片会排队等待最终发送。
|
|
52
|
-
|
|
53
|
-
### 智能消息投递
|
|
54
|
-
- **四层投递回退机制**: 确保消息可靠送达
|
|
55
|
-
1. **流式通道**: 优先通过活跃流式通道发送
|
|
56
|
-
2. **Response URL 回退**: 流式通道关闭后,使用企业微信 response_url 发送
|
|
57
|
-
3. **Webhook Bot 回退**: 支持通过 Webhook 发送到指定群聊
|
|
58
|
-
4. **Agent API 回退**: 通过自建应用 API 主动推送消息
|
|
59
|
-
- **消息防抖合并**: 同一用户在短时间内(2 秒内)连续发送的多条消息自动合并为一次 AI 请求。
|
|
60
|
-
- **内存自动清理**: 定期清理过期的流元数据和响应 URL,防止内存泄漏。
|
|
61
|
-
|
|
62
|
-
### 动态 Agent 与隔离
|
|
63
|
-
- **动态 Agent 管理**: 默认按"每个私聊用户 / 每个群聊"自动创建独立 Agent。每个 Agent 拥有独立的工作区与对话上下文,实现更强的数据隔离。
|
|
64
|
-
- **群聊深度集成**: 支持群聊消息解析,可通过 @提及(At-mention)精准触发机器人响应。
|
|
65
|
-
- **管理员用户**: 可配置管理员列表,默认绕过指令白名单;可选开启“绕过动态 Agent 路由”。
|
|
66
|
-
- **指令白名单**: 内置常用指令支持(如 `/new`、`/status`),并提供指令白名单配置功能。
|
|
67
|
-
|
|
68
|
-
### 多媒体支持
|
|
69
|
-
- **丰富消息类型**: 支持文本、图片、语音、图文混排、文件、位置、链接等消息类型。
|
|
70
|
-
- **入站媒体处理**: 自动解密企业微信 AES-256-CBC 加密的图片,下载并保存语音、视频、文件等媒体供 AI 分析。
|
|
71
|
-
- **出站图片发送**: 支持通过 `msg_item` API 发送 base64 编码图片,单张最大 2MB,每条消息最多 10 张。
|
|
72
|
-
- **文件上传下载**: Agent 模式下支持上传临时媒体文件和下载用户发送的媒体文件。
|
|
73
|
-
|
|
74
|
-
### 安全与扩展
|
|
75
|
-
- **安全与认证**: 完整支持企业微信消息加解密、URL 验证及发送者身份校验。
|
|
76
|
-
- **高性能异步处理**: 采用异步消息处理架构,确保即使在长耗时 AI 推理过程中,企业微信网关也能保持高响应性。
|
|
77
|
-
- **模块化架构**: 清晰的代码组织结构,易于维护和扩展。
|
|
61
|
+
- [相关链接](#相关链接)
|
|
62
|
+
- [贡献与协议](#贡献与协议)
|
|
78
63
|
|
|
79
64
|
## 前置要求
|
|
80
65
|
|
|
81
|
-
- 已安装 [OpenClaw](https://github.com/openclaw/openclaw)
|
|
82
|
-
-
|
|
83
|
-
-
|
|
66
|
+
- 已安装 [OpenClaw](https://github.com/openclaw/openclaw) `2026.3.2+`
|
|
67
|
+
- 企业微信管理后台权限,可创建 AI 机器人或自建应用
|
|
68
|
+
- **机器人已切换到长连接模式**(参考[官方文档](https://open.work.weixin.qq.com/help2/pc/cat?doc_id=21657))
|
|
69
|
+
- 运行 OpenClaw 的机器可以出站访问:
|
|
70
|
+
- `wss://openws.work.weixin.qq.com`
|
|
71
|
+
- `https://qyapi.weixin.qq.com`(启用 Agent / Webhook 时)
|
|
72
|
+
|
|
73
|
+
Bot 主链路不需要企业微信反向访问你的 HTTP 回调地址。
|
|
84
74
|
|
|
85
75
|
## 安装
|
|
86
76
|
|
|
@@ -88,63 +78,33 @@
|
|
|
88
78
|
openclaw plugins install @sunnoy/wecom
|
|
89
79
|
```
|
|
90
80
|
|
|
91
|
-
|
|
92
|
-
- 从 npm 下载插件
|
|
93
|
-
- 安装到 `~/.openclaw/extensions/` 目录
|
|
94
|
-
- 更新 OpenClaw 配置
|
|
95
|
-
- 注册插件
|
|
96
|
-
|
|
97
|
-
### 运行测试
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
npm test
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
运行单元测试(使用 Node.js 内置测试运行器)。
|
|
81
|
+
> **从官方插件迁移:** 如果之前使用 `openclaw plugins install @wecom/wecom-openclaw-plugin`,请先卸载官方插件再安装本插件。`channels.wecom` 配置字段兼容,无需修改。
|
|
104
82
|
|
|
105
|
-
|
|
83
|
+
## 从 HTTP 回调迁移
|
|
106
84
|
|
|
107
|
-
|
|
85
|
+
如果之前使用 HTTP 回调模式(Token + EncodingAESKey + 回调 URL),迁移步骤如下:
|
|
108
86
|
|
|
109
|
-
1.
|
|
87
|
+
1. **企业微信后台**:进入「应用管理」→「智能机器人」,将机器人切换到长连接模式(参考[官方文档](https://open.work.weixin.qq.com/help2/pc/cat?doc_id=21657))
|
|
88
|
+
2. **记录凭证**:切换后获取新的 `BotId` 和 `Secret`
|
|
89
|
+
3. **更新配置**:在 `~/.openclaw/openclaw.json` 中:
|
|
90
|
+
- 设置 `channels.wecom.botId` 和 `channels.wecom.secret`
|
|
91
|
+
- 删除旧的 `token`、`encodingAesKey`、回调 URL 相关配置
|
|
92
|
+
4. **安装插件**:`openclaw plugins install @sunnoy/wecom`
|
|
93
|
+
5. **重启 Gateway**:`openclaw gateway restart`
|
|
110
94
|
|
|
111
|
-
|
|
112
|
-
npm run test:e2e:ali-ai
|
|
113
|
-
```
|
|
95
|
+
迁移后不再需要公网可达的 HTTP 回调地址,插件会主动连接企业微信 WebSocket。
|
|
114
96
|
|
|
115
|
-
|
|
97
|
+
## 运行测试
|
|
116
98
|
|
|
117
99
|
```bash
|
|
118
|
-
|
|
119
|
-
E2E_WECOM_TOKEN=xxx \
|
|
120
|
-
E2E_WECOM_ENCODING_AES_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
|
|
121
|
-
E2E_WECOM_WEBHOOK_PATH=/webhooks/wecom \
|
|
122
|
-
npm run test:e2e
|
|
100
|
+
npm test
|
|
123
101
|
```
|
|
124
102
|
|
|
125
|
-
可选变量:
|
|
126
|
-
- `E2E_WECOM_TEST_USER`(默认 `wecom-e2e-user`)
|
|
127
|
-
- `E2E_WECOM_TEST_COMMAND`(默认 `/status`)
|
|
128
|
-
- `E2E_WECOM_POLL_INTERVAL_MS`(默认 `1200`)
|
|
129
|
-
- `E2E_WECOM_STREAM_TIMEOUT_MS`(默认 `90000`)
|
|
130
|
-
- `E2E_WECOM_ENABLE_BROWSER_CASE`(默认 `1`,设置 `0` 可跳过浏览器场景)
|
|
131
|
-
- `E2E_WECOM_BROWSER_TIMEOUT_MS`(默认 `180000`)
|
|
132
|
-
- `E2E_WECOM_BROWSER_REQUIRE_IMAGE`(默认 `0`,设置 `1` 强制断言 `msg_item` 图片出站)
|
|
133
|
-
- `E2E_WECOM_BROWSER_PROMPT`(浏览器场景自定义提示词)
|
|
134
|
-
- `E2E_WECOM_BROWSER_BING_PDF_PROMPT`(Bing + 保存 PDF 场景提示词)
|
|
135
|
-
- `E2E_WECOM_ENABLE_BROWSER_BING_PDF_CASE`(默认 `1`)
|
|
136
|
-
- `E2E_BROWSER_PREPARE_MODE`(`check`/`install`/`off`,默认 `check`)
|
|
137
|
-
- `E2E_BROWSER_REQUIRE_READY`(默认 `0`,设置 `1` 时浏览器环境不满足则中止)
|
|
138
|
-
- `E2E_COLLECT_BROWSER_PDF`(默认 `1`,执行后自动收集远程 sandbox 中的 PDF)
|
|
139
|
-
- `E2E_PDF_OUTPUT_DIR`(默认 `tests/e2e/artifacts`)
|
|
140
|
-
|
|
141
|
-
> 说明:`test:e2e:ali-ai` 会消耗远程实例的真实 LLM token,并覆盖多种真实入站/出站场景(含浏览器相关场景)。
|
|
142
|
-
> 说明:执行 `test:e2e:ali-ai` 会先做 browser sandbox 准备检查(`prepare-browser-sandbox.sh`),测试后会尝试抓取 PDF 产物(`collect-browser-pdf.sh`)供用户下载。
|
|
143
|
-
> 说明:当 browser sandbox 未就绪(缺浏览器二进制或缺 `browser` skill)时,Bing+PDF case 会自动跳过,并在准备检查输出中标记 `STATUS=MISSING`。
|
|
144
|
-
|
|
145
103
|
## 配置
|
|
146
104
|
|
|
147
|
-
|
|
105
|
+
### 单账号示例
|
|
106
|
+
|
|
107
|
+
在 `~/.openclaw/openclaw.json` 中添加:
|
|
148
108
|
|
|
149
109
|
```json
|
|
150
110
|
{
|
|
@@ -158,462 +118,131 @@ npm run test:e2e
|
|
|
158
118
|
"channels": {
|
|
159
119
|
"wecom": {
|
|
160
120
|
"enabled": true,
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"
|
|
121
|
+
"botId": "aibxxxxxxxxxxxxxxxx",
|
|
122
|
+
"secret": "xxxxxxxxxxxxxxxx",
|
|
123
|
+
"welcomeMessage": "你好,我是 AI 助手。",
|
|
124
|
+
"sendThinkingMessage": true,
|
|
125
|
+
"dmPolicy": "pairing",
|
|
126
|
+
"allowFrom": [],
|
|
127
|
+
"groupPolicy": "open",
|
|
128
|
+
"groupAllowFrom": [],
|
|
129
|
+
"adminUsers": ["admin-userid"],
|
|
164
130
|
"commands": {
|
|
165
131
|
"enabled": true,
|
|
166
|
-
"allowlist": ["/new", "/
|
|
132
|
+
"allowlist": ["/new", "/compact", "/help", "/status"]
|
|
167
133
|
},
|
|
168
|
-
"
|
|
169
|
-
"
|
|
134
|
+
"dynamicAgents": {
|
|
135
|
+
"enabled": true,
|
|
136
|
+
"adminBypass": false
|
|
137
|
+
},
|
|
138
|
+
"dm": {
|
|
139
|
+
"createAgentOnFirstMessage": true
|
|
170
140
|
},
|
|
141
|
+
"groupChat": {
|
|
142
|
+
"enabled": true,
|
|
143
|
+
"requireMention": true,
|
|
144
|
+
"mentionPatterns": ["@"]
|
|
145
|
+
},
|
|
146
|
+
"workspaceTemplate": "/path/to/template-dir",
|
|
171
147
|
"agent": {
|
|
172
|
-
"corpId": "
|
|
173
|
-
"corpSecret": "
|
|
174
|
-
"agentId": 1000002
|
|
175
|
-
"token": "回调 Token (Agent 模式)",
|
|
176
|
-
"encodingAesKey": "回调 EncodingAESKey (Agent 模式)"
|
|
148
|
+
"corpId": "wwxxxxxxxxxxxxxxxx",
|
|
149
|
+
"corpSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
150
|
+
"agentId": 1000002
|
|
177
151
|
},
|
|
178
152
|
"webhooks": {
|
|
179
|
-
"ops
|
|
180
|
-
"dev
|
|
153
|
+
"ops": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx",
|
|
154
|
+
"dev": "yyy"
|
|
155
|
+
},
|
|
156
|
+
"network": {
|
|
157
|
+
"egressProxyUrl": "http://proxy.internal:8080",
|
|
158
|
+
"apiBaseUrl": "https://qyapi.weixin.qq.com"
|
|
181
159
|
}
|
|
182
160
|
}
|
|
183
161
|
}
|
|
184
162
|
}
|
|
185
163
|
```
|
|
186
164
|
|
|
187
|
-
|
|
165
|
+
`webhooks` 的 value 既可以是完整 URL,也可以只写群机器人的 `key`。
|
|
188
166
|
|
|
189
|
-
|
|
167
|
+
### 核心配置
|
|
190
168
|
|
|
191
169
|
| 配置项 | 类型 | 必填 | 说明 |
|
|
192
|
-
|
|
170
|
+
| --- | --- | --- | --- |
|
|
193
171
|
| `plugins.entries.wecom.enabled` | boolean | 是 | 启用插件 |
|
|
194
|
-
| `channels.wecom.
|
|
195
|
-
| `channels.wecom.
|
|
196
|
-
| `channels.wecom.
|
|
197
|
-
| `channels.wecom.
|
|
198
|
-
| `channels.wecom.
|
|
172
|
+
| `channels.wecom.enabled` | boolean | 否 | 渠道开关 |
|
|
173
|
+
| `channels.wecom.botId` | string | 是 | 企业微信 AI 机器人 Bot ID |
|
|
174
|
+
| `channels.wecom.secret` | string | 是 | 企业微信 AI 机器人 Secret |
|
|
175
|
+
| `channels.wecom.websocketUrl` | string | 否 | WS 地址,默认 `wss://openws.work.weixin.qq.com` |
|
|
176
|
+
| `channels.wecom.sendThinkingMessage` | boolean | 否 | 是否先发送 `<think></think>` 占位,默认 `true` |
|
|
177
|
+
| `channels.wecom.welcomeMessage` | string | 否 | 进入会话欢迎语 |
|
|
178
|
+
| `channels.wecom.adminUsers` | string[] | 否 | 管理员用户 ID,可绕过命令白名单 |
|
|
179
|
+
| `channels.wecom.defaultAccount` | string | 否 | 多账号模式默认账号 |
|
|
199
180
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
配置按人/按群隔离的 Agent 管理:
|
|
203
|
-
|
|
204
|
-
| 配置项 | 类型 | 必填 | 说明 |
|
|
205
|
-
|--------|------|------|------|
|
|
206
|
-
| `channels.wecom.dynamicAgents.enabled` | boolean | 否 | 是否启用动态 Agent(默认 true) |
|
|
207
|
-
| `channels.wecom.dynamicAgents.adminBypass` | boolean | 否 | 管理员是否跳过动态 Agent 路由(默认 false) |
|
|
208
|
-
| `channels.wecom.dm.createAgentOnFirstMessage` | boolean | 否 | 私聊时为每个用户创建独立 Agent(默认 true) |
|
|
209
|
-
| `channels.wecom.groupChat.enabled` | boolean | 否 | 是否启用群聊处理(默认 true) |
|
|
210
|
-
| `channels.wecom.groupChat.requireMention` | boolean | 否 | 群聊是否必须 @ 提及才响应(默认 true) |
|
|
211
|
-
|
|
212
|
-
#### 工作区模板配置 (可选)
|
|
213
|
-
|
|
214
|
-
配置工作区模板目录,为动态创建的 Agent 工作区预置初始化文件:
|
|
215
|
-
|
|
216
|
-
| 配置项 | 类型 | 必填 | 说明 |
|
|
217
|
-
|--------|------|------|------|
|
|
218
|
-
| `channels.wecom.workspaceTemplate` | string | 否 | 模板目录路径,支持 AGENTS.md、BOOTSTRAP.md 等 bootstrap 文件 |
|
|
219
|
-
|
|
220
|
-
当动态 Agent 首次创建时,会自动从模板目录复制 bootstrap 文件到对应的工作区。详细说明请参考[动态 Agent 路由](#动态-agent-路由)章节。
|
|
221
|
-
|
|
222
|
-
#### Agent 模式配置 (可选)
|
|
223
|
-
|
|
224
|
-
配置自建应用以实现更强大的消息收发能力:
|
|
181
|
+
### 准入与安全配置
|
|
225
182
|
|
|
226
183
|
| 配置项 | 类型 | 必填 | 说明 |
|
|
227
|
-
|
|
228
|
-
| `channels.wecom.
|
|
229
|
-
| `channels.wecom.
|
|
230
|
-
| `channels.wecom.
|
|
231
|
-
| `channels.wecom.
|
|
232
|
-
| `channels.wecom.
|
|
233
|
-
|
|
234
|
-
|
|
184
|
+
| --- | --- | --- | --- |
|
|
185
|
+
| `channels.wecom.dmPolicy` | string | 否 | `pairing`、`allowlist`、`open`、`disabled`,默认 `pairing` |
|
|
186
|
+
| `channels.wecom.allowFrom` | string[] | 否 | 私聊 allowlist |
|
|
187
|
+
| `channels.wecom.groupPolicy` | string | 否 | `open`、`allowlist`、`disabled`,默认 `open` |
|
|
188
|
+
| `channels.wecom.groupAllowFrom` | string[] | 否 | 允许触发的群聊 ID 列表 |
|
|
189
|
+
| `channels.wecom.groups` | object | 否 | 按群覆盖配置,可为某个群单独设置 `allowFrom` |
|
|
190
|
+
| `channels.wecom.commands.enabled` | boolean | 否 | 是否启用命令白名单,默认 `true` |
|
|
191
|
+
| `channels.wecom.commands.allowlist` | string[] | 否 | 普通用户允许执行的命令 |
|
|
235
192
|
|
|
236
|
-
|
|
193
|
+
### 路由与工作区配置
|
|
237
194
|
|
|
238
195
|
| 配置项 | 类型 | 必填 | 说明 |
|
|
239
|
-
|
|
240
|
-
| `channels.wecom.
|
|
241
|
-
| `
|
|
196
|
+
| --- | --- | --- | --- |
|
|
197
|
+
| `channels.wecom.dynamicAgents.enabled` | boolean | 否 | 是否启用动态 Agent,默认 `true` |
|
|
198
|
+
| `channels.wecom.dynamicAgents.adminBypass` | boolean | 否 | 管理员是否绕过动态 Agent,默认 `false` |
|
|
199
|
+
| `channels.wecom.dm.createAgentOnFirstMessage` | boolean | 否 | 私聊是否按用户建独立 Agent,默认 `true` |
|
|
200
|
+
| `channels.wecom.groupChat.enabled` | boolean | 否 | 是否启用群聊处理,默认 `true` |
|
|
201
|
+
| `channels.wecom.groupChat.requireMention` | boolean | 否 | 群聊是否要求 @ 才响应,默认 `true` |
|
|
202
|
+
| `channels.wecom.groupChat.mentionPatterns` | string[] | 否 | 群聊触发前缀,默认 `["@"]` |
|
|
203
|
+
| `channels.wecom.workspaceTemplate` | string | 否 | 动态 Agent 工作区模板目录 |
|
|
242
204
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
配置 Webhook Bot 用于群通知:
|
|
205
|
+
### 增强出站配置
|
|
246
206
|
|
|
247
207
|
| 配置项 | 类型 | 必填 | 说明 |
|
|
248
|
-
|
|
249
|
-
| `channels.wecom.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
AI 机器人模式适用于简单的问答场景,支持流式输出。
|
|
256
|
-
|
|
257
|
-
> 📖 **官方文档**:[企业微信 AI 机器人开发指南](https://developer.work.weixin.qq.com/document/path/101039)
|
|
258
|
-
|
|
259
|
-
**创建步骤:**
|
|
260
|
-
|
|
261
|
-
1. 登录[企业微信管理后台](https://work.weixin.qq.com/)
|
|
262
|
-
2. 进入「应用管理」→「应用」→ 下拉找到「智能机器人」→ 点击「创建应用」
|
|
263
|
-
3. **关键步骤**:在创建页面底部,选择 **「API 模式创建」**,而非「标准模式创建」
|
|
264
|
-
> ⚠️ **必须选择 API 模式**。标准模式下回调消息为 XML 格式,API 模式为 JSON 格式,本插件的 Bot 模式仅支持 JSON。
|
|
265
|
-
4. 填写机器人名称、头像等基本信息,点击「创建」
|
|
266
|
-
5. 创建完成后,进入机器人详情页:
|
|
267
|
-
- 复制 `Token`(用于验证消息签名)
|
|
268
|
-
- 复制 `EncodingAESKey`(43位字符,用于消息加解密)
|
|
269
|
-
6. 点击「接收消息」区域的「设置」:
|
|
270
|
-
- **URL**: `https://your-domain.com/webhooks/wecom`
|
|
271
|
-
- **Token**: 填入上一步复制的 Token
|
|
272
|
-
- **EncodingAESKey**: 填入上一步复制的 EncodingAESKey
|
|
273
|
-
7. 保存配置并启用消息接收
|
|
274
|
-
|
|
275
|
-
### 方式二:创建自建应用 (Agent 模式)
|
|
276
|
-
|
|
277
|
-
自建应用模式提供更完整的消息收发能力,支持 XML 回调、主动推送、媒体文件处理。
|
|
278
|
-
|
|
279
|
-
> 📖 **官方文档**:[企业微信自建应用开发指南](https://developer.work.weixin.qq.com/document/path/90226)、[接收消息服务器配置](https://developer.work.weixin.qq.com/document/path/90238)
|
|
280
|
-
|
|
281
|
-
**创建步骤:**
|
|
282
|
-
|
|
283
|
-
1. 登录[企业微信管理后台](https://work.weixin.qq.com/)
|
|
284
|
-
2. 进入「应用管理」→「应用」→ 点击「创建应用」
|
|
285
|
-
3. 填写应用信息:
|
|
286
|
-
- 应用名称:如 "AI 助手"
|
|
287
|
-
- 应用头像:上传应用图标
|
|
288
|
-
- 可见成员:选择可使用该应用的成员
|
|
289
|
-
4. 点击「创建应用」,记录以下信息:
|
|
290
|
-
- `AgentId`:应用 ID(数字)
|
|
291
|
-
- `Secret`:应用凭证(点击「查看」获取)
|
|
292
|
-
5. 在「接收消息」区域点击「设置 API 接收」:
|
|
293
|
-
- **URL**: `https://your-domain.com/webhooks/app`
|
|
294
|
-
- **Token**: 点击「随机生成」获取
|
|
295
|
-
- **EncodingAESKey**: 点击「随机生成」获取(43位字符)
|
|
296
|
-
- 点击「保存」时,企业微信会发送验证请求到上述 URL 进行域名校验
|
|
297
|
-
> ⚠️ **注意**:保存前请确保服务已部署并可访问,否则校验会失败。如果遇到「回调 URL 校验失败」,请检查:
|
|
298
|
-
> - 服务器是否可以从公网访问
|
|
299
|
-
> - URL 路径是否正确(`/webhooks/app`)
|
|
300
|
-
> - Token 和 EncodingAESKey 是否已正确配置到插件
|
|
301
|
-
> - 防火墙是否放行了企业微信服务器 IP 段
|
|
302
|
-
6. 获取企业 CorpID:
|
|
303
|
-
- 进入「我的企业」页面
|
|
304
|
-
- 复制页面底部的「企业ID」
|
|
305
|
-
7. 配置应用可见范围(确保需要使用 AI 助手的成员在可见范围内)
|
|
306
|
-
|
|
307
|
-
### 方式三:配置群机器人 (Webhook 模式)
|
|
308
|
-
|
|
309
|
-
Webhook Bot 用于向群聊发送通知消息。
|
|
310
|
-
|
|
311
|
-
> 📖 **官方文档**:[企业微信群机器人开发指南](https://developer.work.weixin.qq.com/document/path/99110)
|
|
312
|
-
|
|
313
|
-
**创建步骤:**
|
|
314
|
-
|
|
315
|
-
1. 在手机或电脑端打开目标群聊
|
|
316
|
-
2. 点击群聊右上角「···」→「群机器人」→「添加机器人」
|
|
317
|
-
3. 选择「新建机器人」,填写机器人名称
|
|
318
|
-
4. 复制 Webhook 地址(格式:`https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx`)
|
|
319
|
-
5. 将 Webhook 地址配置到 `openclaw.json` 的 `webhooks` 中
|
|
208
|
+
| --- | --- | --- | --- |
|
|
209
|
+
| `channels.wecom.agent.corpId` | string | 否 | 自建应用 CorpID |
|
|
210
|
+
| `channels.wecom.agent.corpSecret` | string | 否 | 自建应用 Secret |
|
|
211
|
+
| `channels.wecom.agent.agentId` | number | 否 | 自建应用 AgentId |
|
|
212
|
+
| `channels.wecom.webhooks` | object | 否 | 群机器人 webhook 映射 |
|
|
213
|
+
| `channels.wecom.network.egressProxyUrl` | string | 否 | Agent / Webhook 出站代理 |
|
|
214
|
+
| `channels.wecom.network.apiBaseUrl` | string | 否 | 企业微信 API 基础地址覆盖,默认官方地址 |
|
|
320
215
|
|
|
321
|
-
|
|
322
|
-
- Webhook Bot 仅支持发送消息,不支持接收消息
|
|
323
|
-
- 每个群聊可添加多个机器人
|
|
324
|
-
- Webhook 地址请妥善保管,避免泄露
|
|
216
|
+
Agent 增强出站不需要 `token`、`encodingAesKey`、回调 URL。
|
|
325
217
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
企业微信提供了三种不同的接入方式,每种方式在私聊和群聊场景下的消息收发能力不同:
|
|
329
|
-
|
|
330
|
-
### 能力矩阵
|
|
331
|
-
|
|
332
|
-
| 能力 | Bot 模式 (AI 机器人) | Agent 模式 (自建应用) | Webhook 模式 (群机器人) |
|
|
333
|
-
|------|---------------------|---------------------|----------------------|
|
|
334
|
-
| **私聊接收** | ✅ JSON 回调 | ✅ XML 回调 | ❌ 不支持 |
|
|
335
|
-
| **私聊被动回复** | ✅ 流式 stream | ✅ 同步回复 | ❌ 不支持 |
|
|
336
|
-
| **私聊主动发送** | ❌ 不支持 | ✅ 应用消息 API | ❌ 不支持 |
|
|
337
|
-
| **群聊接收** | ✅ @提及 JSON 回调 | ✅ @提及 XML 回调 | ❌ 不支持 |
|
|
338
|
-
| **群聊被动回复** | ✅ 流式 stream | ✅ 同步回复 | ❌ 不支持 |
|
|
339
|
-
| **群聊主动发送** | ❌ 不支持 | ✅ 应用消息 API | ✅ Webhook URL |
|
|
340
|
-
| **流式回复** | ✅ 打字机效果 | ❌ 仅完整消息 | ❌ 仅完整消息 |
|
|
341
|
-
| **思考过程展示** | ✅ thinking_content | ❌ | ❌ |
|
|
342
|
-
| **媒体发送** | ✅ msg_item (图片) | ✅ API 上传 (图片/文件) | ✅ base64/upload |
|
|
343
|
-
| **Markdown** | ✅ stream content | ✅ Markdown 消息类型 | ✅ Markdown 消息类型 |
|
|
344
|
-
|
|
345
|
-
### 各模式详细说明
|
|
346
|
-
|
|
347
|
-
#### Bot 模式 (AI 机器人)
|
|
348
|
-
|
|
349
|
-
> 📖 [企业微信 AI 机器人开发指南](https://developer.work.weixin.qq.com/document/path/101039)
|
|
350
|
-
|
|
351
|
-
**消息接收机制**:企业微信将用户消息以 **JSON 格式**通过 HTTP POST 回调到配置的 URL。支持私聊消息和群聊中 @提及机器人的消息。
|
|
352
|
-
|
|
353
|
-
**消息回复机制**:采用**流式分片(streaming)**回复。收到回调后立即返回 `stream_id`,后续通过 `stream_refresh` 轮询接口推送增量内容。客户端展示打字机效果。
|
|
354
|
-
|
|
355
|
-
- **被动回复**:用户发消息 → 回调触发 → 流式回复(支持文本、Markdown、图片、思考过程)
|
|
356
|
-
- **主动发送**:❌ 不支持。AI 机器人没有主动发送 API,只能在收到消息后回复
|
|
357
|
-
- **适用场景**:实时对话、问答,流式体验好
|
|
358
|
-
|
|
359
|
-
#### Agent 模式 (自建应用)
|
|
360
|
-
|
|
361
|
-
> 📖 [企业微信自建应用开发指南](https://developer.work.weixin.qq.com/document/path/90226)
|
|
362
|
-
> 📖 [应用消息发送 API](https://developer.work.weixin.qq.com/document/path/90236)
|
|
363
|
-
|
|
364
|
-
**消息接收机制**:企业微信将用户消息以 **XML 格式**通过 HTTP POST 回调到配置的 URL。支持私聊和群聊消息,以及图片、语音、文件等多种消息类型。
|
|
365
|
-
|
|
366
|
-
**消息回复机制**:
|
|
367
|
-
- **被动回复**:在回调响应中直接返回 XML 格式回复(需在 5 秒内响应)
|
|
368
|
-
- **主动发送**:通过[应用消息 API](https://developer.work.weixin.qq.com/document/path/90236) 可主动向用户发送文本、图片、文件、Markdown 等消息。支持指定 `touser`(用户)、`toparty`(部门)、`totag`(标签)
|
|
369
|
-
|
|
370
|
-
- **适用场景**:需要主动推送的场景(异步任务完成通知、定时报告),需要收发文件的场景
|
|
371
|
-
|
|
372
|
-
#### Webhook 模式 (群机器人)
|
|
373
|
-
|
|
374
|
-
> 📖 [企业微信群机器人配置说明](https://developer.work.weixin.qq.com/document/path/99110)
|
|
375
|
-
|
|
376
|
-
**消息发送机制**:通过 HTTP POST 请求向 Webhook URL 发送消息。支持文本、Markdown、图片(base64)、文件(需先上传获取 media_id)。
|
|
377
|
-
|
|
378
|
-
- **接收消息**:❌ 不支持。Webhook 仅为单向发送通道
|
|
379
|
-
- **主动发送**:✅ 向 Webhook URL POST 即可发送到群聊
|
|
380
|
-
- **适用场景**:单向通知(告警、日报)、定时推送
|
|
381
|
-
|
|
382
|
-
### Webhook 消息发送方式
|
|
383
|
-
|
|
384
|
-
Webhook 配置好后(见[方式三](#方式三配置群机器人-webhook-模式)),有以下方式发送消息:
|
|
385
|
-
|
|
386
|
-
#### CLI 直接发送
|
|
387
|
-
|
|
388
|
-
```bash
|
|
389
|
-
openclaw message send --channel wecom --to "webhook:ops-group" "服务已恢复正常"
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
#### Agent 处理后投递到群
|
|
393
|
-
|
|
394
|
-
让 agent 处理消息后将回复发到 webhook 群:
|
|
395
|
-
|
|
396
|
-
```bash
|
|
397
|
-
openclaw agent --agent myagent \
|
|
398
|
-
--message "帮我总结今天的监控告警" \
|
|
399
|
-
--deliver \
|
|
400
|
-
--reply-channel wecom \
|
|
401
|
-
--reply-to "webhook:ops-group"
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
#### Heartbeat 定时推送(推荐)
|
|
405
|
-
|
|
406
|
-
在 agent 配置中添加 heartbeat,自动定时触发并将回复发到 webhook 群:
|
|
407
|
-
|
|
408
|
-
```json
|
|
409
|
-
{
|
|
410
|
-
"id": "report-agent",
|
|
411
|
-
"heartbeat": {
|
|
412
|
-
"every": "1h",
|
|
413
|
-
"target": "webhook:ops-group",
|
|
414
|
-
"prompt": "请总结最新的系统监控状态",
|
|
415
|
-
"activeHours": {
|
|
416
|
-
"start": "09:00",
|
|
417
|
-
"end": "18:00",
|
|
418
|
-
"timezone": "Asia/Shanghai"
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
- `every` — 触发间隔(如 `30m`, `1h`, `6h`)
|
|
425
|
-
- `target` — 回复目标,`webhook:` 前缀加配置中的 webhook 名称
|
|
426
|
-
- `prompt` — 每次触发时给 agent 的提示语
|
|
427
|
-
- `activeHours` — 可选,限制只在工作时间段内触发
|
|
428
|
-
|
|
429
|
-
#### 系统 Crontab 定时发送
|
|
430
|
-
|
|
431
|
-
```bash
|
|
432
|
-
# crontab -e
|
|
433
|
-
# 每天早上9点发送日报
|
|
434
|
-
0 9 * * * openclaw agent --agent report-agent --message "生成今日晨报" --deliver --reply-channel wecom --reply-to "webhook:ops-group"
|
|
435
|
-
|
|
436
|
-
# 每小时发送监控摘要
|
|
437
|
-
0 * * * * openclaw message send --channel wecom --to "webhook:monitor-group" "$(curl -s http://localhost:9090/api/v1/alerts | jq -r '.data.alerts | length') 条活跃告警"
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
### 模式选择建议
|
|
441
|
-
|
|
442
|
-
| 需求 | 推荐模式 |
|
|
443
|
-
|------|---------|
|
|
444
|
-
| 实时对话,流式打字机体验 | **Bot 模式** |
|
|
445
|
-
| 双向对话 + 主动推送 + 文件处理 | **Agent 模式** |
|
|
446
|
-
| 仅需向群聊推送通知 | **Webhook 模式** |
|
|
447
|
-
| 同时需要对话和群通知 | **Bot/Agent 模式 + Webhook 模式** 组合使用 |
|
|
448
|
-
|
|
449
|
-
> 💡 **三种模式可以同时启用**。例如:Bot 模式处理日常对话,Webhook 模式负责定时推送通知到群。配置时在同一个 `channels.wecom` 下同时填写 `token`/`encodingAesKey`(Bot)、`agent`(Agent)和 `webhooks`(Webhook)即可。
|
|
450
|
-
|
|
451
|
-
## 支持的消息类型
|
|
452
|
-
|
|
453
|
-
| 类型 | 方向 | 说明 |
|
|
454
|
-
|------|------|------|
|
|
455
|
-
| 文本 (text) | 收/发 | 纯文本消息 |
|
|
456
|
-
| 图片 (image) | 收/发 | 入站图片自动解密;出站通过 `msg_item` base64 发送 |
|
|
457
|
-
| 语音 (voice) | 收 | 企业微信自动转文字后处理(仅限私聊) |
|
|
458
|
-
| 图文混排 (mixed) | 收 | 文本 + 图片混合消息 |
|
|
459
|
-
| 文件 (file) | 收 | 文件附件(下载后传给 AI 分析) |
|
|
460
|
-
| 位置 (location) | 收 | 位置分享(转换为文本描述) |
|
|
461
|
-
| 链接 (link) | 收 | 分享链接(提取标题、描述、URL 为文本) |
|
|
462
|
-
|
|
463
|
-
## 流式回复能力
|
|
464
|
-
|
|
465
|
-
### Markdown 格式
|
|
466
|
-
|
|
467
|
-
流式回复的 `content` 字段支持以下 Markdown 格式,企业微信客户端会自动渲染:
|
|
468
|
-
|
|
469
|
-
| 格式 | 语法 | 示例 |
|
|
470
|
-
|------|------|------|
|
|
471
|
-
| 加粗 | `**text**` | **加粗文本** |
|
|
472
|
-
| 斜体 | `*text*` | *斜体文本* |
|
|
473
|
-
| 行内代码 | `` `code` `` | `code` |
|
|
474
|
-
| 代码块 | ` ```lang ... ``` ` | 多行代码 |
|
|
475
|
-
| 列表 | `- item` / `1. item` | 有序/无序列表 |
|
|
476
|
-
| 标题 | `# H1` / `## H2` | 各级标题 |
|
|
477
|
-
| 链接 | `[text](url)` | 超链接 |
|
|
478
|
-
|
|
479
|
-
### 思考过程展示(Thinking Mode)
|
|
480
|
-
|
|
481
|
-
当 LLM 模型(如 DeepSeek、QwQ 等支持思考模式的模型)在回复中输出 `<think>...</think>` 标签时,插件会自动:
|
|
482
|
-
|
|
483
|
-
1. **解析** `<think>` 标签,将思考内容与可见内容分离
|
|
484
|
-
2. **映射** 思考内容到企业微信流式回复的 `thinking_content` 字段
|
|
485
|
-
3. **展示** 企业微信客户端会以可折叠的方式显示模型的思考过程
|
|
486
|
-
|
|
487
|
-
**流式处理说明:**
|
|
488
|
-
- 被动回复(首次同步响应)立即启用思考模式 UI,显示「思考中...」
|
|
489
|
-
- 当检测到未闭合的 `<think>` 标签(流式输出中),`thinking_content` 持续更新
|
|
490
|
-
- `</think>` 闭合后,思考内容固定,后续内容显示为可见回复
|
|
491
|
-
- 代码块内的 `<think>` 标签不会被解析(避免误匹配)
|
|
492
|
-
|
|
493
|
-
**支持的标签变体:** `<think>`, `<thinking>`, `<thought>`(均不区分大小写)
|
|
494
|
-
|
|
495
|
-
### 图片回复
|
|
496
|
-
|
|
497
|
-
图片通过 `msg_item` 以 base64 编码在流式回复结束时发送:
|
|
498
|
-
|
|
499
|
-
- 仅在 `finish=true`(最终回复)时包含 `msgtype` 为 `image` 的 `msg_item`
|
|
500
|
-
- 流式过程中生成的图片会排队,待回复完成后一次性发送
|
|
501
|
-
- 单张图片最大 2MB,支持 JPG/PNG 格式,每条消息最多 10 张
|
|
502
|
-
|
|
503
|
-
## 管理员用户
|
|
504
|
-
|
|
505
|
-
管理员用户默认可以绕过指令白名单限制。若希望管理员用户同时跳过动态 Agent 路由(直接路由到主 Agent),可开启 `dynamicAgents.adminBypass`。
|
|
506
|
-
|
|
507
|
-
```json
|
|
508
|
-
{
|
|
509
|
-
"channels": {
|
|
510
|
-
"wecom": {
|
|
511
|
-
"adminUsers": ["user1", "user2"],
|
|
512
|
-
"dynamicAgents": {
|
|
513
|
-
"adminBypass": true
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
管理员用户 ID 不区分大小写,匹配企业微信的 `userid` 字段。
|
|
521
|
-
|
|
522
|
-
## 动态 Agent 路由
|
|
523
|
-
|
|
524
|
-
本插件实现"按人/按群隔离"的 Agent 管理:
|
|
525
|
-
|
|
526
|
-
### 工作原理
|
|
527
|
-
|
|
528
|
-
1. 企业微信消息到达后,插件生成确定性的 `agentId`:
|
|
529
|
-
- **单账号私聊**: `wecom-dm-<userId>`
|
|
530
|
-
- **单账号群聊**: `wecom-group-<chatId>`
|
|
531
|
-
- **多账号私聊**: `wecom-<accountId>-dm-<userId>`
|
|
532
|
-
- **多账号群聊**: `wecom-<accountId>-group-<chatId>`
|
|
533
|
-
2. OpenClaw 自动创建/复用对应的 Agent 工作区
|
|
534
|
-
3. 每个用户/群聊拥有独立的对话历史和上下文
|
|
535
|
-
4. 管理员用户默认参与动态路由;当 `dynamicAgents.adminBypass=true` 时跳过动态路由,直接使用主 Agent
|
|
536
|
-
|
|
537
|
-
### 高级配置
|
|
538
|
-
|
|
539
|
-
配置在 `channels.wecom` 下:
|
|
218
|
+
### 多账号示例
|
|
540
219
|
|
|
541
220
|
```json
|
|
542
221
|
{
|
|
543
222
|
"channels": {
|
|
544
223
|
"wecom": {
|
|
545
|
-
"
|
|
546
|
-
|
|
224
|
+
"defaultAccount": "open",
|
|
225
|
+
"adminUsers": ["admin-userid"],
|
|
226
|
+
"commands": {
|
|
227
|
+
"enabled": true,
|
|
228
|
+
"allowlist": ["/new", "/compact", "/help", "/status"]
|
|
547
229
|
},
|
|
548
|
-
"
|
|
549
|
-
"
|
|
230
|
+
"open": {
|
|
231
|
+
"botId": "aib-open-xxx",
|
|
232
|
+
"secret": "secret-open-xxx",
|
|
233
|
+
"dmPolicy": "open"
|
|
550
234
|
},
|
|
551
|
-
"
|
|
552
|
-
"
|
|
553
|
-
"
|
|
554
|
-
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
| 配置项 | 类型 | 默认值 | 说明 |
|
|
561
|
-
|--------|------|--------|------|
|
|
562
|
-
| `dynamicAgents.enabled` | boolean | `true` | 是否启用动态 Agent |
|
|
563
|
-
| `dynamicAgents.adminBypass` | boolean | `false` | 管理员是否跳过动态 Agent 路由 |
|
|
564
|
-
| `dm.createAgentOnFirstMessage` | boolean | `true` | 私聊使用动态 Agent |
|
|
565
|
-
| `groupChat.enabled` | boolean | `true` | 启用群聊处理 |
|
|
566
|
-
| `groupChat.requireMention` | boolean | `true` | 群聊必须 @ 提及才响应 |
|
|
567
|
-
|
|
568
|
-
### 禁用动态 Agent
|
|
569
|
-
|
|
570
|
-
如果需要所有消息进入默认 Agent:
|
|
571
|
-
|
|
572
|
-
```json
|
|
573
|
-
{
|
|
574
|
-
"channels": {
|
|
575
|
-
"wecom": {
|
|
576
|
-
"dynamicAgents": { "enabled": false }
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
```
|
|
581
|
-
|
|
582
|
-
### 多账号配置(Multi-Bot)
|
|
583
|
-
|
|
584
|
-
支持在一个 OpenClaw 实例中接入多个企业微信机器人,每个机器人独立配置 Token、Agent 凭证、Webhook 等,互不干扰。
|
|
585
|
-
|
|
586
|
-
> 💡 **典型场景**:一个企业微信里创建多个 AI 机器人(如「客服助手」「技术支持」),各自对应不同的 Agent 和会话空间。
|
|
587
|
-
|
|
588
|
-
**配置方式:** 将 `channels.wecom` 下的值改为字典结构,每个 key 是账号 ID(如 `bot1`、`bot2`),value 包含该账号的完整配置:
|
|
589
|
-
|
|
590
|
-
```json
|
|
591
|
-
{
|
|
592
|
-
"channels": {
|
|
593
|
-
"wecom": {
|
|
594
|
-
"bot1": {
|
|
595
|
-
"token": "Bot1 的 Token",
|
|
596
|
-
"encodingAesKey": "Bot1 的 EncodingAESKey",
|
|
597
|
-
"adminUsers": ["admin1"],
|
|
598
|
-
"workspaceTemplate": "/path/to/bot1-template",
|
|
235
|
+
"support": {
|
|
236
|
+
"botId": "aib-support-xxx",
|
|
237
|
+
"secret": "secret-support-xxx",
|
|
238
|
+
"dmPolicy": "pairing",
|
|
599
239
|
"agent": {
|
|
600
|
-
"corpId": "
|
|
601
|
-
"corpSecret": "
|
|
602
|
-
"agentId":
|
|
603
|
-
"token": "Bot1 回调 Token",
|
|
604
|
-
"encodingAesKey": "Bot1 回调 EncodingAESKey"
|
|
240
|
+
"corpId": "wwxxxxxxxxxxxxxxxx",
|
|
241
|
+
"corpSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
242
|
+
"agentId": 1000002
|
|
605
243
|
},
|
|
606
244
|
"webhooks": {
|
|
607
|
-
"ops
|
|
608
|
-
}
|
|
609
|
-
},
|
|
610
|
-
"bot2": {
|
|
611
|
-
"token": "Bot2 的 Token",
|
|
612
|
-
"encodingAesKey": "Bot2 的 EncodingAESKey",
|
|
613
|
-
"agent": {
|
|
614
|
-
"corpId": "企业 CorpID",
|
|
615
|
-
"corpSecret": "Bot2 应用 Secret",
|
|
616
|
-
"agentId": 1000002
|
|
245
|
+
"ops": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
|
|
617
246
|
}
|
|
618
247
|
}
|
|
619
248
|
}
|
|
@@ -621,358 +250,291 @@ openclaw agent --agent myagent \
|
|
|
621
250
|
}
|
|
622
251
|
```
|
|
623
252
|
|
|
624
|
-
|
|
253
|
+
多账号模式下:
|
|
625
254
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
| Webhook 路径 | 自动按账号分配:`/webhooks/wecom/bot1`、`/webhooks/wecom/bot2` |
|
|
631
|
-
| Agent 回调路径 | 自动按账号分配:`/webhooks/app/bot1`、`/webhooks/app/bot2` |
|
|
632
|
-
| 工作区模板 | 支持按账号自定义:`channels.wecom.<accountId>.workspaceTemplate`(覆盖全局配置) |
|
|
633
|
-
| 动态 Agent ID | 按账号隔离:`wecom-bot1-dm-{userId}`、`wecom-bot2-group-{chatId}` |
|
|
634
|
-
| 冲突检测 | 启动时自动检测重复的 Token 或 Agent ID,避免消息路由错乱 |
|
|
255
|
+
- 顶层共享字段会合并到各账号
|
|
256
|
+
- `channels.wecom.<accountId>` 是每个账号自己的覆盖项
|
|
257
|
+
- 动态 Agent ID 会自动带账号前缀
|
|
258
|
+
- 旧的 v1 `token` / `encodingAesKey` 字段不再使用
|
|
635
259
|
|
|
636
|
-
|
|
260
|
+
## 私聊与群聊准入策略
|
|
637
261
|
|
|
638
|
-
###
|
|
262
|
+
### 私聊 `dmPolicy`
|
|
639
263
|
|
|
640
|
-
|
|
264
|
+
| 值 | 含义 |
|
|
265
|
+
| --- | --- |
|
|
266
|
+
| `pairing` | 默认模式。陌生用户首次私聊会收到配对码,管理员执行 `openclaw pairing approve wecom <code>` 后放行 |
|
|
267
|
+
| `allowlist` | 只允许 `allowFrom` 中的用户私聊,不自动发配对码 |
|
|
268
|
+
| `open` | 允许所有能私聊机器人的企业微信成员直接进入会话 |
|
|
269
|
+
| `disabled` | 禁用私聊 |
|
|
641
270
|
|
|
642
|
-
|
|
643
|
-
{
|
|
644
|
-
"channels": {
|
|
645
|
-
"wecom": {
|
|
646
|
-
"workspaceTemplate": "/path/to/template-dir"
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
```
|
|
271
|
+
`open` 的含义就是:如果机器人可见范围允许,企业内任何能私聊到这个 Bot 的成员都可以直接使用。
|
|
651
272
|
|
|
652
|
-
|
|
653
|
-
- `AGENTS.md` - Agent 列表配置
|
|
654
|
-
- `BOOTSTRAP.md` - 初始化引导文档
|
|
655
|
-
- `CLAUDE.md` - Claude Code 指令集
|
|
656
|
-
- 其他自定义文件
|
|
273
|
+
### 群聊策略
|
|
657
274
|
|
|
658
|
-
|
|
275
|
+
| 配置 | 说明 |
|
|
276
|
+
| --- | --- |
|
|
277
|
+
| `groupPolicy: "open"` | 所有群可触发 |
|
|
278
|
+
| `groupPolicy: "allowlist"` + `groupAllowFrom` | 只允许指定群 |
|
|
279
|
+
| `groupPolicy: "disabled"` | 禁用群聊 |
|
|
280
|
+
| `groupChat.requireMention` | 群聊是否必须 @ 才触发 |
|
|
281
|
+
| `groups.<chatId>.allowFrom` | 某个群里仅允许指定成员触发 |
|
|
659
282
|
|
|
660
|
-
##
|
|
283
|
+
## 企业微信侧配置
|
|
661
284
|
|
|
662
|
-
|
|
285
|
+
### 1. 创建 AI 机器人(Bot 主链路)
|
|
663
286
|
|
|
664
|
-
|
|
665
|
-
|------|------|------|
|
|
666
|
-
| `webhook:<name>` | `webhook:ops-group` | 发送到配置的 Webhook 群 |
|
|
667
|
-
| `wecom:<userId>` | `wecom:zhangsan` | 企业微信用户 ID |
|
|
668
|
-
| `party:<id>` | `party:2` | 部门 ID(数字) |
|
|
669
|
-
| `tag:<name>` | `tag:Developers` | 标签名称 |
|
|
670
|
-
| `group:<chatId>` | `group:wr123456` | 群聊 ID |
|
|
671
|
-
| `chatId` | `wr123456` | 以 `wr` 或 `wc` 开头的群聊 ID |
|
|
287
|
+
这是 v2 的主接入方式,使用 WebSocket 长连接。
|
|
672
288
|
|
|
673
|
-
|
|
289
|
+
1. 登录[企业微信管理后台](https://work.weixin.qq.com/wework_admin/frame)
|
|
290
|
+
2. 进入「应用管理」→「智能机器人」
|
|
291
|
+
3. 创建机器人,选择长连接模式(参考[官方文档](https://open.work.weixin.qq.com/help2/pc/cat?doc_id=21657))
|
|
292
|
+
4. 创建完成后记录 `BotId` 和 `Secret`
|
|
293
|
+
5. 填入 OpenClaw 配置的 `channels.wecom.botId` 和 `channels.wecom.secret`
|
|
294
|
+
6. 启动 OpenClaw,插件会主动连接官方 WebSocket
|
|
674
295
|
|
|
675
|
-
|
|
296
|
+
长连接模式下不需要配置 HTTP 回调 URL、Token、EncodingAESKey。
|
|
676
297
|
|
|
677
|
-
|
|
678
|
-
# 发送给指定用户
|
|
679
|
-
openclaw send "wecom:zhangsan" "Hello!"
|
|
298
|
+
### 2. 创建自建应用(Agent 增强出站,可选)
|
|
680
299
|
|
|
681
|
-
|
|
682
|
-
openclaw send "webhook:dev-group" "部署成功!"
|
|
300
|
+
Agent 在本项目里只承担增强出站:
|
|
683
301
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
302
|
+
- 主动给用户 / 群 / 部门 / 标签发消息
|
|
303
|
+
- 上传图片和文件
|
|
304
|
+
- 当 WS 断连时作为回复后备通道
|
|
687
305
|
|
|
688
|
-
|
|
306
|
+
创建步骤:
|
|
689
307
|
|
|
690
|
-
|
|
308
|
+
1. 在企业微信后台创建自建应用
|
|
309
|
+
2. 记录 `CorpID`、`AgentId`、`Secret`
|
|
310
|
+
3. 填入配置:
|
|
311
|
+
- `channels.wecom.agent.corpId`
|
|
312
|
+
- `channels.wecom.agent.agentId`
|
|
313
|
+
- `channels.wecom.agent.corpSecret`
|
|
691
314
|
|
|
692
|
-
|
|
693
|
-
{
|
|
694
|
-
"channels": {
|
|
695
|
-
"wecom": {
|
|
696
|
-
"commands": {
|
|
697
|
-
"enabled": true,
|
|
698
|
-
"allowlist": ["/new", "/status", "/help", "/compact"]
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
```
|
|
704
|
-
|
|
705
|
-
### 推荐白名单指令
|
|
706
|
-
|
|
707
|
-
| 指令 | 说明 | 安全级别 |
|
|
708
|
-
|------|------|----------|
|
|
709
|
-
| `/new` | 重置当前对话,开启全新会话 | 用户级 |
|
|
710
|
-
| `/compact` | 压缩当前会话上下文 | 用户级 |
|
|
711
|
-
| `/help` | 查看帮助信息 | 用户级 |
|
|
712
|
-
| `/status` | 查看当前 Agent 状态 | 用户级 |
|
|
315
|
+
不需要配置接收消息回调。
|
|
713
316
|
|
|
714
|
-
|
|
317
|
+
### 3. 配置群机器人(Webhook 增强出站,可选)
|
|
715
318
|
|
|
716
|
-
|
|
319
|
+
Webhook 只负责群通知。
|
|
717
320
|
|
|
718
|
-
|
|
321
|
+
1. 在目标群添加群机器人
|
|
322
|
+
2. 复制 webhook URL 或 key
|
|
323
|
+
3. 配置到 `channels.wecom.webhooks`
|
|
324
|
+
4. 发送目标使用 `webhook:<name>`
|
|
719
325
|
|
|
720
|
-
|
|
721
|
-
- 后续被合并的消息会显示已合并的提示
|
|
722
|
-
- 指令消息(以 `/` 开头)不参与防抖,会立即处理
|
|
326
|
+
## 消息能力与投递策略
|
|
723
327
|
|
|
724
|
-
|
|
328
|
+
### 能力矩阵
|
|
725
329
|
|
|
726
|
-
|
|
330
|
+
| 能力 | Bot(WS) | Agent API | Webhook |
|
|
331
|
+
| --- | :---: | :---: | :---: |
|
|
332
|
+
| 私聊接收 | ✅ | — | — |
|
|
333
|
+
| 群聊接收(可配置 @ 触发) | ✅ | — | — |
|
|
334
|
+
| 被动流式回复 | ✅ | — | — |
|
|
335
|
+
| 被动最终帧图片 | ✅ | ✅ | ✅ |
|
|
336
|
+
| 主动发送文本 | ✅ | ✅ | ✅ |
|
|
337
|
+
| 主动发送图片 / 文件 | — | ✅ | ✅ |
|
|
338
|
+
| 发送到部门 / 标签 | — | ✅ | — |
|
|
339
|
+
| 思考过程 `<think>` | ✅ | — | — |
|
|
340
|
+
| 欢迎语 | ✅ | — | — |
|
|
341
|
+
| WS 断连补发 | — | ✅ | — |
|
|
727
342
|
|
|
728
|
-
|
|
343
|
+
### 入站消息
|
|
729
344
|
|
|
730
|
-
|
|
731
|
-
|
|
345
|
+
| 类型 | 说明 |
|
|
346
|
+
| --- | --- |
|
|
347
|
+
| `text` | 文本消息 |
|
|
348
|
+
| `image` | 图片(AES 加密下载 + 解密) |
|
|
349
|
+
| `voice` | 语音(自动提取转写文本 `voice.content`) |
|
|
350
|
+
| `file` | 文件(AES 加密下载 + 解密) |
|
|
351
|
+
| `mixed` | 图文混排(自动拆解为文本 + 图片) |
|
|
352
|
+
| `quote` | 引用消息(上下文透传) |
|
|
732
353
|
|
|
733
|
-
|
|
354
|
+
### 被动回复
|
|
734
355
|
|
|
735
|
-
|
|
356
|
+
被动回复统一走 WebSocket `replyStream`:
|
|
736
357
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
358
|
+
- 文本内容支持 Markdown
|
|
359
|
+
- `<thinking>`、`<thought>` 等变体会被规范化为 `<think>`
|
|
360
|
+
- 可先发送 `<think></think>` 占位(配置 `sendThinkingMessage`)
|
|
361
|
+
- 思考流式更新采用 800ms 节流,防止 SDK 队列溢出
|
|
362
|
+
- 最终回复 `finish=true` 时可附带图片 `msg_item`
|
|
363
|
+
- 若最终回复包含 WS 不支持的媒体(文件等),会先文本提示再通过 Agent API 补发
|
|
741
364
|
|
|
742
|
-
|
|
365
|
+
### 主动发送与后备策略
|
|
743
366
|
|
|
744
|
-
|
|
367
|
+
主动发送分层:
|
|
745
368
|
|
|
746
|
-
|
|
369
|
+
1. 普通文本优先走 WS `sendMessage`
|
|
370
|
+
2. 目标为 `webhook:<name>` 时走 Webhook
|
|
371
|
+
3. 目标为用户 / 群 / 部门 / 标签,且配置了 Agent 时走 Agent API
|
|
372
|
+
4. 发送图片 / 文件时,WS 侧给出文本提示,媒体交给 Agent / Webhook 通道
|
|
373
|
+
5. 未配置 Agent / Webhook 时,只保留 WS 文本提示
|
|
747
374
|
|
|
748
|
-
|
|
749
|
-
- **图片限制**:单张图片最大 2MB,支持 JPG 和 PNG 格式,每条消息最多 10 张图片
|
|
750
|
-
- **无需配置**:开箱即用,配合浏览器截图等工具自动生效
|
|
751
|
-
- 图片会在 AI 完成回复后显示(流式输出不支持增量发送图片)
|
|
375
|
+
### WS 断连自动重试
|
|
752
376
|
|
|
753
|
-
|
|
377
|
+
当 WS 断连导致最终回复发送失败时:
|
|
754
378
|
|
|
755
|
-
|
|
379
|
+
1. 插件自动将未送达回复加入 pending 队列(TTL 5 分钟,最多 50 条)
|
|
380
|
+
2. WS 重连并认证成功后,自动通过 Agent API 补发所有 pending 回复
|
|
381
|
+
3. 过期条目自动丢弃,不会无限积压
|
|
756
382
|
|
|
757
|
-
|
|
383
|
+
### 运行时配额感知
|
|
758
384
|
|
|
759
|
-
|
|
385
|
+
插件做本地近似记账,并把状态暴露到账号 snapshot / status:
|
|
760
386
|
|
|
761
|
-
|
|
387
|
+
- 连接占线:同一个 `botId` 被其他实例接管时,标记 `displaced`
|
|
388
|
+
- 24h 被动回复窗口:按会话追踪 reply quota(限额 30,告警 24)
|
|
389
|
+
- 每会话每日主动发送额度:按会话追踪 active send quota(限额 10,告警 8)
|
|
390
|
+
- 接近上限或触顶时输出 warning
|
|
762
391
|
|
|
763
|
-
|
|
392
|
+
当前策略是"感知 + 告警",不做硬阻断。
|
|
764
393
|
|
|
765
|
-
|
|
394
|
+
### 支持的目标格式
|
|
766
395
|
|
|
767
|
-
|
|
396
|
+
| 格式 | 示例 | 说明 |
|
|
397
|
+
| --- | --- | --- |
|
|
398
|
+
| `wecom:<userId>` | `wecom:zhangsan` | 发给企业微信用户 |
|
|
399
|
+
| `group:<chatId>` | `group:wr123456` | 发给群聊 |
|
|
400
|
+
| `party:<id>` | `party:2` | 发给部门 |
|
|
401
|
+
| `tag:<name>` | `tag:Developers` | 发给标签 |
|
|
402
|
+
| `webhook:<name>` | `webhook:ops` | 发给 webhook 群 |
|
|
403
|
+
| `<chatId>` | `wr123456` | 直接写群 ID 也可识别 |
|
|
768
404
|
|
|
769
|
-
|
|
770
|
-
2. 获取应用凭证:
|
|
771
|
-
- `corpId`: 企业 ID(在"我的企业"页面)
|
|
772
|
-
- `agentId`: 应用 ID
|
|
773
|
-
- `corpSecret`: 应用 Secret
|
|
774
|
-
3. 设置接收消息:
|
|
775
|
-
- 获取 `token` 和 `encodingAesKey`(随机生成)
|
|
776
|
-
- 回调 URL: `https://your-domain.com/webhooks/app`
|
|
405
|
+
## 动态 Agent 与路由
|
|
777
406
|
|
|
778
|
-
|
|
779
|
-
```json
|
|
780
|
-
{
|
|
781
|
-
"channels": {
|
|
782
|
-
"wecom": {
|
|
783
|
-
"agent": {
|
|
784
|
-
"corpId": "wwxxxxxxxxxxxxxxxx",
|
|
785
|
-
"corpSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
786
|
-
"agentId": 1000002,
|
|
787
|
-
"token": "your_callback_token",
|
|
788
|
-
"encodingAesKey": "your_43_char_encoding_aes_key"
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
```
|
|
407
|
+
### 动态 Agent
|
|
794
408
|
|
|
795
|
-
|
|
409
|
+
默认路由规则:
|
|
796
410
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
| 主动推送 | 不支持 | 支持 |
|
|
802
|
-
| 媒体下载 | 不支持 | 支持 |
|
|
803
|
-
| 文件消息 | 不支持 | 支持 |
|
|
411
|
+
- 私聊:`wecom-dm-<userId>`
|
|
412
|
+
- 群聊:`wecom-group-<chatId>`
|
|
413
|
+
- 多账号私聊:`wecom-<accountId>-dm-<userId>`
|
|
414
|
+
- 多账号群聊:`wecom-<accountId>-group-<chatId>`
|
|
804
415
|
|
|
805
|
-
|
|
416
|
+
好处:
|
|
806
417
|
|
|
807
|
-
|
|
418
|
+
- 每个用户 / 群聊独立上下文
|
|
419
|
+
- 每个动态 Agent 独立工作区
|
|
420
|
+
- 可以按账号进一步隔离
|
|
808
421
|
|
|
809
|
-
|
|
422
|
+
### Workspace 模板
|
|
810
423
|
|
|
811
|
-
|
|
812
|
-
2. 复制 Webhook URL(包含 key 参数)
|
|
813
|
-
3. 在配置中添加 webhook 映射:
|
|
814
|
-
```json
|
|
815
|
-
{
|
|
816
|
-
"channels": {
|
|
817
|
-
"wecom": {
|
|
818
|
-
"webhooks": {
|
|
819
|
-
"ops-group": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx",
|
|
820
|
-
"dev-group": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=yyy"
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
```
|
|
424
|
+
`workspaceTemplate` 目录中的 bootstrap 文件会在动态 Agent 首次创建时复制到工作区:
|
|
826
425
|
|
|
827
|
-
|
|
828
|
-
- 文本:`webhook:ops-group`
|
|
829
|
-
- 支持 Markdown、图片、文件等多种消息类型
|
|
426
|
+
- `AGENTS.md`、`BOOTSTRAP.md`、`CLAUDE.md`、`SOUL.md`、`TOOLS.md`、`IDENTITY.md`、`USER.md`、`HEARTBEAT.md`、`system-prompt.md`
|
|
830
427
|
|
|
831
|
-
|
|
428
|
+
模板支持 mtime 变更检测 — 当模板文件更新后,下次 Agent 启动会增量同步。
|
|
832
429
|
|
|
833
|
-
|
|
430
|
+
### Bindings
|
|
834
431
|
|
|
835
|
-
|
|
836
|
-
|------|------|------|
|
|
837
|
-
| **Layer 1** | 活跃流式通道 | 正常对话时,消息通过流式通道实时推送 |
|
|
838
|
-
| **Layer 2** | response_url | 流式通道关闭后 1 小时内,可通过 response_url 发送 |
|
|
839
|
-
| **Layer 3a** | Webhook Bot | 目标以 `webhook:` 开头时,使用 Webhook 发送 |
|
|
840
|
-
| **Layer 3b** | Agent API | 配置了 Agent 时,通过自建应用 API 主动推送 |
|
|
432
|
+
如果 OpenClaw 配置了 `bindings`,则优先按 binding 路由,不会被动态 Agent 覆盖。
|
|
841
433
|
|
|
842
|
-
|
|
434
|
+
## 常见问题
|
|
843
435
|
|
|
844
|
-
### Q:
|
|
436
|
+
### Q: 2.0 和之前最大的区别是什么?
|
|
845
437
|
|
|
846
|
-
|
|
847
|
-
- WebUI 访问认证
|
|
848
|
-
- WebSocket 连接认证
|
|
849
|
-
- CLI 远程连接认证
|
|
438
|
+
2.0 完全采用 WebSocket 长连接,不再使用 HTTP 回调。需要在企业微信后台将机器人切换到[长连接模式](https://open.work.weixin.qq.com/help2/pc/cat?doc_id=21657)。
|
|
850
439
|
|
|
851
|
-
|
|
852
|
-
- 使用企业微信自己的签名验证(Token + EncodingAESKey)
|
|
853
|
-
- 不需要 Gateway Auth Token
|
|
854
|
-
- OpenClaw 插件系统会自动处理 webhook 路由
|
|
855
|
-
|
|
856
|
-
**部署建议:**
|
|
857
|
-
1. 如果使用反向代理(如 Nginx),可以为 `/webhooks/wecom` 路径配置豁免认证
|
|
858
|
-
2. 或者将 webhook 端点暴露在独立端口,不经过 Gateway Auth
|
|
859
|
-
|
|
860
|
-
### Q: EncodingAESKey 长度验证失败怎么办?
|
|
861
|
-
|
|
862
|
-
**A:** 常见原因和解决方法:
|
|
863
|
-
|
|
864
|
-
1. **检查配置键名**:确保使用正确的键名 `encodingAesKey`(注意大小写)
|
|
865
|
-
```json
|
|
866
|
-
{
|
|
867
|
-
"channels": {
|
|
868
|
-
"wecom": {
|
|
869
|
-
"encodingAesKey": "..."
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
```
|
|
874
|
-
|
|
875
|
-
2. **检查密钥长度**:EncodingAESKey 必须是 43 位字符
|
|
876
|
-
```bash
|
|
877
|
-
# 检查长度
|
|
878
|
-
echo -n "你的密钥" | wc -c
|
|
879
|
-
```
|
|
880
|
-
|
|
881
|
-
3. **检查是否有多余空格/换行**:确保密钥字符串前后没有空格或换行符
|
|
882
|
-
|
|
883
|
-
### Q: 日志报错 reply delivery failed ... 60020 not allow to access from your ip 怎么办?
|
|
884
|
-
|
|
885
|
-
**A:** 这是企业微信对「自建应用 API 主动发送消息」的安全限制。错误码 60020 表示:当前服务器出口公网 IP 未加入企业微信应用的可信 IP 白名单。
|
|
886
|
-
|
|
887
|
-
**典型日志示例:**
|
|
440
|
+
### Q: 之前用的官方插件 `@wecom/wecom-openclaw-plugin`,怎么迁移?
|
|
888
441
|
|
|
889
442
|
```bash
|
|
890
|
-
|
|
443
|
+
# 卸载官方插件
|
|
444
|
+
openclaw plugins uninstall wecom-openclaw-plugin
|
|
445
|
+
# 安装本插件
|
|
446
|
+
openclaw plugins install @sunnoy/wecom
|
|
447
|
+
# 重启
|
|
448
|
+
openclaw gateway restart
|
|
891
449
|
```
|
|
892
450
|
|
|
451
|
+
`channels.wecom` 配置字段兼容,无需修改。
|
|
893
452
|
|
|
453
|
+
### Q: `dmPolicy: "open"` 是不是企业里任何人都能私聊?
|
|
894
454
|
|
|
895
|
-
|
|
455
|
+
是。前提是该成员对这个机器人可见,并且能在企业微信里私聊到它。
|
|
896
456
|
|
|
897
|
-
|
|
898
|
-
如果企业微信后台为该应用启用了 企业可信IP / 接口可信IP 校验,而当前服务器出口公网 IP 不在白名单内,企业微信会拒绝请求并返回 60020。
|
|
457
|
+
### Q: `pairing` 模式怎么放行用户?
|
|
899
458
|
|
|
900
|
-
|
|
459
|
+
用户第一次私聊会收到配对码。管理员执行:
|
|
901
460
|
|
|
902
|
-
|
|
461
|
+
```bash
|
|
462
|
+
openclaw pairing approve wecom <code>
|
|
463
|
+
```
|
|
903
464
|
|
|
904
|
-
|
|
465
|
+
### Q: Agent 还需要配置 `token` / `encodingAesKey` 吗?
|
|
905
466
|
|
|
906
|
-
|
|
467
|
+
不需要。Agent 只做增强出站,保留 `corpId`、`corpSecret`、`agentId` 即可。
|
|
907
468
|
|
|
908
|
-
|
|
909
|
-
- 建议以错误日志中的 from ip 为准(你的服务器公网ip)
|
|
469
|
+
### Q: 入站图片还依赖全局 `EncodingAESKey` 吗?
|
|
910
470
|
|
|
911
|
-
|
|
471
|
+
不依赖。WS 消息体里的图片 / 文件自带独立 `aeskey`,插件按 `image.aeskey` 或 `file.aeskey` 下载与解密。
|
|
912
472
|
|
|
913
|
-
|
|
473
|
+
### Q: 收到 `disconnected_event` 是什么情况?
|
|
914
474
|
|
|
915
|
-
|
|
916
|
-
openclaw-plugin-wecom/
|
|
917
|
-
├── index.js # 插件入口
|
|
918
|
-
├── package.json # npm 包配置
|
|
919
|
-
├── openclaw.plugin.json # OpenClaw 插件清单
|
|
920
|
-
├── crypto.js # 企业微信加密算法(消息 + 媒体)
|
|
921
|
-
├── logger.js # 日志模块
|
|
922
|
-
├── utils.js # 工具函数(TTL 缓存、消息去重)
|
|
923
|
-
├── stream-manager.js # 流式回复管理
|
|
924
|
-
├── think-parser.js # 思考标签解析(<think> 标签分离)
|
|
925
|
-
├── image-processor.js # 图片编码/校验(msg_item)
|
|
926
|
-
├── webhook.js # 企业微信 Bot 模式 HTTP 通信处理
|
|
927
|
-
├── dynamic-agent.js # 动态 Agent 分配逻辑
|
|
928
|
-
├── wecom/ # 核心模块目录
|
|
929
|
-
│ ├── channel-plugin.js # 主频道插件逻辑
|
|
930
|
-
│ ├── http-handler.js # HTTP 请求处理器
|
|
931
|
-
│ ├── agent-api.js # Agent API 客户端(AccessToken 缓存、消息发送)
|
|
932
|
-
│ ├── agent-inbound.js # Agent 模式入站处理器(XML 回调)
|
|
933
|
-
│ ├── webhook-bot.js # Webhook Bot 客户端
|
|
934
|
-
│ ├── inbound-processor.js # 入站消息处理器
|
|
935
|
-
│ ├── xml-parser.js # XML 解析器(Agent 模式)
|
|
936
|
-
│ ├── target.js # 目标解析器(支持多种目标格式)
|
|
937
|
-
│ ├── commands.js # 命令处理
|
|
938
|
-
│ ├── constants.js # 常量定义
|
|
939
|
-
│ ├── state.js # 状态管理
|
|
940
|
-
│ ├── stream-utils.js # 流式处理工具
|
|
941
|
-
│ ├── response-url.js # response_url 处理
|
|
942
|
-
│ ├── allow-from.js # 权限控制
|
|
943
|
-
│ ├── media.js # 媒体文件处理
|
|
944
|
-
│ ├── webhook-targets.js # Webhook 目标管理
|
|
945
|
-
│ └── workspace-template.js # 工作区模板
|
|
946
|
-
├── tests/ # 测试目录
|
|
947
|
-
│ ├── e2e/
|
|
948
|
-
│ │ ├── remote-wecom.e2e.test.js # 真实远程 E2E(加密请求 + stream 轮询)
|
|
949
|
-
│ │ └── run-ali-ai.sh # ssh ali-ai 一键联调脚本
|
|
950
|
-
│ │ ├── prepare-browser-sandbox.sh # browser sandbox 环境检查/准备
|
|
951
|
-
│ │ └── collect-browser-pdf.sh # 收集并下载 PDF 测试产物
|
|
952
|
-
│ ├── outbound.test.js # 出站投递回退逻辑测试
|
|
953
|
-
│ ├── target.test.js # 目标解析器测试
|
|
954
|
-
│ └── xml-parser.test.js # XML 解析器测试
|
|
955
|
-
├── README.md # 本文档
|
|
956
|
-
├── CONTRIBUTING.md # 贡献指南
|
|
957
|
-
└── LICENSE # 开源协议
|
|
958
|
-
```
|
|
475
|
+
通常表示同一个 `botId` 被另一个实例接管了。企业微信同一时刻只允许一个活跃长连接。
|
|
959
476
|
|
|
960
|
-
|
|
477
|
+
### Q: 什么时候会走 Agent 或 Webhook?
|
|
961
478
|
|
|
962
|
-
|
|
479
|
+
- `webhook:<name>` 目标固定走 Webhook
|
|
480
|
+
- 发送部门 / 标签 / 媒体消息时优先走 Agent
|
|
481
|
+
- WS 断连后的 pending 回复通过 Agent API 补发
|
|
482
|
+
- WS 文本主动发送失败时,尝试回退到 Agent
|
|
963
483
|
|
|
964
|
-
|
|
484
|
+
### Q: `60020 not allow to access from your ip` 是什么问题?
|
|
965
485
|
|
|
966
|
-
|
|
486
|
+
企业微信自建应用 API 的可信 IP 限制。把当前服务器出口 IP 加入企业微信应用的可信 IP 白名单即可。
|
|
967
487
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
## 自定义 Skills 配合沙箱使用实践
|
|
488
|
+
## 项目结构
|
|
971
489
|
|
|
972
|
-
|
|
490
|
+
```text
|
|
491
|
+
openclaw-plugin-wecom/
|
|
492
|
+
├── index.js # 插件入口、生命周期、onboarding
|
|
493
|
+
├── dynamic-agent.js # 动态 Agent 路由判断
|
|
494
|
+
├── image-processor.js # 图片格式检测、MD5、Base64
|
|
495
|
+
├── logger.js # 结构化日志
|
|
496
|
+
├── think-parser.js # <think> 标签规范化
|
|
497
|
+
├── utils.js # 工具函数
|
|
498
|
+
├── openclaw.plugin.json # 插件元数据
|
|
499
|
+
├── wecom/
|
|
500
|
+
│ ├── accounts.js # 多账号管理与配置继承
|
|
501
|
+
│ ├── agent-api.js # Agent API(Token、发送、上传)
|
|
502
|
+
│ ├── allow-from.js # allowlist 规范化与匹配
|
|
503
|
+
│ ├── channel-plugin.js # 核心通道(sendNotice / sendMedia)
|
|
504
|
+
│ ├── commands.js # 指令白名单与命令拦截
|
|
505
|
+
│ ├── constants.js # 常量定义
|
|
506
|
+
│ ├── dm-policy.js # 私聊准入策略
|
|
507
|
+
│ ├── group-policy.js # 群聊准入策略
|
|
508
|
+
│ ├── http.js # HTTP 请求 + 代理
|
|
509
|
+
│ ├── onboarding.js # CLI 交互式配置向导
|
|
510
|
+
│ ├── runtime-telemetry.js # 运行时配额追踪
|
|
511
|
+
│ ├── sandbox.js # 沙箱集成
|
|
512
|
+
│ ├── state.js # 插件状态管理
|
|
513
|
+
│ ├── target.js # 目标解析(user / group / party / tag / webhook)
|
|
514
|
+
│ ├── webhook-bot.js # Webhook Bot 发送
|
|
515
|
+
│ ├── workspace-template.js # 工作区模板同步
|
|
516
|
+
│ ├── ws-monitor.js # WS 消息处理、流式回复、节流、重试
|
|
517
|
+
│ └── ws-state.js # WS 状态 + pending reply 队列
|
|
518
|
+
└── tests/
|
|
519
|
+
├── accounts-reserved-keys.test.js
|
|
520
|
+
├── api-base-url.test.js
|
|
521
|
+
├── channel-plugin.media-type.test.js
|
|
522
|
+
├── channel-plugin.notice.test.js
|
|
523
|
+
├── dynamic-agent.test.js
|
|
524
|
+
├── image-processor.test.js
|
|
525
|
+
├── issue-fixes.test.js
|
|
526
|
+
├── reply-media-directive.test.js
|
|
527
|
+
├── runtime-telemetry.test.js
|
|
528
|
+
├── target.test.js
|
|
529
|
+
├── think-parser.test.js
|
|
530
|
+
├── workspace-template.test.js
|
|
531
|
+
├── ws-monitor.quote-mixed.test.js
|
|
532
|
+
└── ws.e2e.test.js
|
|
533
|
+
```
|
|
973
534
|
|
|
535
|
+
## 自定义 Skills 配合沙箱使用实践
|
|
974
536
|
|
|
975
|
-
|
|
537
|
+
OpenClaw 支持自定义 Skills 并通过沙箱(Docker)隔离执行,下面保留一份生产环境常见配置示例:
|
|
976
538
|
|
|
977
539
|
```json
|
|
978
540
|
{
|
|
@@ -1013,31 +575,23 @@ OpenClaw 支持自定义 Skills 并通过沙箱(Docker)隔离执行,以下
|
|
|
1013
575
|
}
|
|
1014
576
|
```
|
|
1015
577
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
### 使用流程
|
|
1038
|
-
|
|
1039
|
-
1. 在宿主机创建自定义 skill 目录
|
|
1040
|
-
2. 配置 `binds` 将目录映射到沙箱
|
|
1041
|
-
3. 在 `skills.load.extraDirs` 指定加载路径
|
|
1042
|
-
4. Agent 在沙箱中可通过 `/workspace/skills` 访问自定义 skills
|
|
1043
|
-
5. 使用 `/skill` 命令查看和管理 skills
|
|
578
|
+
关键点:
|
|
579
|
+
|
|
580
|
+
- `sandbox.mode: "all"` 表示所有操作都走沙箱
|
|
581
|
+
- `sandbox.workspaceAccess: "rw"` 允许 Agent 读写工作区
|
|
582
|
+
- `sandbox.scope: "agent"` 表示每个 Agent 独立沙箱
|
|
583
|
+
- `sandbox.docker.binds` 可把宿主机技能目录映射到容器内 `/workspace/skills`
|
|
584
|
+
- `skills.load.extraDirs` 用于声明自定义 Skills 加载目录
|
|
585
|
+
- `skills.load.watch` 改动 Skill 后自动热加载
|
|
586
|
+
|
|
587
|
+
## 相关链接
|
|
588
|
+
|
|
589
|
+
- [OpenClaw](https://github.com/openclaw/openclaw) — 开源 AI Agent 运行时
|
|
590
|
+
- [官方 WeCom OpenClaw 插件](https://github.com/WecomTeam/wecom-openclaw-plugin)([npm](https://www.npmjs.com/package/@wecom/wecom-openclaw-plugin))
|
|
591
|
+
- [`@wecom/aibot-node-sdk`](https://github.com/WecomTeam/aibot-node-sdk) — 企业微信智能机器人 Node.js SDK
|
|
592
|
+
- [企业微信 AI 机器人官方文档](https://open.work.weixin.qq.com/help2/pc/cat?doc_id=21657)
|
|
593
|
+
|
|
594
|
+
## 贡献与协议
|
|
595
|
+
|
|
596
|
+
- 贡献说明见 `CONTRIBUTING.md`
|
|
597
|
+
- 许可证为 `ISC`
|