跳到主要内容

WeCom(企业微信)

将 Hermes 与 WeCom(腾讯的企业级消息平台)连接。该适配器使用 WeCom 的 AI Bot WebSocket 网关实现实时双向通信——无需公开端点或 Webhook。

先决条件

  • 一个 WeCom 组织账号
  • 在 WeCom 管理控制台中创建的 AI Bot
  • 从 Bot 的凭证页面获取的 Bot ID 和 Secret
  • Python 包:aiohttphttpx

设置

1. 创建 AI Bot

  1. 登录 WeCom 管理控制台
  2. 导航至 应用创建应用AI Bot
  3. 配置 Bot 名称和描述
  4. 从凭证页面复制 Bot IDSecret

2. 配置 Hermes

运行交互式设置:

hermes gateway setup

选择 WeCom,并输入您的 Bot ID 和 Secret。

或者在 ~/.hermes/.env 中设置环境变量:

WECOM_BOT_ID=your-bot-id
WECOM_SECRET=your-secret

# Optional: restrict access
WECOM_ALLOWED_USERS=user_id_1,user_id_2

# Optional: home channel for cron/notifications
WECOM_HOME_CHANNEL=chat_id

3. 启动网关

hermes gateway

功能特性

  • WebSocket 传输 —— 持久连接,无需公开端点
  • 私信与群组消息 —— 可配置访问策略
  • 按群组发送者白名单 —— 对每个群组中谁可以互动进行细粒度控制
  • 媒体支持 —— 支持图片、文件、语音、视频的上传与下载
  • AES 加密媒体 —— 自动解密传入的附件
  • 引用上下文 —— 保留回复的线程结构
  • Markdown 渲染 —— 支持富文本响应
  • 回复模式流式输出 —— 将响应与传入消息上下文相关联
  • 自动重连 —— 连接中断时采用指数退避重试

配置选项

config.yaml 中的 platforms.wecom.extra 下设置以下选项:

默认值描述
bot_idWeCom AI Bot ID(必需)
secretWeCom AI Bot Secret(必需)
websocket_urlwss://openws.work.weixin.qq.comWebSocket 网关 URL
dm_policyopen私信访问策略:openallowlistdisabledpairing
group_policyopen群组访问策略:openallowlistdisabled
allow_from[]允许私信的用户 ID 列表(当 dm_policy=allowlist 时)
group_allow_from[]允许的群组 ID 列表(当 group_policy=allowlist 时)
groups{}按群组配置(见下文)

访问策略

私信策略(DM Policy)

控制谁可以向 Bot 发送私信:

行为
open任何人都可以向 Bot 发送私信(默认)
allowlistallow_from 列表中的用户 ID 可以发送私信
disabled所有私信均被忽略
pairing配对模式(用于初始设置)
WECOM_DM_POLICY=allowlist

群组策略(Group Policy)

控制 Bot 在哪些群组中响应:

行为
openBot 在所有群组中响应(默认)
allowlistBot 仅在 group_allow_from 列表中的群组 ID 中响应
disabled所有群组消息均被忽略
WECOM_GROUP_POLICY=allowlist

按群组发送者白名单

为实现细粒度控制,您可以限制特定群组中哪些用户可以与 Bot 互动。该配置在 config.yaml 中完成:

platforms:
wecom:
enabled: true
extra:
bot_id: "your-bot-id"
secret: "your-secret"
group_policy: "allowlist"
group_allow_from:
- "group_id_1"
- "group_id_2"
groups:
group_id_1:
allow_from:
- "user_alice"
- "user_bob"
group_id_2:
allow_from:
- "user_charlie"
"*":
allow_from:
- "user_admin"

工作原理:

  1. group_policygroup_allow_from 控制某个群组是否被允许。
  2. 如果群组通过了顶层检查,则 groups.<group_id>.allow_from 列表(如果存在)会进一步限制该群组内哪些发送者可以与 Bot 互动。
  3. 通配符 "*" 条目可作为未显式列出群组的默认规则。
  4. 白名单条目支持 * 通配符以允许所有用户,且条目不区分大小写。
  5. 条目可选择使用 wecom:user:wecom:group: 前缀格式——前缀会自动剥离。

如果某个群组未配置 allow_from,则该群组中所有用户均被允许(前提是该群组本身通过了顶层策略检查)。

媒体支持

入站(接收)

适配器接收用户发送的媒体附件,并在本地缓存以供代理处理:

类型处理方式
图片下载并本地缓存。支持基于 URL 和 base64 编码的图片。
文件下载并缓存。文件名保留原始消息中的名称。
语音若可用,提取语音消息的文本转录。
混合消息WeCom 的混合类型消息(文本 + 图片)会被解析,所有组件均被提取。

引用消息: 被引用(回复)的消息中的媒体也会被提取,使代理能够了解用户正在回复的内容。

AES 加密媒体解密

WeCom 使用 AES-256-CBC 对部分入站媒体附件进行加密。该适配器会自动处理解密过程:

  • 当入站媒体项包含 aeskey 字段时,适配器会下载加密字节,并使用 AES-256-CBC 加密算法配合 PKCS#7 填充进行解密。
  • AES 密钥为 aeskey 字段的 base64 解码值(必须恰好为 32 字节)。
  • IV 由密钥的前 16 字节导出。
  • 此功能需要 cryptography Python 包(运行 pip install cryptography 安装)。

无需配置——当接收到加密媒体时,解密将自动透明完成。

出站(发送)

方法发送内容大小限制
sendMarkdown 文本消息4000 字符
send_image / send_image_file原生图片消息10 MB
send_document文件附件20 MB
send_voice语音消息(仅支持原生语音的 AMR 格式)2 MB
send_video视频消息10 MB

分块上传:文件通过三步协议(初始化 → 分块 → 完成)以 512 KB 为单位上传。适配器会自动处理此过程。

自动降级:当媒体超出原生类型大小限制但仍在绝对 20 MB 文件限制内时,将自动作为通用文件附件发送:

  • 图片 > 10 MB → 作为文件发送
  • 视频 > 10 MB → 作为文件发送
  • 语音 > 2 MB → 作为文件发送
  • 非 AMR 音频 → 作为文件发送(仅 WeCom 支持 AMR 格式的原生语音)

超过绝对 20 MB 限制的文件将被拒绝,并向聊天发送一条信息提示。

回复模式流式响应

当机器人通过 WeCom 回调收到消息时,适配器会记住入站请求 ID。如果在请求上下文仍有效时发送响应,适配器将使用 WeCom 的回复模式(aibot_respond_msg)并启用流式传输,将响应直接关联到入站消息。这在 WeCom 客户端中提供更自然的对话体验。

如果入站请求上下文已过期或不可用,适配器将回退至通过 aibot_send_msg 主动发送消息。

回复模式也适用于媒体:上传的媒体可作为对原始消息的回复发送。

连接与重连

适配器维护与 WeCom 网关的持久化 WebSocket 连接,地址为 wss://openws.work.weixin.qq.com

连接生命周期

  1. 连接:打开 WebSocket 连接,并发送包含 bot_id 和 secret 的 aibot_subscribe 认证帧。
  2. 心跳:每 30 秒发送一次应用层 ping 帧,以保持连接活跃。
  3. 监听:持续读取入站帧并分发消息回调。

重连行为

连接丢失后,适配器使用指数退避机制进行重连:

尝试次数延迟
第 1 次重试2 秒
第 2 次重试5 秒
第 3 次重试10 秒
第 4 次重试30 秒
第 5 次及以上重试60 秒

每次成功重连后,退避计数器重置为 0。断开连接时,所有待处理的请求未来对象均被标记为失败,防止调用者无限挂起。

去重

入站消息通过消息 ID 进行去重,窗口为 5 分钟,最大缓存条目数为 1000 条。这可防止在重连或网络波动期间重复处理消息。

所有环境变量

变量是否必需默认值描述
WECOM_BOT_IDWeCom AI Bot ID
WECOM_SECRETWeCom AI Bot Secret
WECOM_ALLOWED_USERS(空)用于网关级别白名单的逗号分隔用户 ID 列表
WECOM_HOME_CHANNEL用于定时任务/通知输出的聊天 ID
WECOM_WEBSOCKET_URLwss://openws.work.weixin.qq.comWebSocket 网关 URL
WECOM_DM_POLICYopen私聊访问策略
WECOM_GROUP_POLICYopen群组访问策略

故障排除

问题解决方案
WECOM_BOT_ID and WECOM_SECRET are required设置两个环境变量,或在设置向导中进行配置
WeCom startup failed: aiohttp not installed安装 aiohttp:pip install aiohttp
WeCom startup failed: httpx not installed安装 httpx:pip install httpx
invalid secret (errcode=40013)确认密钥与机器人的凭证匹配
Timed out waiting for subscribe acknowledgement检查与 openws.work.weixin.qq.com 的网络连接
机器人在群组中无响应检查 group_policy 设置,并确保群组 ID 在 group_allow_from 列表中
机器人忽略群组中的某些用户检查 groups 配置部分中各群组的 allow_from 列表
媒体解密失败安装 cryptographypip install cryptography
cryptography is required for WeCom media decryption入站媒体为 AES 加密。请安装:pip install cryptography
语音消息以文件形式发送WeCom 仅支持原生 AMR 格式的语音消息。其他格式将自动降级为文件发送。
File too large 错误WeCom 对所有文件上传有 20 MB 的绝对限制。请压缩或拆分文件。
图片以文件形式发送图片大小超过 10 MB 时,超出原生图片限制,将自动降级为文件附件。
Timeout sending message to WeComWebSocket 可能已断开。请检查日志中是否有重连消息。
WeCom websocket closed during authentication网络问题或凭证错误。请验证 bot_id 和 secret。