跳到主要内容

Google Chat 配置

将 Hermes Agent 连接到 Google Chat 作为机器人使用。该集成使用 Cloud Pub/Sub 拉取订阅接收入站事件,使用 Chat REST API 发送出站消息。与 Slack Socket Mode 或 Telegram 长轮询具有相同的使用体验:你的 Hermes 进程不需要公共 URL、隧道或 TLS 证书。它连接、认证并监听订阅——与 Telegram 机器人监听 token 的方式相同。

Workspace 版本

Google Chat 是 Google Workspace 的一部分。你可以在个人 Workspace(通过 Google 注册的 @yourdomain.com)或你拥有管理员权限可以发布应用的工作 Workspace 中使用此集成。纯 Gmail 账户无法托管 Chat 应用。

概览

组件
依赖库google-cloud-pubsubgoogle-api-python-clientgoogle-auth
入站传输Cloud Pub/Sub 拉取订阅(无需公共端点)
出站传输Chat REST API (chat.googleapis.com)
认证在订阅上具有 roles/pubsub.subscriber 的 Service Account JSON
用户标识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:创建 Service Account

IAM & Admin → Service Accounts → Create Service Account。

  • 名称:hermes-chat-bot
  • 跳过"Grant this service account access to project"步骤。你只需要在特定订阅上的 IAM 权限——不要授予项目级 Pub/Sub 角色。

创建后,打开该 SA,进入 Keys → Add Key → Create new key → JSON 并下载文件。将其保存在只有 Hermes 可以读取的位置(如 ~/.hermes/google-chat-sa.jsonchmod 600)。

不存在"Chat Bot Caller"角色

一个常见错误是搜索 Chat 专属的 IAM 角色并在项目级别授予它。该角色不存在。Chat 机器人权限来自被安装到空间中,而非来自 IAM。你的 SA 只需要在你下一步创建的订阅上拥有 Pub/Sub subscriber 权限。


步骤 4:创建 Pub/Sub 主题和订阅

Pub/Sub → Topics → Create topic。

  • Topic ID:hermes-chat-events
  • 其他保持默认。

创建后,主题的详情页有一个 Subscriptions 标签页。创建一个:

  • Subscription ID:hermes-chat-events-sub
  • Delivery type:Pull
  • Message retention:7 days(这样积压消息在 hermes 重启时仍然保留)
  • 其他保持默认。

步骤 5:主题上的 IAM 绑定(关键)

主题(不是订阅)上,添加 IAM 主体:

  • Principal:chat-api-push@system.gserviceaccount.com
  • Role:Pub/Sub Publisher

没有这个,Google Chat 无法向你的主题发布事件,你的机器人将永远收不到任何消息。


步骤 6:订阅上的 IAM 绑定

订阅上,将你自己的 Service Account 添加为主体:

  • Principal:hermes-chat-bot@<your-project>.iam.gserviceaccount.com
  • Role: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:限制为你的 workspace(或特定用户)——在测试时不要发布给所有人。

保存。


步骤 8:在测试空间中安装机器人

在浏览器中打开 Google Chat。在 + New Chat 菜单中搜索你的应用名称以开始私聊。第一次给它发消息时,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,SA 路径回退到 GOOGLE_APPLICATION_CREDENTIALS——使用你偏好的惯例即可。

安装带有可选依赖的 Hermes:

pip install 'hermes-agent[google_chat]'

启动网关:

hermes gateway

你应该能看到类似如下的日志行:

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

在测试私聊中发送"hola"。机器人会先发布一个"Hermes is thinking…"标记,然后就地编辑该消息为真实响应——不会出现"消息已删除"的墓碑提示。


格式化和功能

Google Chat 渲染有限的 Markdown 子集:

支持不支持
*bold*_italic_~strike~`code`标题、列表
通过 URL 的内联图片Card v2 交互按钮(本网关为 v1)
原生文件附件(在 /setup-files 之后——见步骤 10)原生语音消息 / 圆形视频消息

Agent 的系统提示词中包含 Google Chat 专属提示,使其知道这些限制并避免使用不会正确渲染的格式。

消息大小限制:每条消息 4000 字符。较长的 Agent 响应会自动拆分为多条消息。

线程支持:当用户在线程内回复时,Hermes 检测 thread.name 并在同一线程中发布回复,因此每个线程都有一个独立的 Hermes 会话。


步骤 10:原生附件投递(可选)

开箱即用,机器人可以发送文本、通过 URL 内联图片,以及为音频/视频/文档提供下载卡片。要投递原生 Chat 附件——与人类拖放文件时相同的文件小部件——每个用户需要通过单用户 OAuth 流程授权一次。

为什么需要单独的流程

Google Chat 的 media.upload 端点拒绝 Service Account 认证:

This method doesn't support app authentication with a service account. Authenticate with a user account.

没有 IAM 角色或 scope 能修复这个问题。该端点只接受用户凭据。因此机器人在上传文件时必须以用户身份操作——具体来说,是以请求文件的那个用户的身份。

一次性主机设置

  1. 在同一 GCP 项目中进入 APIs & Services → Credentials
  2. Create credentials → OAuth client ID → Desktop app
  3. 下载 JSON。将其移到运行 Hermes 的主机上。
  4. 在主机上,向 Hermes 注册该客户端:
python -m gateway.platforms.google_chat_user_oauth \
--client-secret /path/to/client_secret.json

这会写入 ~/.hermes/google_chat_user_client_secret.json。这是共享基础设施——它标识 OAuth 应用,而非任何单个用户。无论之后有多少用户授权,每台主机一个文件就够了。

每用户授权(在聊天中)

每个用户在自己与机器人的私聊中执行一次流程:

  1. 他们向机器人发送 /setup-files。机器人回复状态和下一步。
  2. 他们发送 /setup-files start。机器人回复 OAuth URL。
  3. 他们打开 URL,点击 Allow,然后看到浏览器无法加载 http://localhost:1/?...&code=...。这个失败是预期的——授权码在地址栏中。
  4. 他们复制失败的 URL(或只是 code=... 值)并粘贴回聊天中作为 /setup-files <PASTED_URL>。机器人将其交换为刷新令牌。

令牌保存在 ~/.hermes/google_chat_user_tokens/<sanitized_email>.json。该用户 DM 中后续的文件请求使用他们的令牌,因此机器人以他们的身份上传,消息落在他们的空间中。

要撤销:/setup-files revoke 只删除该用户的令牌。其他用户的令牌不受影响。

权限范围

该流程只请求一个 scope:chat.messages.create。这涵盖了 media.upload 和引用上传的 attachmentDataRefmessages.create。不涉及 Drive,不涉及更广泛的 Chat scope——这是有意的最小权限设计。

多用户行为

当请求者尚无每用户令牌时,机器人回退到 ~/.hermes/google_chat_user_token.json 的旧式单用户令牌(如果存在于多用户安装之前的版本)。当两者都不可用时,机器人发布明确的文本通知,告知请求者运行 /setup-files

用户撤销只清除自己的槽位。某个用户令牌的 401/403 只驱逐该用户的缓存。用户之间不会相互干扰。


故障排查

发送"hola"后机器人保持沉默。

  1. 检查控制台中 Pub/Sub 订阅是否有未投递的消息。如果有,说明 Hermes 未认证——验证 GOOGLE_CHAT_SERVICE_ACCOUNT_JSON 以及 SA 是否被列为订阅的 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,错误消息会告诉你哪个环境变量需要修复。

机器人回复了但显示的是错误消息而非 Agent 的答复。

检查日志中是否有 [GoogleChat] Pub/Sub stream died——如果重复出现,你的 SA 凭据可能已被轮换或订阅已被删除。10 次尝试后适配器会标记自己为 fatal。

每条出站消息都收到"403 Forbidden"。

机器人已从空间中移除,或者你在 Chat API 控制台中撤销了它。在空间中重新安装它(下一个 ADDED_TO_SPACE 事件将自动重新启用消息传递)。

过多"Rate limit hit"警告。

Chat API 的默认配额允许每个空间每分钟 60 条消息。如果你的 Agent 产生超过该限制的长流式响应,适配器会使用指数退避重试——但你仍然会看到用户可见的延迟。考虑简洁响应或在 GCP 控制台中提高配额。

机器人不断发布"/setup-files"通知而不是文件。

请求者没有每用户 OAuth 令牌且没有旧式后备。在其 DM 中运行 /setup-files 并按照步骤 10 操作。交换完成后,下一个文件请求会原生上传,无需重启网关。

/setup-files start 说"No client credentials stored on the host."

一次性主机设置未完成。在运行 Hermes 的主机终端中:

python -m gateway.platforms.google_chat_user_oauth \
--client-secret /path/to/client_secret.json

然后再次发送 /setup-files start

/setup-files <PASTED_URL> 说"Token exchange failed."

授权码是一次性的且有效期很短(通常几分钟)。发送 /setup-files start 获取新 URL 并重试。


安全注意事项

  • Service Account 范围:适配器请求 chat.botpubsub scope。IAM 应该是实际的执行层——给你的 SA 授予最小权限(订阅上的 roles/pubsub.subscriber + roles/pubsub.viewer),而不是项目级或组织级 Pub/Sub 角色。
  • 附件下载保护:Hermes 只会将 SA bearer token 附加到主机匹配 Google 自有域名白名单的 URL(googleapis.comdrive.google.comlh[3-6].googleusercontent.com 等)。任何其他主机在 HTTP 请求发出前就会被拒绝,以防止精心构造的事件将 bearer token 重定向到 GCE 元数据服务的 SSRF 场景。
  • 脱敏:Service Account 邮箱、订阅路径和主题路径由 agent/redact.py 从日志输出中剥离。调试信封转储(GOOGLE_CHAT_DEBUG_RAW=1)通过同一脱敏过滤器并在 DEBUG 级别记录。
  • 合规性:如果你计划将此机器人连接到受监管的 workspace(任何具有数据驻留或 AI 治理策略的环境),请在首次安装前获得审批。
  • 用户 OAuth 范围:每用户附件流程请求 chat.messages.create——覆盖 media.upload 加上后续 messages.create 的最小权限。令牌以纯 JSON 形式持久化在 ~/.hermes/google_chat_user_tokens/<sanitized_email>.json(文件系统权限是保护措施——与 SA 密钥文件相同的模型)。每个令牌属于确切的一个用户;撤销限定于该用户。