跳到主要內容

微信 (WeChat)

將 Hermes 連接到 微信(騰訊的個人即時通訊平臺)。該適配器使用騰訊的 iLink Bot API 來支持個人微信賬號——這與企業微信(WeCom)不同。消息通過長輪詢方式傳輸,因此無需公網端點或 Webhook。

信息

此適配器適用於 個人微信賬號(微信)。如需企業/公司微信,請參閱 企業微信適配器

前提條件

  • 一個個人微信賬號
  • Python 包:aiohttpcryptography
  • qrcode 包為可選(用於在設置過程中在終端中渲染二維碼)

安裝所需依賴:

pip install aiohttp cryptography
# 可選:用於終端QR代碼顯示
pip install qrcode

設置

1. 運行設置嚮導

連接微信賬號最簡單的方式是通過交互式設置嚮導:

hermes gateway setup

提示時選擇 Weixin。嚮導將執行以下操作:

  1. 向 iLink Bot API 請求一個二維碼
  2. 在終端中顯示二維碼(或提供一個 URL)
  3. 等待您使用微信手機 App 掃描二維碼
  4. 提示您在手機上確認登錄
  5. 自動將賬號憑證保存至 ~/.hermes/weixin/accounts/

確認後,您將看到類似如下消息:

微信連接成功,account_id=your-account-id

嚮導會保存 account_idtokenbase_url,因此無需手動配置。

2. 配置環境變量

首次通過二維碼登錄後,請在 ~/.hermes/.env 中至少設置賬號 ID:

WEIXIN_ACCOUNT_ID=your-account-id

# 可選:覆蓋 token(通常從 QR 登錄自動保存)
# WEIXIN_TOKEN=你的機器人-token

# 可選:限制訪問
WEIXIN_DM_POLICY=open
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2

# 可選:為 Cron / 通知設置主頻道
WEIXIN_HOME_CHANNEL=chat_id
WEIXIN_HOME_CHANNEL_NAME=Home

3. 啟動網關

hermes gateway

適配器將恢復保存的憑證,連接到 iLink API,並開始長輪詢接收消息。

功能特性

  • 長輪詢傳輸 —— 無需公網端點、Webhook 或 WebSocket
  • 二維碼登錄 —— 通過 hermes gateway setup 實現掃碼連接
  • 私信與群組消息 —— 可配置訪問策略
  • 媒體支持 —— 圖片、視頻、文件和語音消息
  • AES-128-ECB 加密 CDN —— 所有媒體傳輸自動加密/解密
  • 上下文令牌持久化 —— 磁盤持久化,支持重啟後繼續回覆
  • Markdown 格式化 —— 標題、表格和代碼塊會重新格式化以適配微信閱讀
  • 智能消息分塊 —— 長消息在邏輯邊界(段落、代碼塊)處自動拆分
  • 輸入提示 —— Agent 處理時,微信客戶端會顯示“正在輸入…”狀態
  • SSRF 保護 —— 下載前驗證出站媒體 URL
  • 消息去重 —— 5 分鐘滑動窗口防止重複處理
  • 自動重試帶退避機制 —— 可從臨時 API 錯誤中恢復

配置選項

config.yaml 中的 platforms.weixin.extra 下設置以下選項:

默認值描述
account_idiLink Bot 賬號 ID(必需)
tokeniLink Bot 令牌(必需,由二維碼登錄自動保存)
base_urlhttps://ilinkai.weixin.qq.comiLink API 基礎 URL
cdn_base_urlhttps://novac2c.cdn.weixin.qq.com/c2c媒體傳輸的 CDN 基礎 URL
dm_policyopen私信訪問策略:openallowlistdisabledpairing
group_policydisabled群組訪問策略:openallowlistdisabled
allow_from[]允許私信的用戶 ID 列表(當 dm_policy=allowlist 時)
group_allow_from[]允許響應的群組 ID 列表(當 group_policy=allowlist 時)

訪問策略

私信策略(DM Policy)

控制誰可以向機器人發送私信:

行為
open任何人都可以向機器人發送私信(默認)
allowlistallow_from 列表中的用戶 ID 可發送私信
disabled所有私信均被忽略
pairing配對模式(用於初始設置)
WEIXIN_DM_POLICY=allowlist
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2

群組策略(Group Policy)

控制機器人在哪些群組中響應:

行為
open機器人在所有群組中響應
allowlist機器人僅在 group_allow_from 列表中的群組 ID 中響應
disabled所有群組消息均被忽略(默認)
WEIXIN_GROUP_POLICY=allowlist
WEIXIN_GROUP_ALLOWED_USERS=group_id_1,group_id_2
備註

個人微信賬號的默認群組策略為 disabled(與企業微信默認為 open 不同)。這是有意為之,因為個人微信賬號可能加入大量群組。

媒體支持

入站(接收)

適配器接收用戶發送的媒體附件,從微信 CDN 下載,解密後本地緩存,供 Agent 處理:

類型處理方式
圖片下載、AES 解密,並緩存為 JPEG 格式。
視頻下載、AES 解密,並緩存為 MP4 格式。
文件下載、AES 解密,並緩存。保留原始文件名。
語音若有文字轉錄,提取為文本;否則下載 SILK 格式的音頻並緩存。

引用消息:來自被引用(回覆)消息的媒體也會被提取,使 Agent 能夠了解用戶回覆的內容上下文。

AES-128-ECB 加密 CDN

微信媒體文件通過加密 CDN 傳輸。適配器會透明地處理此過程:

  • 入站(Inbound): 使用 encrypted_query_param URL 從 CDN 下載加密媒體,然後使用 AES-128-ECB 加密算法配合消息負載中提供的文件級密鑰進行解密。
  • 出站(Outbound): 文件在本地使用隨機生成的 AES-128-ECB 密鑰加密,上傳至 CDN,加密後的引用信息包含在出站消息中。
  • AES 密鑰長度為 16 字節(128 位)。密鑰可以以原始 base64 或十六進制編碼形式到達 —— 適配器會自動處理這兩種格式。
  • 此功能需要安裝 cryptography Python 包。

無需任何配置 —— 加密與解密過程自動完成。

出站(發送)

方法發送內容
send帶有 Markdown 格式的文本消息
send_image / send_image_file原生圖片消息(通過 CDN 上傳)
send_document文件附件(通過 CDN 上傳)
send_video視頻消息(通過 CDN 上傳)

所有出站媒體均通過加密 CDN 上傳流程:

  1. 生成一個隨機的 AES-128 密鑰
  2. 使用 AES-128-ECB + PKCS#7 填充對文件進行加密
  3. 通過 iLink API 請求上傳 URL(getuploadurl
  4. 將密文上傳至 CDN
  5. 發送消息並附帶加密媒體引用

上下文令牌持久化

iLink Bot API 要求每個出站消息必須回傳與特定對端關聯的 context_token。適配器維護一個基於磁盤的上下文令牌存儲:

  • 每個賬戶+對端的令牌保存在 ~/.hermes/weixin/accounts/<account_id>.context-tokens.json
  • 啟動時,先前保存的令牌會被恢復
  • 每條入站消息都會更新對應發送者的存儲令牌
  • 出站消息會自動包含最新的上下文令牌

這確保了即使網關重啟後仍能保持回覆連續性。

Markdown 格式化

微信個人聊天不原生支持完整的 Markdown 渲染。適配器會對內容進行重格式化以提升可讀性:

  • 標題# 標題)→ 轉換為 【標題】(一級標題)或 **標題**(二級及以上)
  • 表格 → 重格式化為帶標籤的鍵值列表(例如:- 列名: 值
  • 代碼塊 → 保持原樣(微信可良好渲染)
  • 過多的空白行 → 合併為雙換行

消息分塊

長消息會智能拆分以適配聊天傳輸:

  • 單條消息最大長度:4000 字符
  • 拆分點優先選擇段落邊界和空行
  • 代碼塊保持完整(不會在塊內拆分)
  • 縮進的續行(重格式化表格/列表中的子項)與父項保持在一起
  • 超大單個塊將回退至基礎適配器的截斷邏輯

輸入狀態指示

適配器會在微信客戶端顯示輸入狀態:

  1. 當消息到達時,適配器通過 getconfig API 獲取 typing_ticket
  2. 每個用戶的 typing_ticket 緩存 10 分鐘
  3. send_typing 發送輸入開始信號;stop_typing 發送輸入停止信號
  4. 網關在 Agent 處理消息期間自動觸發輸入狀態指示

長輪詢連接

適配器使用 HTTP 長輪詢(非 WebSocket)接收消息:

工作原理

  1. 連接: 驗證憑證並啟動輪詢循環
  2. 輪詢: 調用 getupdates,設置 35 秒超時;服務器保持請求打開,直到有消息到達或超時
  3. 分發: 入站消息通過 asyncio.create_task 併發分發
  4. 同步緩衝: 持久化的同步遊標(get_updates_buf)保存在磁盤,確保適配器重啟後能從正確位置恢復

重試行為

在 API 錯誤時,適配器採用簡單的重試策略:

條件行為
臨時錯誤(第 1–2 次)2 秒後重試
重複錯誤(第 3 次及以上)退避 30 秒,然後重置計數器
會話過期(errcode=-14暫停 10 分鐘(可能需要重新登錄)
超時立即重新輪詢(正常長輪詢行為)

去重

入站消息通過消息 ID 進行去重,窗口為 5 分鐘。這可防止網絡波動或重疊輪詢響應導致的重複處理。

令牌鎖

同一令牌僅允許一個 Weixin 網關實例使用。適配器在啟動時獲取作用域鎖,並在關閉時釋放。若已有其他網關正在使用相同令牌,啟動將失敗並顯示提示性錯誤信息。

所有環境變量

變量必需默認值描述
WEIXIN_ACCOUNT_IDiLink Bot 賬號 ID(來自二維碼登錄)
WEIXIN_TOKENiLink Bot 令牌(通過二維碼登錄自動保存)
WEIXIN_BASE_URLhttps://ilinkai.weixin.qq.comiLink API 基礎 URL
WEIXIN_CDN_BASE_URLhttps://novac2c.cdn.weixin.qq.com/c2c媒體傳輸的 CDN 基礎 URL
WEIXIN_DM_POLICYopen私信訪問策略:openallowlistdisabledpairing
WEIXIN_GROUP_POLICYdisabled群組訪問策略:openallowlistdisabled
WEIXIN_ALLOWED_USERS(空)用逗號分隔的用戶 ID,用於私信白名單
WEIXIN_GROUP_ALLOWED_USERS(空)用逗號分隔的群組 ID,用於群組白名單
WEIXIN_HOME_CHANNEL用於定時任務/通知輸出的聊天 ID
WEIXIN_HOME_CHANNEL_NAMEHome主頻道的顯示名稱
WEIXIN_ALLOW_ALL_USERS網關級別標誌,允許所有用戶(由設置嚮導使用)

故障排除

問題解決方法
Weixin startup failed: aiohttp and cryptography are required安裝兩者:pip install aiohttp cryptography
Weixin startup failed: WEIXIN_TOKEN is required運行 hermes gateway setup 完成二維碼登錄,或手動設置 WEIXIN_TOKEN
Weixin startup failed: WEIXIN_ACCOUNT_ID is required.env 文件中設置 WEIXIN_ACCOUNT_ID,或運行 hermes gateway setup
Another local Hermes gateway is already using this Weixin token首先停止其他網關實例——每個令牌僅允許一個輪詢器
會話已過期(errcode=-14您的登錄會話已過期。重新運行 hermes gateway setup 掃描新的二維碼
設置過程中二維碼已過期二維碼最多自動刷新 3 次。如果持續過期,請檢查網絡連接
機器人不響應私信檢查 WEIXIN_DM_POLICY —— 若設置為 allowlist,發送者必須在 WEIXIN_ALLOWED_USERS
機器人忽略群消息群組策略默認為 disabled。請將 WEIXIN_GROUP_POLICY 設置為 openallowlist
媒體下載/上傳失敗確保已安裝 cryptography。檢查對 novac2c.cdn.weixin.qq.com 的網絡訪問權限
Blocked unsafe URL (SSRF protection)外部媒體 URL 指向私有/內部地址。僅允許公共 URL
語音消息顯示為文本若微信提供語音轉文字,適配器將使用文本。這是預期行為
消息出現重複適配器通過消息 ID 去重。若仍見重複,請檢查是否運行了多個網關實例
iLink POST ... HTTP 4xx/5xxiLink 服務端 API 錯誤。請檢查令牌有效性及網絡連接
終端二維碼無法渲染安裝 qrcodepip install qrcode。或打開二維碼上方打印的 URL