跳到主要內容

Google Chat 設置

將 Hermes Agent 作為機器人連接到 Google Chat。該集成使用 Cloud Pub/Sub 拉取訂閱(pull subscriptions)處理入站事件,並使用 Chat REST API 發送出站消息。其易用性與 Slack Socket Mode 或 Telegram 長輪詢相當:你的 Hermes 進程不需要公共 URL、隧道或 TLS 證書。它通過連接、認證並監聽訂閱來工作——這與 Telegram 機器人監聽令牌的方式相同。

運行 hermes gateway setup 並選擇 Google Chat 以獲取引導式 walkthrough。

Workspace 版本

Google Chat 是 Google Workspace 的一部分。你可以使用個人 Workspace(通過 Google 註冊的 @yourdomain.com)或你擁有發佈應用管理員權限的工作 Workspace 進行此集成。僅限 Gmail 的賬戶無法託管 Chat 應用。

概覽

組件
google-cloud-pubsub, google-api-python-client, google-auth
入站傳輸Cloud Pub/Sub 拉取訂閱(無公共端點)
出站傳輸Chat REST API (chat.googleapis.com)
身份驗證服務賬號 JSON,在訂閱上具有 roles/pubsub.subscriber 角色
用戶標識Chat 資源名稱 (users/{id}) + 電子郵件

步驟 1:創建或選擇一個 GCP 項目

你需要一個 Google Cloud 項目來託管 Pub/Sub 主題。如果你還沒有項目,請在 console.cloud.google.com 創建一個——個人賬戶獲得的免費層級足以覆蓋機器人流量。

記下項目 ID(例如 my-chat-bot-123)。你在後續的每個步驟中都會用到它。


步驟 2:啟用兩個 API

在控制檯中,前往 APIs & Services → Library 並啟用:

  • Google Chat API
  • Cloud Pub/Sub API

對於個人機器人產生的流量,這兩者都是免費的。


步驟 3:創建服務賬號

IAM & Admin → Service Accounts → Create Service Account。

  • 名稱:hermes-chat-bot
  • 跳過“授予此服務賬號訪問項目的權限”步驟。你只需要特定訂閱上的 IAM 權限——不要授予項目級別的 Pub/Sub 角色。

創建後,打開該服務賬號,前往 Keys → Add Key → Create new key → JSON 並下載文件。將其保存在只有 Hermes 可以讀取的位置(例如 ~/.hermes/google-chat-sa.json,執行 chmod 600)。

不存在“Chat Bot Caller”角色

一個常見的錯誤是搜索特定的 Chat IAM 角色並在項目級別授予它。該角色並不存在。Chat 機器人的權限來自於安裝在空間(space)中,而非來自 IAM。你的服務賬號只需要在下一步創建的訂閱上擁有 Pub/Sub 訂閱者權限。


步驟 4:創建 Pub/Sub 主題和訂閱

Pub/Sub → Topics → Create topic.

  • 主題 ID:hermes-chat-events
  • 其他所有選項保留默認值。

創建後,在主題的詳情頁面有一個 Subscriptions 標籤頁。創建一個訂閱:

  • 訂閱 ID:hermes-chat-events-sub
  • 交付類型:Pull
  • 消息保留:7 days(以便積壓消息在 hermes 重啟後仍然存在)
  • 其餘保留默認值。

步驟 5:主題上的 IAM 綁定(關鍵)

主題(而非訂閱)上,添加一個 IAM 主體:

  • 主體:chat-api-push@system.gserviceaccount.com
  • 角色:Pub/Sub Publisher

如果沒有這一步,Google Chat 無法向你的主題發佈事件,你的機器人將永遠收不到任何消息。


步驟 6:訂閱上的 IAM 綁定

訂閱上,將你自己的服務賬號添加為主體:

  • 主體:hermes-chat-bot@<your-project>.iam.gserviceaccount.com
  • 角色:Pub/Sub Subscriber

同時在該訂閱上授予 Pub/Sub Viewer 權限——Hermes 在啟動時會調用 subscription.get() 作為可達性檢查。


步驟 7:配置 Chat 應用

前往 APIs & Services → Google Chat API → Configuration

  • App name:你希望用戶看到的名稱(“Hermes”是合理的選擇)。
  • Avatar URL:任何公開的 PNG 圖片(Google 有一些默認圖片)。
  • Description:在應用目錄中顯示的一句簡短描述。
  • Functionality:啟用 Receive 1:1 messagesJoin spaces and group conversations
  • Connection settings:選擇 Cloud Pub/Sub,輸入主題名稱 projects/<your-project>/topics/hermes-chat-events
  • Visibility:限制為你的工作區(或特定用戶)——在測試期間不要發佈給所有人。

保存。


步驟 8:在測試空間中安裝機器人

在瀏覽器中打開 Google Chat。通過在 + New Chat 菜單中搜索應用名稱,開始與你的應用進行私聊(DM)。第一次向其發送消息時,Google 會發送一個 ADDED_TO_SPACE 事件,Hermes 利用該事件緩存機器人自身的 users/{id} 以用於自我消息過濾。


步驟 9:配置 Hermes

將 Google Chat 部分添加到 ~/.hermes/.env

# Required
GOOGLE_CHAT_PROJECT_ID=my-chat-bot-123
GOOGLE_CHAT_SUBSCRIPTION_NAME=projects/my-chat-bot-123/subscriptions/hermes-chat-events-sub
GOOGLE_CHAT_SERVICE_ACCOUNT_JSON=/home/you/.hermes/google-chat-sa.json

# Authorization — paste the emails of people allowed to talk to the bot
GOOGLE_CHAT_ALLOWED_USERS=you@yourdomain.com,coworker@yourdomain.com

# Optional
GOOGLE_CHAT_HOME_CHANNEL=spaces/AAAA... # default delivery destination for cron jobs
GOOGLE_CHAT_MAX_MESSAGES=1 # Pub/Sub FlowControl; 1 serializes commands per session
GOOGLE_CHAT_MAX_BYTES=16777216 # 16 MiB — cap on in-flight message bytes

項目 ID 也可以回退到 GOOGLE_CLOUD_PROJECT,服務賬號路徑可以回退到 GOOGLE_APPLICATION_CREDENTIALS——使用你喜歡的約定即可。

安裝 Google Chat 適配器所需的依賴項(目前尚未發佈 Hermes extra——直接安裝它們):

pip install google-cloud-pubsub google-api-python-client google-auth google-auth-oauthlib

啟動網關:

hermes gateway

你應該會看到類似如下的日誌行:

[GoogleChat] Connected; project=my-chat-bot-123, subscription=<redacted>,
bot_user_id=users/XXXX, flow_control(msgs=1, bytes=16777216)

在測試私聊(DM)中發送“hola”。機器人會先發佈一個“Hermes is thinking…”標記,然後就地編輯該消息,替換為實際響應——不會出現“消息已刪除”的佔位符。


格式與功能

Google Chat 僅支持有限的 Markdown 子集:

支持不支持
*bold*_italic_~strike~`code`標題、列表
通過 URL 嵌入圖片交互式 Card v2 按鈕(本網關的 v1 版本)
原生文件附件(在執行 /setup-files 後——參見步驟 10)原生語音筆記 / 圓形視頻筆記

代理的系統提示中包含針對 Google Chat 的特定提示,使其瞭解這些限制並避免使用無法渲染的格式。

消息大小限制:每條消息 4000 個字符。較長的代理響應會自動拆分為多條消息。

線程支持:當用戶在線程內回覆時,Hermes 會檢測 thread.name 並在同一線程中發佈回覆,因此每個線程擁有獨立的 Hermes 會話。


步驟 10:原生附件交付(可選)

默認情況下,機器人可以發佈文本、通過 URL 嵌入圖片,以及用於音頻/視頻/文檔的下載卡片。要交付原生 Chat 附件(即人類拖放文件時出現的相同文件小部件),每位用戶需通過每用戶 OAuth 流程對機器人進行一次授權。

為何需要單獨的流程

Google Chat 的 media.upload 端點明確拒絕服務賬號認證:

此方法不支持使用服務賬號進行應用認證。請使用用戶賬號進行認證。

沒有任何 IAM 角色或範圍可以解決此問題。該端點僅接受用戶憑據。因此,機器人在上傳文件時必須以用戶身份行事——具體而言,是以請求文件的用戶身份。

一次性設置(每個配置文件)

  1. 在同一 GCP 項目中,前往 APIs & Services → Credentials
  2. Create credentials → OAuth client ID → Desktop app
  3. 下載 JSON 文件。將其移動到運行 Hermes 的主機上。
  4. 向 Hermes 註冊客戶端(在希望限定範圍的配置文件下運行):
# Default profile:
python -m plugins.platforms.google_chat.oauth \
--client-secret /path/to/client_secret.json

# A named profile gets its own separate registration:
hermes -p <profile> python -m plugins.platforms.google_chat.oauth \
--client-secret /path/to/client_secret.json

這會將客戶端密鑰寫入活動配置文件的 Hermes 主目錄(例如,默認配置文件為 ~/.hermes/google_chat_user_client_secret.json)。客戶端密鑰是配置文件範圍的,不在配置文件間共享——每個配置文件註冊自己的密鑰。這是有意為之:配置文件是隔離的認證邊界,因此兩個配置文件可以指向不同的 Google OAuth 應用/賬號。僅為需要 Google Chat 附件交付的每個配置文件註冊一次。

每用戶授權(在聊天中)

每位用戶在其與機器人的私聊(DM)中運行一次該流程:

  1. 他們向機器人發送 /setup-files。機器人回覆狀態和下一步操作。
  2. 他們發送 /setup-files start。機器人回覆一個 OAuth URL。
  3. 他們打開該 URL,點擊 Allow,並觀察瀏覽器無法加載 http://localhost:1/?...&code=...。這種失敗是預期的——認證代碼位於 URL 欄中。
  4. 他們複製失敗的 URL(或僅複製 code=... 值)並將其粘貼回聊天中,作為 /setup-files <PASTED_URL>。機器人將其交換為刷新令牌。

令牌存儲在 ~/.hermes/google_chat_user_tokens/<sanitized_email>.json。該用戶後續在私聊中的文件請求將使用令牌,因此機器人以其身份上傳,消息出現在其空間中。

如需稍後撤銷:/setup-files revoke 僅刪除該用戶的令牌。其他用戶的令牌不受影響。

範圍

該流程僅請求一個範圍:chat.messages.create。這涵蓋了 media.upload 和引用已上傳 attachmentDataRefmessages.create。不包含 Drive,也不包含更廣泛的 Chat 範圍——這是有意遵循最小權限原則。

多用戶行為

當提問者尚無每用戶令牌時,機器人會回退到遺留的單用戶令牌 ~/.hermes/google_chat_user_token.json(如果存在來自預多用戶安裝的令牌)。如果兩者均不可用,機器人會發布明確的文本通知,告知提問者運行 /setup-files

用戶撤銷僅清除其自己的槽位。來自某用戶令牌的 401/403 錯誤僅驅逐該用戶的緩存。用戶之間不會相互干擾。


故障排除

發送“hola”後機器人保持沉默。

  1. 在控制檯中檢查 Pub/Sub 訂閱是否有未投遞的消息。如果有,說明 Hermes 未通過認證——驗證 GOOGLE_CHAT_SERVICE_ACCOUNT_JSON 並確保服務賬號在訂閱中被列為 Pub/Sub Subscriber
  2. 如果訂閱中沒有消息,說明 Google Chat 未發佈消息。仔細檢查主題上的 IAM 綁定:chat-api-push@system.gserviceaccount.com 必須具有 Pub/Sub Publisher 角色。
  3. 檢查 hermes gateway 日誌中是否有 [GoogleChat] Connected。如果看到 [GoogleChat] Config validation failed,錯誤消息會告訴你需要修復哪個環境變量。

機器人回覆了,但顯示的是錯誤消息而非代理的答案。

檢查日誌中是否有 [GoogleChat] Pub/Sub stream died——如果反覆出現,你的服務賬號憑據可能已被輪換或訂閱已被刪除。嘗試 10 次後,適配器會將自身標記為致命錯誤。

每條出站消息都出現“403 Forbidden”。

機器人已從空間中移除,或者你在 Chat API 控制檯中撤消了它。 在空間中重新安裝它(下一個 ADDED_TO_SPACE 事件將自動重新啟用消息傳遞)。

“Rate limit hit”警告過多。

Chat API 的默認配額允許每個空間每分鐘發送 60 條消息。如果你的代理生成了超過該限制的長流式響應,適配器會使用指數退避進行重試——但你仍然會看到用戶可見的延遲。請考慮使用更簡潔的響應或在 GCP 控制檯中提高配額。

機器人持續發佈“/setup-files”通知而不是文件。

提問者沒有每用戶 OAuth 令牌,且沒有舊版回退機制。在他們的私聊(DM)中運行 /setup-files 並按照步驟 10 操作。交換完成後,下一次文件請求將原生上傳,無需重啟網關。

/setup-files start 顯示“No client credentials stored.”

尚未為此配置文件執行一次性設置(客戶端密鑰是配置文件範圍的,因此在一個配置文件下注冊的密鑰不會在另一個配置文件中可見)。從終端中,在網關使用的配置文件下運行它:

# Default profile:
python -m plugins.platforms.google_chat.oauth \
--client-secret /path/to/client_secret.json

# Named profile:
hermes -p <profile> python -m plugins.platforms.google_chat.oauth \
--client-secret /path/to/client_secret.json

然後再次發送 /setup-files start

/setup-files <PASTED_URL> 顯示“Token exchange failed.”

授權代碼是一次性且短效的(通常只有幾分鐘)。發送 /setup-files start 以獲取新的 URL 並重試。


安全說明

  • 服務賬號範圍:適配器請求 chat.botpubsub 範圍。IAM 應是實際的執行機制——授予你的服務賬號最小權限(訂閱上的 roles/pubsub.subscriber + roles/pubsub.viewer),而不是項目級或組織級的 Pub/Sub 角色。
  • 附件下載保護:Hermes 僅將服務賬號持有者令牌附加到主機與 Google 自有域名的簡短允許列表匹配 URL(googleapis.comdrive.google.comlh[3-6].googleusercontent.com 以及其他幾個域名)。任何其他主機都會在 HTTP 請求之前被拒絕,以防止 SSRF 場景,即精心構造的事件可能將持有者令牌重定向到 GCE 元數據服務。
  • 脫敏:服務賬號電子郵件、訂閱路徑和主題路徑會通過 agent/redact.py 從日誌輸出中剝離。調試信封轉儲(GOOGLE_CHAT_DEBUG_RAW=1)通過相同的脫敏過濾器路由,並以 DEBUG 級別記錄。
  • 合規性:如果你計劃將此機器人連接到受監管的工作區(任何具有數據駐留或 AI 治理策略的工作區),請在首次安裝前獲得批准。
  • 用戶 OAuth 範圍:每用戶附件流僅請求 chat.messages.create——這是涵蓋 media.upload 以及後續 messages.create 的最小範圍。令牌以純 JSON 形式持久存儲在 ~/.hermes/google_chat_user_tokens/<sanitized_email>.json(文件系統權限是保護機制——與服務賬號密鑰文件的模型相同)。每個令牌僅由一個用戶擁有;撤消範圍僅限於該用戶。