跳到主要内容

WeCom (Enterprise WeChat)

通过 WeCom(企业微信)将 Hermes 接入腾讯的企业通信平台。该适配器使用 WeCom 的 AI Bot WebSocket 网关实现实时双向通信,无需公网端点或 webhook。

前提条件

  • 一个 WeCom 企业组织账号
  • 在 WeCom 管理后台中创建好的 AI Bot
  • 该 bot 凭据页中的 Bot ID 与 Secret
  • Python 包:aiohttphttpx

设置

第 1 步:创建 AI Bot

推荐:扫码创建(一条命令)

hermes gateway setup

选择 WeCom,然后用 WeCom 手机端扫码。Hermes 会自动创建一个权限配置正确的 bot 应用,并保存凭据。

向导会:

  1. 在终端显示二维码
  2. 等你用 WeCom 手机端扫码
  3. 自动获取 Bot ID 与 Secret
  4. 引导你配置访问控制

备选:手动设置

如果扫码创建不可用,向导会回退到手动输入:

  1. 登录 WeCom Admin Console
  2. 进入 ApplicationsCreate ApplicationAI Bot
  3. 配置 bot 名称与描述
  4. 从凭据页复制 Bot IDSecret
  5. 运行 hermes gateway setup,选择 WeCom 并按提示输入凭据
注意

请妥善保管 Bot Secret。任何持有它的人都可以冒充你的 bot。

第 2 步:配置 Hermes

hermes gateway setup

向导会引导你配置:

  • bot 凭据(扫码或手动输入)
  • 访问控制(allowlist、pairing 或开放访问)
  • 用于通知的 home channel

Option B: Manual Configuration

把以下内容加入 ~/.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 transport:持久连接,无需公网端点
  • DM 和群消息:支持可配置访问策略
  • 按群发送者 allowlist:细粒度控制每个群里谁能与 bot 交互
  • 媒体支持:图片、文件、语音、视频上传下载
  • AES 加密媒体:自动解密入站附件
  • 引用上下文:保留 reply threading 关系
  • Markdown rendering:支持富文本回复
  • Reply-mode streaming:把回复关联回原始入站消息上下文
  • Auto-reconnect:连接断开后自动退避重连

配置选项

config.yamlplatforms.wecom.extra 下配置:

KeyDefaultDescription
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[]私聊 allowlist
group_allow_from[]群 allowlist
groups{}每个群的细粒度配置

访问策略

DM Policy

ValueBehavior
open任何人都可以私聊 bot(默认)
allowlist只有 allow_from 中的用户可以私聊
disabled忽略所有私聊
pairing配对模式
WECOM_DM_POLICY=allowlist

Group Policy

ValueBehavior
open在所有群中响应(默认)
allowlist只在 group_allow_from 列出的群中响应
disabled忽略所有群消息
WECOM_GROUP_POLICY=allowlist

Per-Group Sender Allowlists

你还可以在 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. allowlist 条目支持 * 通配符,且匹配不区分大小写
  5. 条目也可写成 wecom:user:wecom:group: 前缀形式,适配器会自动剥离前缀

如果某个群没有配置 allow_from,则该群内所有用户都可使用 bot(前提是该群本身已经通过顶层策略校验)。

媒体支持

入站(接收)

适配器会接收并缓存以下媒体附件供 agent 处理:

TypeHow it's handled
Images下载并缓存,支持 URL 和 base64 两种形式
Files下载并缓存,保留原始文件名
Voice如果存在语音转写文本,会优先提取文本
Mixed messagesWeCom 的混合消息(文本 + 图片)会被拆解并提取全部组件

Quoted messages: 被引用消息中的媒体也会被抽取,方便 agent 理解用户正在回复什么。

AES-Encrypted Media Decryption

部分入站媒体会使用 AES-256-CBC 加密。适配器会自动处理:

  • 当媒体项包含 aeskey 字段时,适配器会先下载密文,再用 AES-256-CBC + PKCS#7 padding 解密
  • AES key 为 aeskey 字段的 base64 解码值,长度必须为 32 字节
  • IV 取自 key 的前 16 字节
  • 依赖 cryptography Python 包(pip install cryptography

出站(发送)

MethodWhat it sendsSize limit
sendMarkdown 文本消息4000 chars
send_image / send_image_file原生图片消息10 MB
send_document文件附件20 MB
send_voice原生语音消息(仅支持 AMR)2 MB
send_video视频消息10 MB

分块上传: 文件会通过三段式协议(init → chunks → finish)按 512 KB 分块上传,适配器会自动处理。

自动降级: 当媒体超出对应原生类型限制,但未超过 20 MB 文件绝对上限时,会自动降级为普通文件发送:

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

超过 20 MB 的文件会被拒绝,并在聊天中返回说明信息。

Reply-Mode Stream Responses

当 bot 通过 WeCom callback 收到消息后,适配器会记录入站请求 ID。如果在请求上下文仍然有效时发送回复,适配器会优先使用 WeCom reply-mode(aibot_respond_msg)并启用 streaming,把回复直接关联到原消息上。

如果入站请求上下文已过期或不可用,适配器会回退到主动发送模式 aibot_send_msg

reply-mode 也支持媒体:上传后的媒体可以作为对原消息的回复发送回去。

连接与重连

适配器会维持到 wss://openws.work.weixin.qq.com 的持久 WebSocket 连接。

Connection Lifecycle

  1. Connect:建立 WebSocket 连接,并发送带有 bot_idsecretaibot_subscribe 鉴权帧
  2. Heartbeat:每 30 秒发送应用层 ping,保持连接活跃
  3. Listen:持续读取入站帧并分发消息回调

Reconnection Behavior

断线后,适配器会按指数退避重连:

AttemptDelay
第 1 次重试2 秒
第 2 次重试5 秒
第 3 次重试10 秒
第 4 次重试30 秒
第 5 次及以后60 秒

每次成功重连后,退避计数都会清零。断线时,所有待决请求 future 都会失败,避免调用方无限挂起。

Deduplication

入站消息会按 message ID 做 5 分钟窗口去重,缓存上限为 1000 条,防止在重连或网络抖动场景下重复处理。

All Environment Variables

VariableRequiredDefaultDescription
WECOM_BOT_IDWeCom AI Bot ID
WECOM_SECRETWeCom AI Bot Secret
WECOM_ALLOWED_USERS(empty)网关级 allowlist 用户 ID
WECOM_HOME_CHANNELcron / 通知输出 chat ID
WECOM_WEBSOCKET_URLwss://openws.work.weixin.qq.comWebSocket 网关 URL
WECOM_DM_POLICYopen私聊访问策略
WECOM_GROUP_POLICYopen群访问策略

Troubleshooting

ProblemFix
WECOM_BOT_ID and WECOM_SECRET are required设置环境变量或使用设置向导
WeCom startup failed: aiohttp not installed安装 aiohttppip install aiohttp
WeCom startup failed: httpx not installed安装 httpxpip install httpx
invalid secret (errcode=40013)检查 secret 是否与后台配置一致
Timed out waiting for subscribe acknowledgement检查到 openws.work.weixin.qq.com 的网络连通性
群里不响应检查 group_policygroup_allow_from
某些用户在群里被忽略检查群级 allow_from 列表
媒体解密失败安装 cryptography
cryptography is required for WeCom media decryption该入站媒体为 AES 加密,请安装 cryptography
语音消息被当作文件发送WeCom 原生语音只支持 AMR,其他格式会自动降级
File too largeWeCom 对所有文件上传都限制为 20 MB
图片被当作文件发送图片超过 10 MB 时会自动降级为文件附件
Timeout sending message to WeComWebSocket 可能已断开,请检查重连日志
WeCom websocket closed during authentication可能是网络问题或凭据错误,请检查 bot_id 与 secret