OpenClaw-Wechat 企业微信插件

March 15, 2026 · View on GitHub

中文 README | English README

OpenClaw-Wechat 是一个面向 OpenClaw 的企业微信渠道插件,支持两种接入方式:

  • Agent 模式:企业微信自建应用(XML 回调,经典模式)
  • Bot 模式:企业微信智能机器人 API 模式(JSON 回调,原生 stream)
  • Webhook 目标出站:将消息主动投递到企业微信群 Webhook 或命名 Webhook 目标

适用于“个人微信扫码进入企业微信应用对话”、“企业内员工问答助手”、“多账户多业务线消息分流”等场景。

目录

可靠投递更新(v2.2.0)

这版重点不在接入元信息,而是把 WeCom 回复链路补成“可感知、可补发、可诊断”的可靠投递。

这版新增了什么

项目结果
可靠投递状态/status 新增 24h 窗口 / 主动发送额度 / Pending Reply 摘要
Pending Reply最终回复投递失败后自动入队,支持定时重试和下次入站补发
Pending Reply 持久化可选落盘,gateway 重启后继续补发未送达的最终回复
配额感知统一区分 窗口过期 / 额度不足 / 传输失败 / 目标无效
推理展示策略delivery.reasoning 可控制 <think> 内容分离显示、合并到最终回复或隐藏
Selfcheck 摘要wecom:selfcheck / wecom:agent:selfcheck / wecom:bot:selfcheck 增加 reliable-delivery 摘要
群策略诊断/status 与 selfcheck 会显示当前群规则来源、准入模式以及白名单是否生效
最终回复格式delivery.replyFormat 支持 auto / text / markdown,会按链路选择纯文本或 markdown 能力
媒体指令模型最终回复支持 MEDIA: / FILE: 指令,自动回传图片/文件并隐藏指令行
Bot/Agent 收口Bot fallback 与 Agent 最终回复统一纳入可靠投递跟踪
长连接日志降噪正常的 connect / opened / subscribed 继续保持 debug,默认日志更安静

这版对接入有什么实际影响

  • 现在能直接看出当前会话是否仍在 24h 回复窗口内,以及是否存在待补发的最终回复。
  • Bot / Agent 不再只是超时兜底,而是会把失败结果分类并进入 Pending Reply 重试。
  • selfcheck 会明确告诉你可靠投递追踪是否打开、是否持久化,以及当前推理展示模式。
  • 群聊策略不再只能靠日志反推,/status 和 selfcheck 会直接说明当前命中的群规则来源与白名单是否真的在限制触发。
  • Bot 长连接默认日志仍然更安静,排障时再开 debug 看正常心跳和订阅细节。

当前推荐的接入顺序

现在 package / manifest / runtime channel meta 都会暴露同一套 quickstart metadata,便于 installer、quickstart、doctor 和后续集成入口读取同一份推荐模式、starter config 和 setup checklist。

  1. 先选一个主入口:
    • Bot 长连接:适合最快跑通对话
    • Agent:适合需要主动发送、菜单、自建应用能力
  2. 再决定私聊准入:
    • open:直接可聊
    • allowlist:仅显式白名单
    • pairing:首次私聊先审批
  3. 最后再加增强项:
    • bindings
    • dynamicAgent
    • wecom_doc

Quickstart 命令

推荐入口:

npx -y @dingxiang-me/openclaw-wecom-cli install

如果你更想留在仓库内执行同一套流程:

npm run wecom:quickstart -- --mode bot_long_connection
npm run wecom:doctor -- --json

如果你想走交互式向导:

npm run wecom:quickstart -- --wizard

如果你已经准备好了 WECOM_* / WECOM_BOT_* 环境变量,也可以使用兼容性的 env-backed 初始化路径:

export WECOM_BOT_LONG_CONNECTION_BOT_ID=your-bot-id
export WECOM_BOT_LONG_CONNECTION_SECRET=your-bot-secret
openclaw channels add --channel wecom --use-env

这条 channels add --use-env 路径不需要任何 OpenClaw core 补丁,但它只适合 env-backed 初始化。
日常文档、排障和安装说明都默认以 installer / quickstart / doctor 为主路径;如果你需要完整接入和迁移闭环,仍然优先用 npx -y @dingxiang-me/openclaw-wecom-cli install

常见用法:

# 默认推荐模式:Bot 长连接
npm run wecom:quickstart -- --json

# 交互式选择 mode / dm / 群策略,并决定是否直接写入配置
npm run wecom:quickstart -- --wizard

# 把推荐 selfcheck 也串起来跑;如仍有占位项,默认会先阻止执行
npm run wecom:quickstart -- --run-checks

# 即使还没填完占位项,也强制执行推荐检查
npm run wecom:quickstart -- --run-checks --force-checks

# 把修复用的 configPatch 和 .env 模板直接写到目录里
npm run wecom:quickstart -- --run-checks --repair-dir ./.wecom-repair

# 直接把生成的 repair configPatch 合并进目标 openclaw.json
npm run wecom:quickstart -- --run-checks --apply-repair

# 先预览将要修改的字段,再确认是否真的应用 repair patch
npm run wecom:quickstart -- --run-checks --confirm-repair

# 单独盘点当前配置里的 legacy / mixed-layout 问题,并生成迁移 patch
npm run wecom:migrate -- --json

# 一次性聚合安装状态、迁移状态、自检、长连接探针和回调矩阵
npm run wecom:doctor -- --json

# 跑本地黑盒 onboarding E2E:install -> doctor -> fix -> rerun
npm run test:e2e:local

# 检查 root 包、installer CLI、manifest 和 npm pack 产物是否一致
npm run test:release

# 生成 sales 账号的 Agent 回调模板
npm run wecom:quickstart -- --mode agent_callback --account sales --dm-mode allowlist

# 直接带一份群白名单模板(值班群/运营群)
npm run wecom:quickstart -- --mode hybrid --group-profile allowlist_template --group-chat-id wr-ops-room --group-allow ops_lead,oncall_user

# 直接合并写入 openclaw.json,并自动备份原文件
npm run wecom:quickstart -- --mode hybrid --write

--group-profile 可选值有:inheritmention_onlyopen_directallowlist_templatedeny
默认行为只打印 starter config 和检查清单;只有显式传 --write 才会写文件。 --wizard 会把当前 CLI 参数当作默认值,然后逐步提问,最后再确认是否写入 openclaw.json--run-checks 会按当前 mode 的推荐命令执行自检;若 starter config 里还有占位项,默认会阻止执行,除非显式传 --force-checks--apply-repair 会把 postcheck.repairArtifacts.configPatch 直接 merge 到 --config 指向的配置文件,并自动备份原文件。 --confirm-repair 会先打印将要修改的字段,再询问是否真正执行 --apply-repair;交互提示走 stderr,不会污染 --json 的机器输出。 npm run wecom:migrate -- --json 不再生成 starter config,只做当前安装 / 迁移状态盘点,适合排查 legacy_config / mixed_layout / stale_packagenpm run wecom:migrate -- --jsonnpm run wecom:doctor -- --json 现在还会给出 migrationSource,直接区分 official-wecom / sunnoy-wecom / legacy-openclaw-wechat / mixed-sourcenpm run wecom:doctor -- --json 会把 migration + selfcheck + agent/bot e2e + longconn probe + callback matrix 聚合成一份报告;可以加 --skip-network 先只看本地安装 / 迁移问题。 npm run wecom:doctor -- --fix --skip-network --json 会先应用当前可落盘的本地 fix patch(例如 migration patch、plugins.allow/entries),再用修正后的配置重跑 doctor。 npm run wecom:doctor -- --confirm-fix --skip-network --json 会先预览将要修改的字段,再确认是否真正写回。 npm run wecom:quickstart -- --json 现在也会带 sourcePlaybook,把当前来源推荐的检查顺序、占位项提示和默认 repair 策略一起返回。 npx -y @dingxiang-me/openclaw-wecom-cli install 会先尝试执行 openclaw plugins install @dingxiang-me/openclaw-wechat,再写入 starter config,并可选继续跑本地 doctor。 npm run test:e2e:local 会黑盒验证 install -> doctor -> fix -> rerun 这条本地闭环,不依赖真实企微网络。 npm run test:release 会校验 root 包、installer CLI、manifest、运行时版本常量和 npm pack --dry-run 产物,适合作为发版前门禁。 如果当前配置更像官方插件 / sunnoy / 旧版 OpenClaw-Wechat,安装器会在 --json 输出里直接给出 migration.guide、来源说明、legacy 字段路径和回滚命令。 如果你想人工确认是否附带执行 doctor --fix,可以加 --confirm-doctor-fix;要强制不附带 --fix,可加 --no-doctor-fix,自动确认则用 --yes。 安装器的 --json 现在还会直接输出 actions,把来源审阅、迁移 patch、回滚和重跑 doctor 这些步骤结构化暴露出来。 如果你没有显式传 --mode,安装器还会按来源和现有能力自动选择 bot_long_connection / agent_callback / hybrid,并在 sourceProfile 里说明为什么这么选。 sourceProfile 现在还会给出来源专属 checkOrderrepairDefaults。例如官方 / legacy 来源默认允许自动附带 doctor --fix,而 sunnoy / mixed-source 来源默认只给修复建议,不会直接附带 --fix。 仓库现在也自带两条 GitHub Actions 门禁:Onboarding E2E 跑本地安装闭环,Release Check 跑版本/打包一致性;tag 发布会走独立 release workflow,顺序发布插件包和 installer CLI。

--json 输出会额外给出:

  • placeholders:还有哪些模板占位项没替换
  • setupChecklist:下一步应该执行的管理台配置和自检命令
  • actions:可被 CLI / UI 直接消费的结构化 setup flow
  • installState / migrationState:当前是 fresh、legacy_config、stale_package、mixed_layout 还是 ready
  • migrationSource / migrationSourceSummary:当前更接近官方插件、sunnoy 配置、legacy-openclaw-wechat,还是 mixed-source
  • fix:doctor --fix 是否已提示、确认、落盘,以及真实 changedPaths
  • sourcePlaybook:quickstart 基于当前来源生成的推荐检查顺序、占位提示和 repair 默认值
  • sourceProfile.checkOrder / sourceProfile.repairDefaults:当前来源推荐的检查顺序,以及 installer 默认采用的修复策略
  • warnings:当前 mode / group profile 下仍需确认的风险点
  • postcheck:推荐 selfcheck 的执行结果、阻塞原因或汇总状态
  • postcheck.remediation:把失败检查翻译成可执行的修复建议
  • postcheck.repairArtifacts:自动生成最小 configPatch.env 模板,便于直接修复当前检查暴露的问题
  • postcheck.repairPlan:按项列出 repair patch 的配置变更、env 变更和会写出的文件
  • migration.configPatch / migration.envTemplate:当前 legacy 配置可直接迁移到的新布局建议

如果再加 --repair-dir <path>,quickstart 还会把这些修复产物直接落盘成:

  • wecom.config-patch.json
  • wecom.account-patch.json
  • wecom.env.template
  • README.txt

如果加的是 --apply-repair,则会在输出中额外看到 repairApply,说明 repair patch 是否已实际写入目标配置。 如果加的是 --confirm-repairrepairApply 里还会带 prompted/confirmed,方便区分“用户拒绝”与“自动执行”;真正写入的字段会出现在 repairApply.changedPaths

5 分钟极速上手

适合“先跑起来再细调”的场景。

Step 1. 安装插件

最快入口:

npx -y @dingxiang-me/openclaw-wecom-cli install

它会复用仓库内的 quickstart / migrate / doctor 能力,把“安装插件 + 写 starter config + 跑本地体检”串成一次执行。

如果你只想单独安装插件包:

openclaw plugins install @dingxiang-me/openclaw-wechat

最低建议版本:2.3.0。如果 openclaw.json 里的 plugins.installs.openclaw-wechat 仍显示 1.7.x,请先升级或重装;旧包不会正确注册 wecom channel 元数据,也不包含当前这套接入、迁移与可靠投递能力。

如果你是在本地开发或要直接跑仓库源码,再用下面这套:

git clone https://github.com/dingxiang-me/OpenClaw-Wechat.git
cd OpenClaw-Wechat
npm install

Step 2. 在 OpenClaw 里启用插件

如果你是通过 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
      }
    }
  }
}

Step 3. 选择一种模式配置

模式回调路径企业微信侧类型最少需要的配置
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 加入白名单。否则可能出现“能收到消息但不回复”。

如果你希望私聊先审批,再开放会话,可以直接加:

{
  "channels": {
    "wecom": {
      "dm": {
        "mode": "pairing"
      }
    }
  }
}

Step 4. 重启并自检

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

现在自检输出会先给出两行摘要:

  • readiness: 当前是否能收、能回、能发
  • routing: 当前是否启用 bindingsdynamicAgent

Step 5. 发一条消息验证

验证项预期结果
文本消息机器人返回文本
图片消息(Bot)不再提示“图片接收失败”,可识别图像内容
openclaw gateway statusRPC 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/pairing/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)
回调数据格式XMLJSON
企业微信创建方式应用管理 -> 自建应用智能机器人 -> 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-cliwhisper
ffmpeg(推荐)AMR 等格式转码时需要

安装与加载

方式 A:通过 OpenClaw 安装(推荐)

openclaw plugins install @dingxiang-me/openclaw-wechat

安装后插件会进入 ~/.openclaw/extensions/openclaw-wechat/。这个目录主要用于 OpenClaw 运行时发现插件,通常不建议直接手改其中的 package.jsonpackage-lock.jsonopenclaw.plugin.json

方式 B:本地路径加载(开发模式)

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.*bindingsenv.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.enabledplugins.allowplugins.entries.openclaw-wechat
企业微信业务配置channels.wecom.*
多账号配置channels.wecom.accounts.<id>.*
文档工具默认账号channels.wecom.defaultAccount
账号到 Agent 路由OpenClaw 根配置 bindings
敏感信息优先 env.vars.* 或系统环境变量;其次写入 openclaw.json

Control UI、文件、环境变量怎么分工

方式适合什么
Control UI日常调整常规字段:corpIdcallbackTokenaccounts.*tools.doc
openclaw.json结构化配置、版本管理、多人协作、bindings
env.vars / 系统环境变量Secret、代理、不同环境下的覆盖项

快速开始

1) 企业微信侧准备

Agent 模式(自建应用)

  1. 创建自建应用,拿到 AgentIdSecret
  2. 在“我的企业”拿到 CorpId
  3. 开启“接收消息”,配置:
    • URL: https://你的域名/wecom/callback
    • Token: 自定义随机字符串
    • EncodingAESKey: 企业微信生成

Bot 模式(智能机器人)

  1. 创建智能机器人时选择 API 模式
  2. 配置回调 URL:https://你的域名/wecom/bot/callback
  3. 获取并保存 tokenencodingAesKey

2) OpenClaw 最小配置示例

Agent 最小可用

{
  "channels": {
    "wecom": {
      "enabled": true,
      "corpId": "wwxxxx",
      "corpSecret": "xxxx",
      "agentId": 1000004,
      "callbackToken": "xxxx",
      "callbackAesKey": "xxxx",
      "webhookPath": "/wecom/callback"
    }
  }
}

Bot 最小可用(Bot-only)

{
  "channels": {
    "wecom": {
      "enabled": true,
      "bot": {
        "enabled": true,
        "token": "xxxx",
        "encodingAesKey": "xxxx",
        "webhookPath": "/wecom/bot/callback"
      }
    }
  }
}

Bot 长连接最小可用(无需公网 Bot 回调)

{
  "channels": {
    "wecom": {
      "enabled": true,
      "bot": {
        "enabled": true,
        "longConnection": {
          "enabled": true,
          "botId": "your-bot-id",
          "secret": "your-bot-secret"
        }
      }
    }
  }
}

3) 启动与验证

openclaw gateway restart
openclaw gateway status
openclaw plugins list
npm run wecom:selfcheck -- --all-accounts
npm run wecom:bot:selfcheck -- --account default

wecom:selfcheck 帮助:

node ./scripts/wecom-selfcheck.mjs --help

wecom:bot:selfcheck 帮助:

node ./scripts/wecom-bot-selfcheck.mjs --help

文档工具(WeCom Doc)

插件现在内置了 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删除文档或收集表docIdformId
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 在执行时按下面顺序选择账号:

  1. 工具参数里的 accountId
  2. 当前 agent 绑定账号
  3. channels.wecom.defaultAccount
  4. 第一个启用了文档工具的可用账号

创建后自动授权

默认开启:如果 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

配置参考

主配置键(channels.wecom

类型默认说明
enabledbooleantrue是否启用 WeCom 渠道
corpIdstring-企业 ID(Agent 模式)
corpSecretstring-应用 Secret(敏感)
agentIdnumber/string-应用 AgentId
callbackTokenstring-回调 Token(敏感)
callbackAesKeystring-回调 AES Key(敏感)
webhookPathstring/wecom/callbackAgent 回调路径(非 default 账户未配置时自动生成 /wecom/<accountId>/callback
agentobject-兼容旧配置:agent.corpId/corpSecret/agentId(与顶层 Agent 字段等价)
outboundProxystring-WeCom 出站代理
apiBaseUrlstringhttps://qyapi.weixin.qq.com可选:覆盖默认 WeCom API Base URL
defaultAccountstring-多账号下的默认账号 ID(文档工具等优先使用)
tools.docbooleantrue是否启用 wecom_doc 文档工具
webhooksobject-命名 Webhook 目标映射(如 { "ops": "https://...key=xxx" }
accountsobject-多账户配置(支持 accounts.<id>.bot 独立 Bot 配置)

兼容说明:支持旧字段与旧结构迁移:nametoken / encodingAesKeyagent.*dynamicAgents.*dm.createAgentOnFirstMessagedm.allowFromworkspaceTemplatecommandAllowlist/commandBlockMessagecommands.blockMessage、inline 账户写法 channels.wecom.<accountId>,以及官方 / sunnoy 风格的 botIdsecretnetwork.egressProxyUrlnetwork.apiBaseUrl。新配置建议优先使用 accounts.<id>callbackToken/callbackAesKeybot.longConnection.*outboundProxy/apiBaseUrlcommands.*dynamicAgent.*

提示:accounts.<id> 现在支持 Bot-only 账号(仅配置 bot.*),不再强制要求 corpId/corpSecret/agentId。 兼容提示:当使用默认新路径时会自动附加 legacy alias,便于旧回调地址平滑迁移:Agent 默认路径会附加 /webhooks/app(多账号为 /webhooks/app/<id>),Bot 默认路径会附加 /webhooks/wecom(多账号为 /webhooks/wecom/<id>)。若 alias 与另一类路由冲突会自动跳过并告警。

Bot 配置(channels.wecom.bot

类型默认说明
enabledbooleanfalse启用 Bot 模式
tokenstring-Bot 回调 Token(敏感)
encodingAesKeystring-Bot 回调 AESKey(43 位,敏感)
webhookPathstring/wecom/bot/callbackBot 回调路径(非 default 账户未配置时自动生成 /wecom/<accountId>/bot/callback
placeholderTextstring消息已收到...stream 初始占位文案(可设为空字符串)
streamExpireMsinteger600000stream 状态保留时间(30s~1h)
replyTimeoutMsinteger90000Bot 等待模型回包超时(15s~10m)
lateReplyWatchMsinteger180000Bot 超时后异步补发观察窗口(30s~10m)
lateReplyPollMsinteger2000Bot 异步补发轮询间隔(500ms~10s)
longConnectionobject-企业微信智能机器人长连接(WebSocket)配置
cardobject见下方Bot 卡片回包策略(response_url / webhook_bot

重要限制:企业微信官方 Bot 在群聊里通常仅对 @机器人 消息触发回调。
因此 Bot 模式下即使配置 groupChat.triggerMode=direct/keyword,也会按 mention 处理(插件会输出告警)。

Bot 长连接配置(channels.wecom.bot.longConnection

类型默认说明
enabledbooleanfalse启用企业微信智能机器人长连接
botIdstring-企业微信智能机器人 BotID
secretstring-企业微信智能机器人 Secret(敏感)
urlstringwss://openws.work.weixin.qq.com官方长连接地址
pingIntervalMsinteger30000心跳 ping 间隔
reconnectDelayMsinteger5000首次重连延迟
maxReconnectDelayMsinteger60000指数退避最大重连延迟

说明:

  • 长连接模式下不需要暴露公网 Bot 回调地址。
  • 插件会在网关启动后主动连接 wss://openws.work.weixin.qq.com,并自动发送 aibot_subscribe
  • 入站消息与事件分别使用 aibot_msg_callback / aibot_event_callback,统一接入现有 Bot 处理链路。
  • 模型 block 输出会直接通过长连接发送 aibot_respond_msg,不是被动等待 stream-refresh 拉取。

Bot 卡片配置(channels.wecom.bot.card

类型默认说明
enabledbooleanfalse启用卡片回包
modestringmarkdownmarkdown(兼容优先)或 template_card
titlestringOpenClaw-Wechat卡片标题
subtitlestring-卡片副标题
footerstring-卡片底部说明
maxContentLengthinteger1400卡片正文最大长度(自动截断)
responseUrlEnabledbooleantrue是否在 response_url 层发送卡片
webhookBotEnabledbooleantrue是否在 webhook_bot 层发送卡片

多账户 Bot 覆盖配置(channels.wecom.accounts.<id>.bot

当你启用了 accounts 多账户时,可以为每个账户单独配置 Bot 回调密钥、路径、超时和代理;若未配置,则回退到 channels.wecom.bot

类型默认说明
enabledbooleanfalse是否启用该账户 Bot
token / callbackTokenstring-该账户 Bot 回调 Token(兼容旧字段)
encodingAesKey / callbackAesKeystring-该账户 Bot 回调 AESKey(兼容旧字段)
webhookPathstring/wecom/bot/callback该账户 Bot 回调路径
placeholderTextstring消息已收到...stream 初始占位文案
streamExpireMsinteger600000stream 状态保留时间
replyTimeoutMsinteger90000Bot 等待模型回包超时
lateReplyWatchMsinteger180000超时后异步补发观察窗口
lateReplyPollMsinteger2000异步补发轮询间隔
longConnectionobject-该账户专用长连接配置(覆盖全局 bot.longConnection
cardobject-该账户专用卡片回包配置(覆盖全局 bot.card

兼容提示:如果你是从官方插件或 sunnoy 配置直接迁移,也可以先保留 channels.wecom.botId/secretaccounts.<id>.botId/secret,以及 network.egressProxyUrl/apiBaseUrl;插件会在运行时兼容读取,npm run wecom:migrate -- --json 会给出归一化 patch。

多账户文档工具覆盖(channels.wecom.accounts.<id>.tools

类型默认说明
docbooleantrue是否启用该账户的 wecom_doc 工具
outboundProxy / proxyUrl / proxystring-该账户 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
群聊准入策略groupPolicy + groupChat.policy + groups.<chatId>.policy显式控制 open / allowlist / deny;支持账户级覆盖与按群覆盖
群聊成员授权groupAllowFrom + groups.<chatId>.allowFromallowlist 搭配使用,控制哪些群成员可以触发机器人;支持账户级覆盖与按群覆盖
动态路由dynamicAgent.*(兼容 dynamicAgents.*dm.createAgentOnFirstMessage动态 Agent + workspace bootstrap 播种

吞吐与稳定性

模块配置键说明
文本防抖debounce.enabled/windowMs/maxBatch合并短时间多条文本
Agent 增量回包streaming.enabled/minChars/minIntervalMs多消息模拟流式
异步补发WECOM_LATE_REPLY_WATCH_MS/POLL_MSdispatch 超时后补发最终回复
Pending Reply 持久化delivery.pendingReply.persist/storeFile重启后恢复未送达最终回复;未指定 storeFile 时自动写入 OpenClaw state 目录
推理展示delivery.reasoning.mode/title/maxChars控制 <think> / reasoning 分离显示、附加到最终回复,或完全隐藏
最终回复格式delivery.replyFormatauto / text / markdown;优先在支持的 WeCom 链路上保留 markdown,其余链路自动回退纯文本
观测统计observability.enabled/logPayloadMeta记录入站/回包/错误并在 /status 展示

语音转写(本地)

默认说明
voiceTranscription.enabledtrue开启回退转写
providerlocal-whisper-clilocal-whisper-cli / local-whisper
command自动探测本地命令路径
modelPath-whisper-cli 模型路径
modelbasewhisper 模型名
timeoutMs120000单次转写超时
maxBytes10485760最大音频大小
ffmpegEnabledtrue不兼容格式自动转码
transcodeToWavtrue优先转为 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 bindings 做账号级 Agent 路由

OpenClaw-Wechat 不自己实现第二套路由规则;账号到 Agent 的稳定绑定,直接走 OpenClaw 核心 bindings。插件会把 channel=wecomaccountId=<id> 传给核心路由层。

示例:

{
  "bindings": [
    {
      "match": {
        "channel": "wecom",
        "accountId": "sales"
      },
      "agentId": "sales"
    },
    {
      "match": {
        "channel": "wecom",
        "accountId": "support"
      },
      "agentId": "support"
    }
  ]
}

这套绑定优先级高于插件里的动态账号猜测,适合多账号、多业务线、同一 OpenClaw 上挂多个 WeCom 入口的场景。

消息能力矩阵

Agent 模式

类型入站出站备注
文本自动分段
图片入站可识别,出站可发送
语音入站支持本地转写回退;出站支持 AMR/SILK
视频下载并可回包
文件下载并可回包
链接提取标题/描述/URL

Bot 模式

类型入站出站备注
文本原生 stream
图片response_url mixed + webhook fallback
语音以文本结果回传
文件Bot 文件入站下载;出站可按 file 回传
mixed(图文)聚合后回文本
链接/位置转换为文本上下文

命令与会话策略

命令

命令说明
/help查看帮助
/status查看运行状态
/clear清理会话(兼容映射到 /reset
/new新建会话(兼容映射到 /reset
/reset重置会话
/compact压缩会话(由上层运行时支持)

会话策略

  • 默认账号一用户一会话:wecom:<userid>
  • 非默认账号一用户一会话:wecom:<accountId>:<userid>
  • 群聊可配置“仅 @ 才触发”,避免误触发

出站目标格式

  • userwecom:alice / user:alice
  • group(chat)group:wrxxxx / chat:wcxxxx(自动走 appchat/send
  • partyparty:2 / dept:2
  • tagtag:ops
  • webhookwebhook:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxwebhook:key:xxx
  • webhook(命名)webhook:ops(从 channels.wecom.webhooks.opsaccounts.<id>.webhooks.ops 解析)

环境变量速查

核心与回调

变量必填说明
WECOM_CORP_IDAgent 必填企业 ID
WECOM_CORP_SECRETAgent 必填应用 Secret
WECOM_AGENT_IDAgent 必填AgentId
WECOM_CALLBACK_TOKENAgent 必填回调 Token
WECOM_CALLBACK_AES_KEYAgent 必填回调 AESKey
WECOM_WEBHOOK_PATHAgent 回调路径(默认 /wecom/callback
WECOM_WEBHOOK_TARGETS命名 Webhook 目标映射(name=url,多个用 ,/; 分隔)

Bot

变量必填说明
WECOM_BOT_ENABLED是否启用 Bot 模式
WECOM_BOT_TOKENBot 必填Bot Token
WECOM_BOT_ENCODING_AES_KEYBot 必填Bot EncodingAESKey
WECOM_BOT_WEBHOOK_PATHBot 回调路径
WECOM_BOT_PLACEHOLDER_TEXTstream 占位文案
WECOM_BOT_STREAM_EXPIRE_MSstream 保留时长
WECOM_BOT_REPLY_TIMEOUT_MSBot 等待模型回包超时
WECOM_BOT_LATE_REPLY_WATCH_MSBot 超时后补发观察窗口
WECOM_BOT_LATE_REPLY_POLL_MSBot 补发轮询间隔
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_ENABLEDresponse_url 层卡片开关
WECOM_BOT_CARD_WEBHOOK_BOT_ENABLEDwebhook_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_MSAgent 增量回包
WECOM_LATE_REPLY_WATCH_MS / WECOM_LATE_REPLY_POLL_MS异步补发窗口与轮询频率
WECOM_OBSERVABILITY_ENABLED / WECOM_OBSERVABILITY_PAYLOAD_META观测统计与载荷元信息日志开关

语音回退转写

变量说明
WECOM_VOICE_TRANSCRIBE_ENABLED启用本地语音转写回退
WECOM_VOICE_TRANSCRIBE_PROVIDERlocal-whisper-cli / local-whisper
WECOM_VOICE_TRANSCRIBE_COMMAND转写命令
WECOM_VOICE_TRANSCRIBE_MODEL_PATHwhisper-cli 模型路径
WECOM_VOICE_TRANSCRIBE_MODELwhisper 模型名
WECOM_VOICE_TRANSCRIBE_TIMEOUT_MS转写超时
WECOM_VOICE_TRANSCRIBE_MAX_BYTES音频大小上限
WECOM_VOICE_TRANSCRIBE_FFMPEG_ENABLED是否允许 ffmpeg 转码
WECOM_VOICE_TRANSCRIBE_TRANSCODE_TO_WAV是否优先转 WAV

公网回调与 Gateway Auth

目标

企业微信访问你的回调地址时,必须直接命中 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/callback200 + wecom webhook ok
curl -i http://127.0.0.1:8885/wecom/bot/callback200 + 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/504OpenClaw 网关端口不可达先修网关存活与 upstream
404路径写错或插件路由没注册核对 webhookPath、插件启用状态和 legacy alias

反代示例(Nginx)

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;
  }
}

Cloudflare Tunnel 示例

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-found
  • html-fallback
  • gateway-auth
  • redirect-auth
  • gateway-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

Webhook 与 Heartbeat 运维

适用场景

需求推荐方式
手工发一条群通知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>"

先配置命名 Webhook

{
  "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 "服务已恢复正常"

让 Agent 结果投递到群

openclaw agent \
  --message "整理今天的告警摘要" \
  --deliver \
  --reply-channel wecom \
  --reply-to webhook:ops

用 Heartbeat 定时投递到群

当前机器上的 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 "立即执行下一轮运维心跳"

与其他渠道并存建议

建议固定以下三点,减少“偶发无回复/冲突”风险:

  1. 配置 plugins.allow 显式白名单(至少包含 openclaw-wechat
  2. 各渠道使用独立 webhook path,不复用
  3. 同一台机器尽量只运行一个 OpenClaw gateway 进程

详细说明见:docs/troubleshooting/coexistence.md

故障排查

快速定位表

现象先看什么常见原因处理建议
回调验证失败curl https://域名/wecom/callbackURL 不通、Token/AESKey 不一致先通公网,再核对配置
curl 到公网回调是 200,但企业微信后台仍提示 openapi回调地址请求不通过企业微信后台校验临时隧道域名、不受信任公网域名、企业侧域名策略或回调链路仍被中间层改写优先换成稳定公网域名;不要把 trycloudflare.com 之类临时域名当正式 Agent 回调地址
curl /wecom/callback 返回 WebUI 页面反向代理路由与回调路径域名把 /wecom/callback 转发到了前端/静态站点单独为 /wecom/* 配置反向代理到 OpenClaw 网关端口
curl https://域名/wecom/callback 返回 401/403Gateway 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 urlURL 失效、返回非图像流已支持 octet-stream+解密兜底,先升级到最新版本
语音转写失败wecom: voice transcription failed本地命令或模型路径错误检查 commandmodelPathffmpeg
启动出现账号体检告警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-accountsAgent 多账号端到端链路体检(逐账号跑 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重启网关

发版建议流程

  1. 更新 CHANGELOG.md 与版本号
  2. 运行 npm testwecom:selfcheck
  3. 打 tag 并发布 GitHub Release
  4. (可选)发布 npm 包

FAQ

Q1:Bot 模式回调一直失败?

通常是机器人创建成“标准模式”。请重建为 API 模式(JSON 回调)。

Q2:为什么图片偶发识别失败?

企业微信可能返回非标准 content-type 或加密媒体流。插件已增加类型识别与解密兜底;仍失败时请查看日志中的 header/下载错误。

Q3:能收消息但一直不回复,日志看起来也正常?

优先检查企业微信自建应用后台是否配置了可信 IP。如果可信 IP 缺失,企业微信可能在发送/回调链路上做安全拦截,表现为“能收到但不回”。

建议:把 OpenClaw 网关实际出网 IP 加入该应用的可信 IP 列表,保存后重试。

Q4:Telegram 和 WeCom 会互相影响吗?

理论上独立;实战中若复用 webhook 路径、多进程抢占、或 plugins.allow 未收紧,会出现干扰。按“并存建议”配置可大幅降低风险。

Q5:支持个人微信吗?

支持企业微信场景下的“微信插件入口”(个人微信扫码进入企业应用对话),不等同于“个人微信网页版协议”。

Q4.1:为什么 Bot 模式在“微信插件入口”里看不到机器人联系人?

这是企业微信产品形态差异,不是插件故障。
在很多租户里,“微信插件入口”主要对应**自建应用(Agent 回调)**可见,Bot 模式(智能机器人 API)不会以可直接会话的联系人形态出现。

建议:

  1. 需要稳定私聊入口:优先用自建应用(Agent 模式)
  2. 需要群聊通知/群内对话:优先用 Webhook Bot / Bot 模式
  3. 需要两者兼顾:并行启用 Agent(入口)+ Bot(群能力)
  4. 运行 npm run wecom:bot:selfcheck -- --account <id>(或 --all-accounts)可看到 bot.entry.visibility 提示,用于快速确认该行为属于产品形态差异而非插件故障

Q5:为什么 curl https://域名/wecom/callback 返回的是 WebUI 页面?

这是路由层问题,不是插件正常行为。GET /wecom/callback(无 echostr)应返回纯文本 wecom webhook ok
若返回 WebUI,说明你的反向代理把该路径转发到了前端服务而不是 OpenClaw 网关。

建议按顺序排查:

  1. 本机验证:curl http://127.0.0.1:8885/wecom/callback(应返回 wecom webhook ok
  2. 公网验证:curl -i https://你的域名/wecom/callback
  3. 代理配置:为 /wecom/* 单独反代到 OpenClaw 网关端口,不要落到 WebUI 路由

Q5.1:为什么本机和公网 curl 都是 200 wecom webhook ok,企业微信后台仍提示 openapi回调地址请求不通过

这说明“你的路由打通了”,但还不能证明企业微信后台会接受这条回调地址

常见根因:

  1. 用了临时公网域名,例如 trycloudflare.com
  2. 企业侧要求更稳定/更受信任的公网域名
  3. 你的回调链路虽然 curl200,但企业微信实际校验时仍遇到了中间层改写

明确建议:

  1. 自建应用正式回调地址优先用你自己的稳定公网域名
  2. 不要把 trycloudflare.com 这类临时隧道域名当正式 Agent 回调地址
  3. 继续确认该域名的 /wecom/callback 没有鉴权、跳转、前端兜底和缓存层干扰
  4. 如果只是想快速群聊验证,Bot/Webhook 路径通常比自建应用回调更容易先跑通

Q6:自建应用群聊怎么开?为什么群里不 @ 就不触发?

先区分两种通道能力:

  1. 群机器人(Webhook Bot):可直接添加到企微群,天然适合群聊收发;但群聊通常仅 @机器人 时才会回调。
  2. 自建应用(Agent 回调):插件支持处理 ChatId 群消息;但是否能收到“普通群消息”取决于企业微信实际下发能力(很多租户里普通群只能加机器人,无法像成员一样加自建应用)。

如果你的场景是“普通群里稳定对话”,优先用 Webhook Bot 模式(注意通常仍需 @机器人 才触发)。
如果你确认企业微信会把群消息回调到自建应用(日志里有 chatId=...),再配置触发模式:

{
  "channels": {
    "wecom": {
      "groupPolicy": "open",
      "groupChat": {
        "enabled": true,
        "triggerMode": "direct"
      }
    }
  }
}

如果还要限制“只有指定群成员能触发”,可以再加一层群聊成员授权:

{
  "channels": {
    "wecom": {
      "groupPolicy": "allowlist",
      "groupAllowFrom": ["alice", "bob"],
      "groups": {
        "wr9N1x...": {
          "policy": "allowlist",
          "allowFrom": ["ops_lead"],
          "rejectMessage": "当前群仅限值班同学触发。"
        }
      }
    }
  }
}

如果你要“一刀切关闭群聊处理”,直接用:

{
  "channels": {
    "wecom": {
      "groupPolicy": "deny"
    }
  }
}

同时确认企业微信侧前提:

  1. 自建应用已开启“接收消息”并完成 URL 验证
  2. 应用可见范围包含该群成员
  3. 日志里能看到 chatId=...(若没有 chatId,说明企业微信没有把群消息推送到该回调)

若你在企微侧只能给群添加“机器人”而不能添加“自建应用”,这不是插件配置问题,属于企微产品形态差异;建议走 Bot 模式承载群聊,自建应用用于私聊/应用会话/主动推送。

Q7:多账号创建了两个 agent,但只有一个回复,或者会话串了?

这是多账号隔离问题,不是“企微互相干扰”。

从当前版本开始:

  1. Agent 会话 key 已按账号隔离
  2. wecom:selfcheck -- --all-accounts 会识别 accounts.<id>agent 子块、legacy inline 账户
  3. bindings.match.channel=wecom + accountId=<id> 可以把不同账号稳定路由到不同 Agent

建议排查顺序:

  1. npm run wecom:selfcheck -- --all-accounts
  2. 确认每个账号 config.account 都是 OK
  3. openclaw.json 中为多账号配置 bindings
  4. 确认会话 key 形态符合预期:默认账号为 wecom:<userid>;非默认账号为 wecom:<accountId>:<userid>

版本与贡献

欢迎提交 Issue / PR。

Star History

Star History Chart