OpenClaw-Wechat 是一个面向 OpenClaw 的企业微信渠道插件,支持两种接入方式:
Agent 模式:企业微信自建应用(XML 回调,经典模式)Bot 模式:企业微信智能机器人 API 模式(JSON 回调,原生 stream)Webhook 目标出站:将消息主动投递到企业微信群 Webhook 或命名 Webhook 目标
适用于“个人微信扫码进入企业微信应用对话”、“企业内员工问答助手”、“多账户多业务线消息分流”等场景。
- 重大更新(v2.0.0)
- 功能概览
- 模式对比
- 5 分钟极速上手
- 前置要求
- 安装与加载
- 配置文件与路径职责
- 快速开始
- 文档工具(WeCom Doc)
- 配置参考
- 消息能力矩阵
- 命令与会话策略
- 环境变量速查
- 公网回调与 Gateway Auth
- Webhook 与 Heartbeat 运维
- 与其他渠道并存建议
- 故障排查
- 开发与发布
- FAQ
- 版本与贡献
这次是一次真正的能力级更新,不是小修补。
OpenClaw-Wechat 现在已经把 企业微信智能机器人长连接 正式做成可用能力,并且已经在真实网关环境下完成:
- WebSocket 握手成功
aibot_subscribe鉴权成功- 心跳
ping/ 回执成功 - 网关日志出现
socket opened和subscribed
| 项目 | 结果 |
|---|---|
| 官方地址 | wss://openws.work.weixin.qq.com |
| 入站命令 | aibot_msg_callback / aibot_event_callback |
| 出站命令 | aibot_respond_msg |
| 运行时实现 | 已切换为 ws,不再使用会导致 1006 的 Node 内置 WebSocket |
| Bot 回调公网依赖 | 长连接模式下不需要 |
| 自检命令 | npm run wecom:bot:longconn:probe -- --json |
这次版本同时还保留并增强了原有的 WeCom Doc 工具链。
现在 OpenClaw-Wechat 已经同时具备:
- 后台可视化配置
- WeCom Doc 文档/表格/收集表工具
- 文档权限与协作者管理
- 分享链接可用性诊断
- 文档权限打不开问题的直接诊断
- 链接文本输出完整性修复(URL 下划线不再丢失)
| 场景 | 旧问题 | 现在的处理方式 |
|---|---|---|
| 企业微信 Bot 长连接 | 旧版地址、命令字和运行时实现不对,连接阶段直接 1006 |
已对齐官方地址、协议命令和 ws 实现,真实网关已订阅成功 |
| 想验证“到底连上没有” | 只能看零散日志,难以区分握手、鉴权还是心跳失败 | wecom:bot:longconn:probe 会直接验证握手、鉴权与心跳 |
| 创建文档后自己打不开 | 文档创建成功,但发起人没被自动授权 | create 默认自动把当前企微请求人加入协作者 |
| 分享链接能发出来,但别人打开像“文档不存在” | 无法快速判断是权限、分享码还是 guest 访问问题 | validate_share_link 直接诊断 guest / blankpage / scode / 路径资源 ID |
| 只知道“更新成员权限成功”,但还是打不开 | 成员权限、查看规则、外部分享是三套概念,容易混淆 | diagnose_auth 直接输出企业内/企业外访问、查看成员、协作者与请求人角色 |
把分享链接路径当成 docId 使用 |
后续 API 调用报 invalid docid |
create/share/get_auth 结果显式返回真实 docId,并给出使用提示 |
| 链接里有下划线,发出去后被改坏 | Markdown 清洗误伤 URL | 文本格式化已修复,URL 下划线完整保留 |
| 项目 | 现状 | 说明 |
|---|---|---|
| WeCom 配置表单 | ✅ | channels.wecom 支持在后台页面直接编辑与保存 |
| 中文字段标签 | ✅ | 常用字段(如 corpId、callbackToken、accounts.*)均已中文化 |
| 敏感项标记 | ✅ | secret/token/aesKey 字段按敏感项展示 |
| 状态展示 | ✅ | Connected 不再长期 n/a,默认账号显示名中文化为“默认账号” |
| 入站状态追踪 | ✅ | 收到回调后自动更新 Last inbound(重启后首次入站前为 n/a 属正常) |
| 文档工具开关 | ✅ | tools.doc 等文档相关配置可被 schema 正确识别 |
| 能力层 | 新增内容 |
|---|---|
| 文档基础 | create、rename、get_info、share、delete |
| 权限管理 | grant_access、add_collaborators、set_join_rule、set_member_auth、set_safety_setting |
| 运维诊断 | get_auth、diagnose_auth、validate_share_link |
| 表格/收集表 | get_sheet_properties、create_collect、modify_collect、get_form_info、get_form_answer、get_form_statistic |
- 在 OpenClaw 后台的
Channels -> WeCom页面可直接配置并保存核心参数。 - 在同一个插件里直接调用
wecom_doc,不需要额外安装第二个 WeCom Doc 插件。 - 现在排查“为什么这个链接打不开”不需要再手翻日志和原始 JSON,工具会直接给出结论。
- 文档创建、协作者授权、分享链接诊断已经形成闭环,适合直接上线给真实企微用户使用。
适合“先跑起来再细调”的场景。
openclaw plugins install @dingxiang-me/openclaw-wechat最低建议版本:
2.0.0。如果openclaw.json里的plugins.installs.openclaw-wechat仍显示1.7.x,请先升级或重装;旧包不会正确注册wecomchannel 元数据。
如果你是在本地开发或要直接跑仓库源码,再用下面这套:
git clone https://github.com/dingxiang-me/OpenClaw-Wechat.git
cd OpenClaw-Wechat
npm install如果你是通过 openclaw plugins install 安装,在 ~/.openclaw/openclaw.json 增加:
{
"plugins": {
"enabled": true,
"allow": ["openclaw-wechat"],
"entries": {
"openclaw-wechat": {
"enabled": true
}
}
}
}如果你是源码路径加载,再使用下面这版(多一个 load.paths):
{
"plugins": {
"enabled": true,
"allow": ["openclaw-wechat"],
"load": {
"paths": ["/path/to/OpenClaw-Wechat"]
},
"entries": {
"openclaw-wechat": {
"enabled": true
}
}
}
}| 模式 | 回调路径 | 企业微信侧类型 | 最少需要的配置 |
|---|---|---|---|
| Agent(自建应用) | /wecom/callback |
自建应用 API 接收 | corpId/corpSecret/agentId/callbackToken/callbackAesKey |
| Bot(智能机器人) | /wecom/bot/callback |
智能机器人 API 模式 | bot.enabled/token/encodingAesKey |
| Bot(智能机器人长连接) | 无需公网回调 | 智能机器人 长连接模式 | bot.enabled/bot.longConnection.enabled/bot.longConnection.botId/bot.longConnection.secret |
Agent 模式补充(重要):在企业微信自建应用后台请配置可信 IP,把 OpenClaw 网关实际出网 IP 加入白名单。否则可能出现“能收到消息但不回复”。
openclaw gateway restart
openclaw gateway status
npm run wecom:selfcheck -- --all-accounts
npm run wecom:agent:selfcheck -- --all-accounts
npm run wecom:bot:selfcheck -- --all-accounts| 验证项 | 预期结果 |
|---|---|
| 文本消息 | 机器人返回文本 |
| 图片消息(Bot) | 不再提示“图片接收失败”,可识别图像内容 |
openclaw gateway status |
RPC probe: ok 且 WeCom 状态正常 |
| 能力 | 状态 | 说明 |
|---|---|---|
| 企业微信入站消息处理 | ✅ | 文本、图片、语音、链接、文件/视频(Agent + Bot) |
| AI 自动回复 | ✅ | 接入 OpenClaw Runtime,自动路由 Agent |
| Bot 原生 stream 协议 | ✅ | msgtype=stream 刷新与增量回包 |
| Bot 长连接(WebSocket) | ✅ | 原生 aibot_subscribe / aibot_msg_callback / aibot_respond_msg |
| Bot 卡片回包 | ✅ | 支持 markdown/template_card,失败自动降级文本 |
| 多账户 | ✅ | channels.wecom.accounts.<id> |
| 发送者授权控制 | ✅ | allowFrom + 账户级覆盖 |
| 私聊策略(DM) | ✅ | dm.mode=open/allowlist/deny + 账户级覆盖 |
| 事件欢迎语(enter_agent) | ✅ | events.enterAgentWelcome* 可配置 |
| 命令白名单 | ✅ | /help /status /clear /new 等 |
| 群聊触发策略 | ✅ | 支持 direct/mention/keyword 三种模式 |
| 企业微信文档工具 | ✅ | 内置 wecom_doc 工具:创建/重命名/分享/权限管理/收集表/表格属性 |
| 文本防抖合并 | ✅ | 窗口期内多条消息合并投递 |
| 异步补发(超时后) | ✅ | transcript 轮询补发最终回复 |
| 观测统计 | ✅ | 入站/回包/错误计数 + 最近失败样本(/status) |
| WeCom 出站代理 | ✅ | outboundProxy / WECOM_PROXY |
| 能力 | 状态 | 说明 |
|---|---|---|
| 图片识别(入站) | ✅ | 支持 URL 下载、类型识别、必要时解密后识别 |
| 图片发送(出站) | ✅ | Agent 模式支持 |
| 语音/视频/文件发送(出站) | ✅ | 自动判型上传后发送(语音支持 AMR/SILK) |
| 语音转写(本地) | ✅ | 企业微信 Recognition 优先,缺失时回退本地 whisper |
| Bot 模式媒体回传 | ✅ | active_stream 优先 msg_item(image);失败自动降级媒体链接,response_url/Webhook Bot 继续兜底 |
| Bot 思考过程展示 | ✅ | 识别 <think>/<thinking>/<thought>,映射到原生 thinking_content 折叠区 |
| Bot 文件入站 | ✅ | 支持 msgtype=file 下载并注入会话上下文 |
| Bot 引用消息上下文 | ✅ | 自动将 quote 内容前置到本轮上下文 |
| 维度 | Agent 模式(自建应用) | Bot 模式(智能机器人 API) |
|---|---|---|
| 回调数据格式 | XML | JSON |
| 企业微信创建方式 | 应用管理 -> 自建应用 | 智能机器人 -> API 模式 |
| 回调路径默认值 | /wecom/callback |
/wecom/bot/callback |
| 回复机制 | 主动调用 WeCom 发送 API | 回调响应 stream + 轮询刷新 |
| 流式体验 | 多条消息模拟增量 | 原生 stream 协议 |
| 思考展示 | 不适用 | 支持 <think> 标签映射到 thinking_content |
| 出站媒体(图/语音/视频/文件) | 支持 | 支持(active_stream msg_item(image) + response_url/Webhook 回包,video 自动按 file 回传) |
| 典型场景 | 标准企业应用、菜单/回调体系 | 对话机器人、连续流式问答 |
| 场景 | 建议 |
|---|---|
| 同时开 Agent + Bot | 使用不同路径:/wecom/callback 与 /wecom/bot/callback |
| 多账户 Agent | 每个账户独立路径(如 /wecom/sales/callback) |
| 与 Telegram/Feishu 并存 | 不复用任何 webhook path,避免路由冲突 |
| 项目 | 说明 |
|---|---|
| OpenClaw | 已安装并可正常运行 Gateway |
| 企业微信管理员权限 | 可创建应用或智能机器人并配置回调 |
| 公网入口 | 企业微信需回调到可访问 URL(常见用 Cloudflare Tunnel) |
| Node.js | 与 OpenClaw 运行环境一致 |
| 本地语音识别(可选) | whisper-cli 或 whisper |
| ffmpeg(推荐) | AMR 等格式转码时需要 |
openclaw plugins install @dingxiang-me/openclaw-wechat安装后插件会进入 ~/.openclaw/extensions/openclaw-wechat/。这个目录主要用于 OpenClaw 运行时发现插件,通常不建议直接手改其中的 package.json、package-lock.json、openclaw.plugin.json。
git clone https://github.com/dingxiang-me/OpenClaw-Wechat.git
cd OpenClaw-Wechat
npm install在 ~/.openclaw/openclaw.json 中配置插件加载:
{
"plugins": {
"enabled": true,
"allow": ["openclaw-wechat"],
"load": {
"paths": ["/path/to/OpenClaw-Wechat"]
},
"entries": {
"openclaw-wechat": {
"enabled": true
}
}
}
}Issue #25 里问到的几个路径,职责完全不同。先把边界理清:
| 路径 | 应不应该手改 | 作用 |
|---|---|---|
~/.openclaw/openclaw.json |
应该 | OpenClaw 主配置入口。插件加载、channels.wecom.*、bindings、env.vars 都写这里 |
~/.openclaw/extensions/openclaw-wechat/package.json |
一般不要 | 已安装插件包的元数据,不是业务配置入口 |
~/.openclaw/extensions/openclaw-wechat/openclaw.plugin.json |
一般不要 | 插件 manifest / schema,供 OpenClaw 识别配置结构 |
~/.openclaw/extensions/openclaw-wechat/package-lock.json |
不要 | 安装锁文件,不承载运行配置 |
~/.openclaw/agents/<id>/sessions/sessions.json |
不要 | 运行时会话索引,属于状态数据,不是配置文件 |
~/.openclaw/agents/<id>/sessions/*.jsonl |
不要 | 会话 transcript / 运行产物 |
Windows 对应关系也是同一套逻辑,例如:
| Windows 示例路径 | 结论 |
|---|---|
D:\\Win\\AppData\\LocalLow\\.openclaw\\openclaw.json |
这是主配置文件,参数加这里 |
D:\\Win\\AppData\\LocalLow\\.openclaw\\extensions\\openclaw-wechat\\openclaw.plugin.json |
这是插件 schema,不是让你填业务参数的地方 |
D:\\Win\\AppData\\LocalLow\\.openclaw\\agents\\main\\sessions\\sessions.json |
这是运行态索引,不要手动写参数 |
| 参数类型 | 推荐位置 |
|---|---|
| 插件启用 / 加载 | plugins.enabled、plugins.allow、plugins.entries.openclaw-wechat |
| 企业微信业务配置 | channels.wecom.* |
| 多账号配置 | channels.wecom.accounts.<id>.* |
| 文档工具默认账号 | channels.wecom.defaultAccount |
| 账号到 Agent 路由 | OpenClaw 根配置 bindings |
| 敏感信息 | 优先 env.vars.* 或系统环境变量;其次写入 openclaw.json |
| 方式 | 适合什么 |
|---|---|
| Control UI | 日常调整常规字段:corpId、callbackToken、accounts.*、tools.doc |
openclaw.json |
结构化配置、版本管理、多人协作、bindings |
env.vars / 系统环境变量 |
Secret、代理、不同环境下的覆盖项 |
- 创建自建应用,拿到
AgentId、Secret - 在“我的企业”拿到
CorpId - 开启“接收消息”,配置:
- URL:
https://你的域名/wecom/callback - Token: 自定义随机字符串
- EncodingAESKey: 企业微信生成
- URL:
- 创建智能机器人时选择 API 模式
- 配置回调 URL:
https://你的域名/wecom/bot/callback - 获取并保存
token与encodingAesKey
{
"channels": {
"wecom": {
"enabled": true,
"corpId": "wwxxxx",
"corpSecret": "xxxx",
"agentId": 1000004,
"callbackToken": "xxxx",
"callbackAesKey": "xxxx",
"webhookPath": "/wecom/callback"
}
}
}{
"channels": {
"wecom": {
"enabled": true,
"bot": {
"enabled": true,
"token": "xxxx",
"encodingAesKey": "xxxx",
"webhookPath": "/wecom/bot/callback"
}
}
}
}{
"channels": {
"wecom": {
"enabled": true,
"bot": {
"enabled": true,
"longConnection": {
"enabled": true,
"botId": "your-bot-id",
"secret": "your-bot-secret"
}
}
}
}
}openclaw gateway restart
openclaw gateway status
openclaw plugins list
npm run wecom:selfcheck -- --all-accounts
npm run wecom:bot:selfcheck -- --account defaultwecom:selfcheck 帮助:
node ./scripts/wecom-selfcheck.mjs --helpwecom:bot:selfcheck 帮助:
node ./scripts/wecom-bot-selfcheck.mjs --help插件现在内置了 wecom_doc 工具,不需要额外安装第二个插件。它复用当前 OpenClaw-Wechat 的账号、代理和多账户配置。
当前 wecom_doc 重点覆盖创建、权限、分享、收集表和诊断能力;不包含富文本正文编辑器式的文档内容编辑。如果需要改正文,请先在产品描述里明确这是后续能力,不要按“已支持编辑”对外承诺。
| action | 说明 | 关键参数 |
|---|---|---|
create |
新建文档/表格,可创建后立即授权 | docName docType viewers? collaborators? |
rename |
重命名文档 | docId newName |
get_info |
获取文档基础信息 | docId |
share |
获取文档分享信息 | docId |
get_auth |
获取文档权限信息 | docId |
diagnose_auth |
诊断为什么打不开文档/链接 | docId |
validate_share_link |
校验分享链接对 guest/外部访问是否可用 | shareUrl |
delete |
删除文档或收集表 | docId 或 formId |
grant_access |
批量增删查看人/协作者 | docId viewers? collaborators? remove*? |
add_collaborators |
快速添加协作者 | docId collaborators |
set_join_rule |
修改文档可见范围/加入规则 | docId request |
set_member_auth |
修改文档通知成员与权限 | docId request |
set_safety_setting |
修改文档安全设置 | docId request |
create_collect |
创建收集表 | formInfo spaceId? fatherId? |
modify_collect |
修改收集表 | oper formId formInfo |
get_form_info |
获取收集表定义 | formId |
get_form_answer |
获取收集表答案 | repeatedId answerIds? |
get_form_statistic |
获取收集表统计 | requests |
get_sheet_properties |
获取在线表格属性 | docId |
默认启用。你也可以显式配置:
{
"channels": {
"wecom": {
"defaultAccount": "docs",
"tools": {
"doc": true,
"docAutoGrantRequesterCollaborator": true
},
"accounts": {
"docs": {
"corpId": "wwxxxx",
"corpSecret": "xxxx",
"agentId": 1000008,
"tools": {
"doc": true
}
}
}
}
}
}wecom_doc 在执行时按下面顺序选择账号:
- 工具参数里的
accountId - 当前 agent 绑定账号
channels.wecom.defaultAccount- 第一个启用了文档工具的可用账号
默认开启:如果 wecom_doc 是在企业微信会话里被调用,插件会把当前发送者自动加成文档协作者,避免“文档已创建但发起人无权限查看”。
create / share 结果现在会明确返回真实 docId,后续做权限、分享和诊断时应优先使用这个 docId,不要直接拿分享链接路径里的片段代替。
可关闭:
{
"channels": {
"wecom": {
"tools": {
"doc": true,
"docAutoGrantRequesterCollaborator": false
}
}
}
}- “帮我新建一个企微文档,标题是《周会纪要》”
- “把这个文档改名为《Q2 Roadmap》”
- “查询文档
docxxxx的权限信息” - “诊断为什么这个企微文档链接打不开”
- “校验这个企微文档分享链接为什么对外打不开”
- “创建一个企微文档,并把我加成协作者”
- “给文档
docxxxx添加协作者dingxiang” - “把文档
docxxxx授权给alice查看,给bob协作” - “把文档
docxxxx的查看规则改成仅企业内部可见” - “创建一个收集表,标题是《报名表》”
- “查询收集表
formxxxx的定义和题目” - “读取这份收集表最近一次提交答案”
- “获取这个表格的 sheet 属性”
| 目标 | 推荐动作顺序 |
|---|---|
| 创建后立刻给业务同事协作 | create -> grant_access / add_collaborators |
| 判断“为什么别人打不开这个文档” | diagnose_auth -> validate_share_link |
| 给外部链接排障 | 先看 validate_share_link,再决定是否执行 set_join_rule |
| 后续继续操作同一文档 | 始终使用 create/share 返回的真实 docId,不要直接复制分享链接路径片段 |
| 误区 | 正确做法 |
|---|---|
分享链接路径里的 ID 就是 docId |
不一定。以后续工具返回的真实 docId 为准 |
| “加了协作者”就等于任何浏览器都能打开 | 不是。协作者权限、企业内访问、企业外访问、外部分享是不同层级 |
| 链接能在企业微信里打开,就代表外部环境也能打开 | 不成立。guest 视角可能仍然是 blankpage |
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
enabled |
boolean | true |
是否启用 WeCom 渠道 |
corpId |
string | - | 企业 ID(Agent 模式) |
corpSecret |
string | - | 应用 Secret(敏感) |
agentId |
number/string | - | 应用 AgentId |
callbackToken |
string | - | 回调 Token(敏感) |
callbackAesKey |
string | - | 回调 AES Key(敏感) |
webhookPath |
string | /wecom/callback |
Agent 回调路径(非 default 账户未配置时自动生成 /wecom/<accountId>/callback) |
agent |
object | - | 兼容旧配置:agent.corpId/corpSecret/agentId(与顶层 Agent 字段等价) |
outboundProxy |
string | - | WeCom 出站代理 |
defaultAccount |
string | - | 多账号下的默认账号 ID(文档工具等优先使用) |
tools.doc |
boolean | true |
是否启用 wecom_doc 文档工具 |
webhooks |
object | - | 命名 Webhook 目标映射(如 { "ops": "https://...key=xxx" }) |
accounts |
object | - | 多账户配置(支持 accounts.<id>.bot 独立 Bot 配置) |
兼容说明:支持旧字段与旧结构迁移:name、token / encodingAesKey、agent.*、dynamicAgents.*、dm.createAgentOnFirstMessage、dm.allowFrom、workspaceTemplate、commandAllowlist/commandBlockMessage、commands.blockMessage、以及 inline 账户写法 channels.wecom.<accountId>。新配置建议优先使用 accounts.<id>、callbackToken/callbackAesKey、commands.* 与 dynamicAgent.*。
提示:accounts.<id> 现在支持 Bot-only 账号(仅配置 bot.*),不再强制要求 corpId/corpSecret/agentId。
兼容提示:当使用默认新路径时会自动附加 legacy alias,便于旧回调地址平滑迁移:Agent 默认路径会附加 /webhooks/app(多账号为 /webhooks/app/<id>),Bot 默认路径会附加 /webhooks/wecom(多账号为 /webhooks/wecom/<id>)。若 alias 与另一类路由冲突会自动跳过并告警。
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
enabled |
boolean | false |
启用 Bot 模式 |
token |
string | - | Bot 回调 Token(敏感) |
encodingAesKey |
string | - | Bot 回调 AESKey(43 位,敏感) |
webhookPath |
string | /wecom/bot/callback |
Bot 回调路径(非 default 账户未配置时自动生成 /wecom/<accountId>/bot/callback) |
placeholderText |
string | 消息已收到... |
stream 初始占位文案(可设为空字符串) |
streamExpireMs |
integer | 600000 |
stream 状态保留时间(30s~1h) |
replyTimeoutMs |
integer | 90000 |
Bot 等待模型回包超时(15s~10m) |
lateReplyWatchMs |
integer | 180000 |
Bot 超时后异步补发观察窗口(30s~10m) |
lateReplyPollMs |
integer | 2000 |
Bot 异步补发轮询间隔(500ms~10s) |
longConnection |
object | - | 企业微信智能机器人长连接(WebSocket)配置 |
card |
object | 见下方 | Bot 卡片回包策略(response_url / webhook_bot) |
重要限制:企业微信官方 Bot 在群聊里通常仅对
@机器人消息触发回调。
因此 Bot 模式下即使配置groupChat.triggerMode=direct/keyword,也会按mention处理(插件会输出告警)。
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
enabled |
boolean | false |
启用企业微信智能机器人长连接 |
botId |
string | - | 企业微信智能机器人 BotID |
secret |
string | - | 企业微信智能机器人 Secret(敏感) |
url |
string | wss://openws.work.weixin.qq.com |
官方长连接地址 |
pingIntervalMs |
integer | 30000 |
心跳 ping 间隔 |
reconnectDelayMs |
integer | 5000 |
首次重连延迟 |
maxReconnectDelayMs |
integer | 60000 |
指数退避最大重连延迟 |
说明:
- 长连接模式下不需要暴露公网 Bot 回调地址。
- 插件会在网关启动后主动连接
wss://openws.work.weixin.qq.com,并自动发送aibot_subscribe。 - 入站消息与事件分别使用
aibot_msg_callback/aibot_event_callback,统一接入现有 Bot 处理链路。 - 模型 block 输出会直接通过长连接发送
aibot_respond_msg,不是被动等待stream-refresh拉取。
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
enabled |
boolean | false |
启用卡片回包 |
mode |
string | markdown |
markdown(兼容优先)或 template_card |
title |
string | OpenClaw-Wechat |
卡片标题 |
subtitle |
string | - | 卡片副标题 |
footer |
string | - | 卡片底部说明 |
maxContentLength |
integer | 1400 |
卡片正文最大长度(自动截断) |
responseUrlEnabled |
boolean | true |
是否在 response_url 层发送卡片 |
webhookBotEnabled |
boolean | true |
是否在 webhook_bot 层发送卡片 |
当你启用了 accounts 多账户时,可以为每个账户单独配置 Bot 回调密钥、路径、超时和代理;若未配置,则回退到 channels.wecom.bot。
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
enabled |
boolean | false |
是否启用该账户 Bot |
token / callbackToken |
string | - | 该账户 Bot 回调 Token(兼容旧字段) |
encodingAesKey / callbackAesKey |
string | - | 该账户 Bot 回调 AESKey(兼容旧字段) |
webhookPath |
string | /wecom/bot/callback |
该账户 Bot 回调路径 |
placeholderText |
string | 消息已收到... |
stream 初始占位文案 |
streamExpireMs |
integer | 600000 |
stream 状态保留时间 |
replyTimeoutMs |
integer | 90000 |
Bot 等待模型回包超时 |
lateReplyWatchMs |
integer | 180000 |
超时后异步补发观察窗口 |
lateReplyPollMs |
integer | 2000 |
异步补发轮询间隔 |
longConnection |
object | - | 该账户专用长连接配置(覆盖全局 bot.longConnection) |
card |
object | - | 该账户专用卡片回包配置(覆盖全局 bot.card) |
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
doc |
boolean | true |
是否启用该账户的 wecom_doc 工具 |
outboundProxy / proxyUrl / proxy |
string | - | 该账户 Bot 专用代理(优先于全局) |
| 模块 | 配置键 | 作用 |
|---|---|---|
| 发送者授权 | allowFrom / accounts.<id>.allowFrom |
限定可对话用户;支持 * |
| 拒绝文案 | allowFromRejectMessage |
未授权提示 |
| 管理员 | adminUsers |
绕过命令白名单 |
| 命令白名单 | commands.enabled + commands.allowlist |
限制 / 指令 |
| 私聊策略 | dm.mode + dm.allowFrom + dm.rejectMessage |
控制私聊开放/白名单/拒绝 |
| 事件策略 | events.enabled + events.enterAgentWelcomeEnabled + events.enterAgentWelcomeText |
控制事件处理与 enter_agent 欢迎语 |
| 群聊触发 | groupChat.enabled + triggerMode + mentionPatterns + triggerKeywords |
控制群消息触发条件(自建应用支持 direct/mention/keyword;Bot 模式按平台限制固定 mention) |
| 动态路由 | dynamicAgent.*(兼容 dynamicAgents.*、dm.createAgentOnFirstMessage) |
动态 Agent + workspace bootstrap 播种 |
| 模块 | 配置键 | 说明 |
|---|---|---|
| 文本防抖 | debounce.enabled/windowMs/maxBatch |
合并短时间多条文本 |
| Agent 增量回包 | streaming.enabled/minChars/minIntervalMs |
多消息模拟流式 |
| 异步补发 | WECOM_LATE_REPLY_WATCH_MS/POLL_MS |
dispatch 超时后补发最终回复 |
| 观测统计 | observability.enabled/logPayloadMeta |
记录入站/回包/错误并在 /status 展示 |
| 键 | 默认 | 说明 |
|---|---|---|
voiceTranscription.enabled |
true |
开启回退转写 |
provider |
local-whisper-cli |
local-whisper-cli / local-whisper |
command |
自动探测 | 本地命令路径 |
modelPath |
- | whisper-cli 模型路径 |
model |
base |
whisper 模型名 |
timeoutMs |
120000 |
单次转写超时 |
maxBytes |
10485760 |
最大音频大小 |
ffmpegEnabled |
true |
不兼容格式自动转码 |
transcodeToWav |
true |
优先转为 wav |
{
"channels": {
"wecom": {
"outboundProxy": "http://127.0.0.1:7890",
"accounts": {
"default": {
"enabled": true,
"corpId": "ww-default",
"corpSecret": "secret-default",
"agentId": 1000004,
"callbackToken": "token-default",
"callbackAesKey": "aes-default",
"webhookPath": "/wecom/callback",
"allowFrom": ["*"]
},
"sales": {
"enabled": true,
"corpId": "ww-sales",
"corpSecret": "secret-sales",
"agentId": 1000005,
"callbackToken": "token-sales",
"callbackAesKey": "aes-sales",
"webhookPath": "/wecom/sales/callback",
"outboundProxy": "http://10.0.0.5:8888",
"bot": {
"enabled": true,
"token": "sales-bot-token",
"encodingAesKey": "sales-bot-aes",
"webhookPath": "/wecom/sales/bot/callback",
"replyTimeoutMs": 120000,
"outboundProxy": "http://10.0.0.9:7890"
},
"allowFrom": ["alice", "wecom:bob"],
"allowFromRejectMessage": "销售助手未授权,请联系管理员。"
}
}
}
}
}OpenClaw-Wechat 不自己实现第二套路由规则;账号到 Agent 的稳定绑定,直接走 OpenClaw 核心 bindings。插件会把 channel=wecom 和 accountId=<id> 传给核心路由层。
示例:
{
"bindings": [
{
"match": {
"channel": "wecom",
"accountId": "sales"
},
"agentId": "sales"
},
{
"match": {
"channel": "wecom",
"accountId": "support"
},
"agentId": "support"
}
]
}这套绑定优先级高于插件里的动态账号猜测,适合多账号、多业务线、同一 OpenClaw 上挂多个 WeCom 入口的场景。
| 类型 | 入站 | 出站 | 备注 |
|---|---|---|---|
| 文本 | ✅ | ✅ | 自动分段 |
| 图片 | ✅ | ✅ | 入站可识别,出站可发送 |
| 语音 | ✅ | ✅ | 入站支持本地转写回退;出站支持 AMR/SILK |
| 视频 | ✅ | ✅ | 下载并可回包 |
| 文件 | ✅ | ✅ | 下载并可回包 |
| 链接 | ✅ | ❌ | 提取标题/描述/URL |
| 类型 | 入站 | 出站 | 备注 |
|---|---|---|---|
| 文本 | ✅ | ✅ | 原生 stream |
| 图片 | ✅ | ✅ | response_url mixed + webhook fallback |
| 语音 | ✅ | ✅ | 以文本结果回传 |
| 文件 | ✅ | ✅ | Bot 文件入站下载;出站可按 file 回传 |
| mixed(图文) | ✅ | ✅ | 聚合后回文本 |
| 链接/位置 | ✅ | ✅ | 转换为文本上下文 |
| 命令 | 说明 |
|---|---|
/help |
查看帮助 |
/status |
查看运行状态 |
/clear |
清理会话(兼容映射到 /reset) |
/new |
新建会话(兼容映射到 /reset) |
/reset |
重置会话 |
/compact |
压缩会话(由上层运行时支持) |
- 默认账号一用户一会话:
wecom:<userid> - 非默认账号一用户一会话:
wecom:<accountId>:<userid> - 群聊可配置“仅 @ 才触发”,避免误触发
user:wecom:alice/user:alicegroup(chat):group:wrxxxx/chat:wcxxxx(自动走appchat/send)party:party:2/dept:2tag:tag:opswebhook:webhook:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx或webhook:key:xxxwebhook(命名):webhook:ops(从channels.wecom.webhooks.ops或accounts.<id>.webhooks.ops解析)
| 变量 | 必填 | 说明 |
|---|---|---|
WECOM_CORP_ID |
Agent 必填 | 企业 ID |
WECOM_CORP_SECRET |
Agent 必填 | 应用 Secret |
WECOM_AGENT_ID |
Agent 必填 | AgentId |
WECOM_CALLBACK_TOKEN |
Agent 必填 | 回调 Token |
WECOM_CALLBACK_AES_KEY |
Agent 必填 | 回调 AESKey |
WECOM_WEBHOOK_PATH |
否 | Agent 回调路径(默认 /wecom/callback) |
WECOM_WEBHOOK_TARGETS |
否 | 命名 Webhook 目标映射(name=url,多个用 ,/; 分隔) |
| 变量 | 必填 | 说明 |
|---|---|---|
WECOM_BOT_ENABLED |
否 | 是否启用 Bot 模式 |
WECOM_BOT_TOKEN |
Bot 必填 | Bot Token |
WECOM_BOT_ENCODING_AES_KEY |
Bot 必填 | Bot EncodingAESKey |
WECOM_BOT_WEBHOOK_PATH |
否 | Bot 回调路径 |
WECOM_BOT_PLACEHOLDER_TEXT |
否 | stream 占位文案 |
WECOM_BOT_STREAM_EXPIRE_MS |
否 | stream 保留时长 |
WECOM_BOT_REPLY_TIMEOUT_MS |
否 | Bot 等待模型回包超时 |
WECOM_BOT_LATE_REPLY_WATCH_MS |
否 | Bot 超时后补发观察窗口 |
WECOM_BOT_LATE_REPLY_POLL_MS |
否 | Bot 补发轮询间隔 |
WECOM_BOT_CARD_ENABLED |
否 | 是否启用 Bot 卡片回包 |
WECOM_BOT_CARD_MODE |
否 | 卡片模式:markdown / template_card |
WECOM_BOT_CARD_TITLE |
否 | 卡片标题 |
WECOM_BOT_CARD_SUBTITLE |
否 | 卡片副标题 |
WECOM_BOT_CARD_FOOTER |
否 | 卡片底部说明 |
WECOM_BOT_CARD_MAX_CONTENT_LENGTH |
否 | 卡片正文最大长度 |
WECOM_BOT_CARD_RESPONSE_URL_ENABLED |
否 | response_url 层卡片开关 |
WECOM_BOT_CARD_WEBHOOK_BOT_ENABLED |
否 | webhook_bot 层卡片开关 |
WECOM_<ACCOUNT>_BOT_* |
否 | 账户级 Bot 覆盖(如 WECOM_SALES_BOT_TOKEN) |
WECOM_<ACCOUNT>_BOT_PROXY |
否 | 账户级 Bot 媒体下载/回包代理 |
| 变量 | 说明 |
|---|---|
WECOM_ALLOW_FROM / WECOM_<ACCOUNT>_ALLOW_FROM |
发送者白名单 |
WECOM_ALLOW_FROM_REJECT_MESSAGE / WECOM_<ACCOUNT>_ALLOW_FROM_REJECT_MESSAGE |
未授权提示 |
WECOM_ADMIN_USERS |
管理员用户列表 |
WECOM_COMMANDS_ENABLED / WECOM_COMMANDS_ALLOWLIST / WECOM_COMMANDS_REJECT_MESSAGE |
命令白名单策略 |
WECOM_DM_POLICY / WECOM_DM_MODE / WECOM_DM_ALLOW_FROM / WECOM_DM_REJECT_MESSAGE |
私聊策略(支持 WECOM_<ACCOUNT>_DM_* 覆盖) |
WECOM_EVENTS_ENABLED / WECOM_EVENTS_ENTER_AGENT_WELCOME_ENABLED / WECOM_EVENTS_ENTER_AGENT_WELCOME_TEXT |
事件处理与 enter_agent 欢迎语(支持 WECOM_<ACCOUNT>_EVENTS_*) |
WECOM_GROUP_CHAT_ENABLED / WECOM_GROUP_CHAT_REQUIRE_MENTION / WECOM_GROUP_CHAT_MENTION_PATTERNS |
群触发策略 |
WECOM_DEBOUNCE_ENABLED / WECOM_DEBOUNCE_WINDOW_MS / WECOM_DEBOUNCE_MAX_BATCH |
文本防抖 |
WECOM_STREAMING_ENABLED / WECOM_STREAMING_MIN_CHARS / WECOM_STREAMING_MIN_INTERVAL_MS |
Agent 增量回包 |
WECOM_LATE_REPLY_WATCH_MS / WECOM_LATE_REPLY_POLL_MS |
异步补发窗口与轮询频率 |
WECOM_OBSERVABILITY_ENABLED / WECOM_OBSERVABILITY_PAYLOAD_META |
观测统计与载荷元信息日志开关 |
| 变量 | 说明 |
|---|---|
WECOM_VOICE_TRANSCRIBE_ENABLED |
启用本地语音转写回退 |
WECOM_VOICE_TRANSCRIBE_PROVIDER |
local-whisper-cli / local-whisper |
WECOM_VOICE_TRANSCRIBE_COMMAND |
转写命令 |
WECOM_VOICE_TRANSCRIBE_MODEL_PATH |
whisper-cli 模型路径 |
WECOM_VOICE_TRANSCRIBE_MODEL |
whisper 模型名 |
WECOM_VOICE_TRANSCRIBE_TIMEOUT_MS |
转写超时 |
WECOM_VOICE_TRANSCRIBE_MAX_BYTES |
音频大小上限 |
WECOM_VOICE_TRANSCRIBE_FFMPEG_ENABLED |
是否允许 ffmpeg 转码 |
WECOM_VOICE_TRANSCRIBE_TRANSCODE_TO_WAV |
是否优先转 WAV |
企业微信访问你的回调地址时,必须直接命中 OpenClaw 网关的 webhook 路由。
不能被这些中间层拦住:
- Gateway Auth / Token 鉴权
- 反向代理登录页 / SSO
- 前端 WebUI 路由
- 另一台静态站点或错误 upstream
| 场景 | 推荐做法 |
|---|---|
| 单域名 | 将 /wecom/*、legacy /webhooks/app*、/webhooks/wecom* 单独反代到 OpenClaw 网关端口 |
| 有 Gateway Auth / Zero Trust | 对上述 webhook 路径做认证豁免,不要求 Authorization/Cookie |
| 前端与网关共用域名 | 前端只接管 /ui、静态资源等路径,不要吞掉 /wecom/* |
| 最稳妥 | 单独给企微回调使用一个子域名,只代理到 OpenClaw |
| 探测 | 预期 |
|---|---|
curl -i http://127.0.0.1:8885/wecom/callback |
200 + wecom webhook ok |
curl -i http://127.0.0.1:8885/wecom/bot/callback |
200 + wecom bot webhook ok |
curl -i https://你的域名/wecom/callback |
与本机一致,不应返回 HTML、401/403 或跳转 |
curl -i https://你的域名/wecom/bot/callback |
与本机一致,不应返回 HTML、401/403 或跳转 |
| 现象 | 结论 | 处理 |
|---|---|---|
200 + wecom webhook ok / wecom bot webhook ok |
路由命中正常 | 继续做 URL 验证与企业微信后台配置 |
200 + HTML |
请求被前端/WebUI 接走 | 单独为 /wecom/* 配反代,不要落到前端 |
401/403 |
被 Gateway Auth / Zero Trust / 反代鉴权拦截 | 为 webhook 路径放行认证 |
301/302/307/308 |
被登录页、SSO 或前端路由重定向 | 取消 webhook 路径重定向,直接代理到网关 |
502/503/504 |
OpenClaw 网关端口不可达 | 先修网关存活与 upstream |
404 |
路径写错或插件路由没注册 | 核对 webhookPath、插件启用状态和 legacy alias |
server {
listen 443 ssl http2;
server_name wecom.example.com;
location /wecom/ {
proxy_pass http://127.0.0.1:8885;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /webhooks/app {
proxy_pass http://127.0.0.1:8885;
}
location /webhooks/wecom {
proxy_pass http://127.0.0.1:8885;
}
}ingress:
- hostname: wecom.example.com
service: http://127.0.0.1:8885
- service: http_status:404建议把企微回调放到单独子域名,不要和前端登录页共用同一套路由规则。
npm run wecom:selfcheck -- --all-accounts
npm run wecom:agent:selfcheck -- --all-accounts
npm run wecom:bot:selfcheck -- --all-accounts
npm run wecom:callback:matrix -- --agent-url https://你的域名/wecom/callback --bot-url https://你的域名/wecom/bot/callback现在自检会明确提示这些原因:
route-not-foundhtml-fallbackgateway-authredirect-authgateway-unreachable
如果你要把新路径和 legacy alias 一次跑完,直接用:
npm run wecom:callback:matrix -- \
--agent-url https://你的域名/wecom/callback \
--bot-url https://你的域名/wecom/bot/callback \
--agent-legacy-url https://你的域名/webhooks/app \
--bot-legacy-url https://你的域名/webhooks/wecom| 需求 | 推荐方式 |
|---|---|
| 手工发一条群通知 | openclaw message send --channel wecom --target webhook:<name> |
| 让 agent 处理后发到群 | openclaw agent --deliver --reply-channel wecom --reply-to webhook:<name> |
| 固定周期发摘要/巡检结果 | OpenClaw agents.defaults.heartbeat + target: "wecom" + to: "webhook:<name>" |
{
"channels": {
"wecom": {
"webhooks": {
"ops": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx",
"dev": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=yyy"
}
}
}
}多账号时,也可以挂到 channels.wecom.accounts.<id>.webhooks。
openclaw message send --channel wecom --target webhook:ops --message "服务已恢复正常"openclaw agent \
--message "整理今天的告警摘要" \
--deliver \
--reply-channel wecom \
--reply-to webhook:ops当前机器上的 OpenClaw 2026.3.2 支持把 heartbeat 直接投递到指定渠道和目标。
对 WeCom Webhook 的推荐写法是:
{
"channels": {
"wecom": {
"webhooks": {
"ops": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
}
}
},
"agents": {
"defaults": {
"heartbeat": {
"every": "30m",
"target": "wecom",
"to": "webhook:ops",
"prompt": "检查网关状态、最近告警和企业微信通道健康;如果一切正常,以三行内摘要输出。",
"ackMaxChars": 300
}
}
}
}多账号 webhook 场景可以再加:
{
"agents": {
"defaults": {
"heartbeat": {
"target": "wecom",
"to": "webhook:ops",
"accountId": "sales"
}
}
}
}说明:
target: "wecom"指定投递到 WeCom 渠道to: "webhook:ops"指定 WeCom 渠道里的命名 webhook 目标accountId只在多账号场景需要- 如果不设
target,heartbeat 默认运行但不会向外发送消息
openclaw system heartbeat last
openclaw config get agents.defaults.heartbeat
openclaw status --deep
openclaw logs --follow需要手工触发一次立即执行:
openclaw system event --mode now --text "立即执行下一轮运维心跳"建议固定以下三点,减少“偶发无回复/冲突”风险:
- 配置
plugins.allow显式白名单(至少包含openclaw-wechat) - 各渠道使用独立 webhook path,不复用
- 同一台机器尽量只运行一个 OpenClaw gateway 进程
详细说明见:docs/troubleshooting/coexistence.md
| 现象 | 先看什么 | 常见原因 | 处理建议 |
|---|---|---|---|
| 回调验证失败 | curl https://域名/wecom/callback |
URL 不通、Token/AESKey 不一致 | 先通公网,再核对配置 |
curl 到公网回调是 200,但企业微信后台仍提示 openapi回调地址请求不通过 |
企业微信后台校验 | 临时隧道域名、不受信任公网域名、企业侧域名策略或回调链路仍被中间层改写 | 优先换成稳定公网域名;不要把 trycloudflare.com 之类临时域名当正式 Agent 回调地址 |
curl /wecom/callback 返回 WebUI 页面 |
反向代理路由与回调路径 | 域名把 /wecom/callback 转发到了前端/静态站点 |
单独为 /wecom/* 配置反向代理到 OpenClaw 网关端口 |
curl https://域名/wecom/callback 返回 401/403 |
Gateway Auth / Zero Trust / 反代鉴权 | webhook 路径被要求登录或带 Token | 对 /wecom/*、/webhooks/app*、/webhooks/wecom* 做认证豁免 |
curl https://域名/wecom/callback 返回 301/302/307/308 |
登录跳转 / SSO / 前端路由 | webhook 被重定向到登录页或前端 | 让 webhook 路径直接反代到 OpenClaw 网关 |
| 能收到消息但不回复 | openclaw gateway status + openclaw logs --follow |
模型超时、会话排队、权限策略拦截 | 查看 dispatch/allowFrom/commands 日志 |
| 能收到消息但不回复(已确认本地日志正常) | 企业微信自建应用后台 -> 开发设置 | 未配置“可信 IP”,企业微信拒绝部分回调/发送链路 | 在应用里补充 OpenClaw 出网 IP 到可信 IP 列表(保存后重试) |
| Bot 图片识别失败 | wecom(bot): failed to fetch image url |
URL 失效、返回非图像流 | 已支持 octet-stream+解密兜底,先升级到最新版本 |
| 语音转写失败 | wecom: voice transcription failed |
本地命令或模型路径错误 | 检查 command、modelPath、ffmpeg |
| 启动出现账号体检告警 | wecom: account diagnosis ... |
多账号 Token/Agent/路径存在冲突风险 | 按日志 code 与账户列表调整配置,优先处理 warn 级别 |
wecom:selfcheck -- --all-accounts 提示 account '<id>' not found or incomplete |
账号配置结构 | 旧版本自检脚本没完全识别 agent 子块、legacy inline 账户,或账号字段确实缺失 |
升级到最新版本后重跑;再核对 channels.wecom.accounts.<id> 是否包含完整 Agent 凭据 |
| gettoken 失败 | 企业微信 API 返回码 | CorpId/Secret 错或网络受限 | 检查凭据/配置代理 |
openclaw gateway status
openclaw status --deep
openclaw logs --follow
npm run wecom:selfcheck -- --all-accounts
npm run wecom:agent:selfcheck -- --all-accounts
npm run wecom:bot:selfcheck -- --all-accounts| 命令 | 作用 |
|---|---|
npm test |
语法与单测 |
WECOM_E2E_ENABLE=1 npm run test:e2e:remote |
运行远程 E2E 测试(默认跳过;支持 WECOM_E2E_* 与兼容 E2E_WECOM_* 两套变量) |
WECOM_E2E_MATRIX_ENABLE=1 npm run test:e2e:matrix |
运行远程矩阵 E2E(签名验签/异常请求/stream refresh/去重链路) |
npm run test:e2e:prepare-browser |
远程浏览器沙箱就绪检查(可选自动安装 Chromium) |
npm run test:e2e:collect-pdf |
收集远端浏览器沙箱中的 PDF 产物到本地 |
npm run wecom:selfcheck -- --all-accounts |
配置+网络体检 |
npm run wecom:agent:selfcheck -- --account <id> |
Agent 单账号端到端链路体检(URL 验证 + 加密 POST) |
npm run wecom:agent:selfcheck -- --all-accounts |
Agent 多账号端到端链路体检(逐账号跑 URL 验证 + 加密 POST) |
npm run wecom:bot:selfcheck -- --account <id> |
Bot 端到端链路体检(URL 验证/签名/加密/stream-refresh,支持多账户) |
npm run wecom:callback:matrix -- --agent-url <公网Agent回调> --bot-url <公网Bot回调> |
公网回调矩阵体检(可附带 legacy alias URL) |
npm run wecom:remote:e2e -- --mode all --agent-url <公网Agent回调> --bot-url <公网Bot回调> |
远端矩阵验证(Agent+Bot) |
npm run wecom:remote:e2e -- --mode all --agent-url <公网Agent回调> --bot-url <公网Bot回调> --prepare-browser --collect-pdf |
远端矩阵验证(含浏览器沙箱检查与 PDF 回收) |
WECOM_E2E_BOT_URL=<...> WECOM_E2E_AGENT_URL=<...> npm run wecom:remote:e2e -- --mode all |
用环境变量驱动远端 E2E(兼容旧 E2E_WECOM_*) |
npm run wecom:e2e:scenario -- --scenario full-smoke --agent-url <公网Agent回调> --bot-url <公网Bot回调> |
场景化 E2E(预置 smoke/queue 场景) |
npm run wecom:e2e:scenario -- --scenario callback-matrix --agent-url <公网Agent回调> --bot-url <公网Bot回调> |
只做公网回调矩阵检查 |
npm run wecom:e2e:scenario -- --scenario compat-smoke --agent-url <新Agent回调> --agent-legacy-url <旧Agent回调> --bot-url <新Bot回调> --bot-legacy-url <旧Bot回调> |
兼容矩阵验证(新旧回调地址都跑一遍) |
npm run wecom:e2e:scenario -- --scenario matrix-smoke --bot-url <公网Bot回调> |
Bot 协议矩阵验证(验签/异常请求/stream-refresh/去重;需 WECOM_BOT_TOKEN/WECOM_BOT_ENCODING_AES_KEY) |
npm run wecom:e2e:compat -- --agent-url <新Agent回调> --agent-legacy-url <旧Agent回调> --bot-url <新Bot回调> --bot-legacy-url <旧Bot回调> |
兼容矩阵快捷命令(等价 --scenario compat-smoke) |
npm run wecom:e2e:full -- --agent-url <公网Agent回调> --bot-url <公网Bot回调> |
一键 full-smoke(默认带 --prepare-browser --collect-pdf) |
GitHub Actions -> CI -> Run workflow |
在仓库 CI 手动触发远程 E2E:设置 run_remote_e2e=true,可选 e2e_scenario(含 compat-smoke)与浏览器参数 |
npm run wecom:smoke |
升级后快速回归(Agent 主链路) |
npm run wecom:smoke -- --with-bot-e2e |
升级后快速回归(含 Bot E2E) |
openclaw gateway restart |
重启网关 |
- 更新
CHANGELOG.md与版本号 - 运行
npm test与wecom:selfcheck - 打 tag 并发布 GitHub Release
- (可选)发布 npm 包
通常是机器人创建成“标准模式”。请重建为 API 模式(JSON 回调)。
企业微信可能返回非标准 content-type 或加密媒体流。插件已增加类型识别与解密兜底;仍失败时请查看日志中的 header/下载错误。
优先检查企业微信自建应用后台是否配置了可信 IP。如果可信 IP 缺失,企业微信可能在发送/回调链路上做安全拦截,表现为“能收到但不回”。
建议:把 OpenClaw 网关实际出网 IP 加入该应用的可信 IP 列表,保存后重试。
理论上独立;实战中若复用 webhook 路径、多进程抢占、或 plugins.allow 未收紧,会出现干扰。按“并存建议”配置可大幅降低风险。
支持企业微信场景下的“微信插件入口”(个人微信扫码进入企业应用对话),不等同于“个人微信网页版协议”。
这是企业微信产品形态差异,不是插件故障。
在很多租户里,“微信插件入口”主要对应**自建应用(Agent 回调)**可见,Bot 模式(智能机器人 API)不会以可直接会话的联系人形态出现。
建议:
- 需要稳定私聊入口:优先用自建应用(Agent 模式)
- 需要群聊通知/群内对话:优先用 Webhook Bot / Bot 模式
- 需要两者兼顾:并行启用 Agent(入口)+ Bot(群能力)
- 运行
npm run wecom:bot:selfcheck -- --account <id>(或--all-accounts)可看到bot.entry.visibility提示,用于快速确认该行为属于产品形态差异而非插件故障
这是路由层问题,不是插件正常行为。GET /wecom/callback(无 echostr)应返回纯文本 wecom webhook ok。
若返回 WebUI,说明你的反向代理把该路径转发到了前端服务而不是 OpenClaw 网关。
建议按顺序排查:
- 本机验证:
curl http://127.0.0.1:8885/wecom/callback(应返回wecom webhook ok) - 公网验证:
curl -i https://你的域名/wecom/callback - 代理配置:为
/wecom/*单独反代到 OpenClaw 网关端口,不要落到 WebUI 路由
这说明“你的路由打通了”,但还不能证明企业微信后台会接受这条回调地址。
常见根因:
- 用了临时公网域名,例如
trycloudflare.com - 企业侧要求更稳定/更受信任的公网域名
- 你的回调链路虽然
curl是200,但企业微信实际校验时仍遇到了中间层改写
明确建议:
- 自建应用正式回调地址优先用你自己的稳定公网域名
- 不要把
trycloudflare.com这类临时隧道域名当正式 Agent 回调地址 - 继续确认该域名的
/wecom/callback没有鉴权、跳转、前端兜底和缓存层干扰 - 如果只是想快速群聊验证,Bot/Webhook 路径通常比自建应用回调更容易先跑通
先区分两种通道能力:
- 群机器人(Webhook Bot):可直接添加到企微群,天然适合群聊收发;但群聊通常仅
@机器人时才会回调。 - 自建应用(Agent 回调):插件支持处理
ChatId群消息;但是否能收到“普通群消息”取决于企业微信实际下发能力(很多租户里普通群只能加机器人,无法像成员一样加自建应用)。
如果你的场景是“普通群里稳定对话”,优先用 Webhook Bot 模式(注意通常仍需 @机器人 才触发)。
如果你确认企业微信会把群消息回调到自建应用(日志里有 chatId=...),再配置触发模式:
{
"channels": {
"wecom": {
"groupChat": {
"enabled": true,
"triggerMode": "direct"
}
}
}
}同时确认企业微信侧前提:
- 自建应用已开启“接收消息”并完成 URL 验证
- 应用可见范围包含该群成员
- 日志里能看到
chatId=...(若没有chatId,说明企业微信没有把群消息推送到该回调)
若你在企微侧只能给群添加“机器人”而不能添加“自建应用”,这不是插件配置问题,属于企微产品形态差异;建议走 Bot 模式承载群聊,自建应用用于私聊/应用会话/主动推送。
这是多账号隔离问题,不是“企微互相干扰”。
从当前版本开始:
- Agent 会话 key 已按账号隔离
wecom:selfcheck -- --all-accounts会识别accounts.<id>、agent子块、legacy inline 账户bindings.match.channel=wecom + accountId=<id>可以把不同账号稳定路由到不同 Agent
建议排查顺序:
- 跑
npm run wecom:selfcheck -- --all-accounts - 确认每个账号
config.account都是OK - 在
openclaw.json中为多账号配置bindings - 确认会话 key 形态符合预期:默认账号为
wecom:<userid>;非默认账号为wecom:<accountId>:<userid>
- 版本记录:
CHANGELOG.md - 渠道文档:
docs/channels/wecom.md - 问题排查:
docs/troubleshooting/coexistence.md - 许可证:MIT
欢迎提交 Issue / PR。