ByteNoteByteNote

字节笔记本

2026年6月21日

hermes教程-Google Chat

API中转
¥120

Google Chat 设置

将 Hermes Agent 作为机器人连接到 Google Chat。该集成使用 Cloud Pub/Sub 拉取订阅来处理入站事件,并使用 Chat REST API 处理出站消息。其操作方式与 Slack Socket 模式或 Telegram 长轮询类似:你的 Hermes 进程不需要公共 URL、隧道或 TLS 证书。它通过订阅进行连接、身份验证和监听——就像 Telegram 机器人通过令牌监听一样。

运行 hermes gateway setup 并选择 Google Chat 以获取引导式操作指南。

注意——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

在控制台中,转到 API 和服务 → 库 并启用:

  • Google Chat API
  • Cloud Pub/Sub API

对于个人机器人产生的流量,两者都是免费的。


步骤 3:创建服务账户

IAM 和管理 → 服务账户 → 创建服务账户。

  • 名称:hermes-chat-bot
  • 跳过“授予此服务账户对项目的访问权限”步骤。你只需要在特定订阅上设置 IAM——不要授予项目级别的 Pub/Sub 角色。

创建后,打开服务账户,转到 密钥 → 添加密钥 → 创建新密钥 → JSON 并下载文件。将其保存在只有 Hermes 能读取的位置(例如 ~/.hermes/google-chat-sa.jsonchmod 600)。

注意——没有“Chat 机器人调用者”角色

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


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

Pub/Sub → 主题 → 创建主题。

  • 主题 ID:hermes-chat-events
  • 其他所有选项保持默认。

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

  • 订阅 ID:hermes-chat-events-sub
  • 投递类型:拉取
  • 消息保留:7 天(这样重启 Hermes 后积压消息仍存在)
  • 其余保持默认。

步骤 5:在主题上设置 IAM 绑定(关键)

主题(而非订阅)上,添加一个 IAM 主体:

  • 主体:chat-api-push@system.gserviceaccount.com
  • 角色:Pub/Sub 发布者

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


步骤 6:在订阅上设置 IAM 绑定

订阅 上,将你自己的服务账户添加为主体:

  • 主体:hermes-chat-bot@<your-project>.iam.gserviceaccount.com
  • 角色:Pub/Sub 订阅者

同时在同一订阅上授予 Pub/Sub 查看者 角色——Hermes 在启动时会调用 subscription.get() 作为可达性检查。


步骤 7:配置 Chat 应用

转到 API 和服务 → Google Chat API → 配置

  • 应用名称:你希望用户看到的名称(“Hermes” 是合理的)。
  • 头像 URL:任何公共 PNG(Google 有一些默认头像)。
  • 描述:在应用目录中显示的简短句子。
  • 功能:启用 接收 1:1 消息加入空间和群组对话
  • 连接设置:选择 Cloud Pub/Sub,输入主题名称 projects/<your-project>/topics/hermes-chat-events
  • 可见性:限制在你的工作区(或特定用户)——测试时不要发布给所有人。

保存。


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

在浏览器中打开 Google Chat。通过搜索其名称,在 + 新聊天 菜单中与你的应用开始私聊。第一次发送消息时,Google 会发送一个 ADDED_TO_SPACE 事件,Hermes 会利用该事件缓存机器人自己的 users/{id},用于自消息过滤。


步骤 9:配置 Hermes

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

bash
## 必需
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
## 授权——粘贴允许与机器人对话的用户邮箱
GOOGLE_CHAT_ALLOWED_USERS=you@yourdomain.com,coworker@yourdomain.com
## 可选
GOOGLE_CHAT_HOME_CHANNEL=spaces/AAAA...         # cron 作业的默认投递目标
GOOGLE_CHAT_MAX_MESSAGES=1                      # Pub/Sub 流量控制;1 表示每个会话串行化命令
GOOGLE_CHAT_MAX_BYTES=16777216                  # 16 MiB——在途消息字节数上限

项目 ID 也可以回退到 GOOGLE_CLOUD_PROJECT,服务账户路径也可以回退到 GOOGLE_APPLICATION_CREDENTIALS——使用你喜欢的任何约定。

安装 Google Chat 适配器所需的依赖项(目前没有发布 Hermes 额外包——直接安装它们):

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

启动网关:

bash
hermes gateway

你应该会看到类似这样的日志行:

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

在测试私聊中发送“hola”。机器人会发布一个“Hermes 正在思考…”标记,然后用真实响应原地编辑同一条消息——不会出现“消息已删除”的墓碑。


格式与功能

Google Chat 渲染有限的 Markdown 子集:

支持不支持
*粗体*, _斜体_, ~删除线~, `代码`标题、列表
通过 URL 的内联图片交互式卡片 v2 按钮(此网关的 v1 版本)
原生文件附件(在 /setup-files 之后——见步骤 10)原生语音笔记 / 圆形视频笔记

代理的系统提示中包含一个 Google Chat 特定的提示,以便它了解这些限制,并避免使用无法渲染的格式。

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

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


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

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

为什么需要单独的流程

Google Chat 的 media.upload 端点硬性拒绝服务账户认证:

此方法不支持使用服务账户的应用认证。请使用用户账户进行认证。

没有 IAM 角色或作用域可以解决这个问题。该端点只接受用户凭据。因此,机器人每次上传文件时都必须以 用户 的身份操作——具体来说,是以请求该文件的用户的身份。

一次性设置(每个配置文件)

  1. 在同一 GCP 项目中转到 API 和服务 → 凭据
  2. 创建凭据 → OAuth 客户端 ID → 桌面应用
  3. 下载 JSON。将其移动到运行 Hermes 的主机上。
  4. 向 Hermes 注册客户端(在你希望其作用域所在的配置文件下运行):
bash
## 默认配置文件:
python -m plugins.platforms.google_chat.oauth \
    --client-secret /path/to/client_secret.json
## 命名配置文件有自己独立的注册:
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 附件投递的配置文件注册一次。

每用户授权(在聊天中)

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

  1. 用户向机器人发送 /setup-files。机器人回复状态和下一步。
  2. 用户发送 /setup-files start。机器人回复一个 OAuth URL。
  3. 用户打开 URL,点击 允许,然后看到浏览器无法加载 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 和引用上传的 attachmentDataRef 的后续 messages.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 订阅者
  2. 如果订阅有零条消息,说明 Google Chat 没有发布。再次检查 主题 上的 IAM 绑定:chat-api-push@system.gserviceaccount.com 必须具有 Pub/Sub 发布者 角色。
  3. 检查 hermes gateway 日志中是否有 [GoogleChat] Connected。如果你看到 [GoogleChat] Config validation failed,错误消息会告诉你需要修复哪个环境变量。

机器人回复了,但出现错误消息而不是代理的答案。

检查日志中是否有 [GoogleChat] Pub/Sub stream died——如果这些重复出现,你的服务账户凭据可能已被轮换,或者订阅已被删除。在 10 次尝试后,适配器会将其标记为致命错误。

每条出站消息都出现“403 Forbidden”。

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

出现太多“达到速率限制”警告。

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

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

请求者没有每用户 OAuth 令牌,也没有旧版回退。在他们的私聊中运行 /setup-files 并按照步骤 10 操作。交换完成后,下一个文件请求将原生上传,无需重启网关。

/setup-files start 显示“未存储客户端凭据。”

一次性设置没有针对 此配置文件 完成(客户端密钥是配置文件作用域的,因此在一个配置文件下的注册不会被另一个配置文件看到)。在终端中,在网关使用的配置文件下运行:

bash
## 默认配置文件:
python -m plugins.platforms.google_chat.oauth \
    --client-secret /path/to/client_secret.json
## 命名配置文件:
hermes -p <profile> python -m plugins.platforms.google_chat.oauth \
    --client-secret /path/to/client_secret.json

然后再次发送 /setup-files start

/setup-files <PASTED_URL> 显示“令牌交换失败。”

认证码是单次使用且寿命短暂(通常几分钟)。发送 /setup-files start 获取新的 URL 并重试。


安全说明

  • 服务账户作用域:适配器请求 chat.botpubsub 作用域。IAM 应该是实际的执行机制——授予你的服务账户最小权限(订阅上的 roles/pubsub.subscriber + roles/pubsub.viewer),而不是项目级别或组织级别的 Pub/Sub 角色。
  • 附件下载保护:Hermes 只会将服务账户持有者令牌附加到主机名与 Google 拥有的域名的短白名单(googleapis.comdrive.google.comlh[3-6].googleusercontent.com 等)匹配的 URL。任何其他主机名都会在 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(文件系统权限是保护措施——与服务账户密钥文件相同模型)。每个令牌仅由一个用户拥有;撤销仅限于该用户。


分享: