Skip to content

dingxiang-me/OpenClaw-Wechat

Repository files navigation

OpenClaw-Wechat 企业微信插件

中文 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 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/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)
回调数据格式 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-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

类型 默认 说明
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 出站代理
apiBaseUrl string https://qyapi.weixin.qq.com 可选:覆盖默认 WeCom API Base URL
defaultAccount string - 多账号下的默认账号 ID(文档工具等优先使用)
tools.doc boolean true 是否启用 wecom_doc 文档工具
webhooks object - 命名 Webhook 目标映射(如 { "ops": "https://...key=xxx" }
accounts object - 多账户配置(支持 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

类型 默认 说明
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 处理(插件会输出告警)。

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

类型 默认 说明
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 拉取。

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

类型 默认 说明
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 层发送卡片

多账户 Bot 覆盖配置(channels.wecom.accounts.<id>.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

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

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

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

吞吐与稳定性

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

Bot

变量 必填 说明
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

公网回调与 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/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

反代示例(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/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 本地命令或模型路径错误 检查 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-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 重启网关

发版建议流程

  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

About

🔥🔥🔥 首个把OpenClaw接入企业微信的插件 / 个人微信互通 / BOT流式输出 长连接模式 / 支持群聊 / 白名单控制 / 文档能力 / 全中文可视化配置

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors