跳转至

Google Chat

Google Chat 以官方 @openclaw/googlechat 插件形式运行:通过 Google Chat API Webhook 支持 DM 和 spaces(仅 HTTP 端点,不使用 Pub/Sub)。

安装

openclaw plugins install @openclaw/googlechat

本地检出(从 git 仓库运行时):

openclaw plugins install ./path/to/local/googlechat-plugin

快速设置(初学者)

  1. 创建一个 Google Cloud 项目,并启用 Google Chat API。
  2. 前往:Google Chat API 凭据
  3. 如果 API 尚未启用,请启用它。
  4. 创建一个 服务账号:
  5. 点击 创建凭据 > 服务账号。
  6. 名称可以任意设置(例如 openclaw-chat)。
  7. 保持权限和 principals 为空(继续,然后 完成)。
  8. 创建并下载 JSON 密钥:
  9. 点击新的服务账号 > 密钥 选项卡 > 添加密钥 > 创建新密钥 > JSON > 创建。
  10. 将下载的 JSON 文件保存在你的网关主机上(例如 ~/.openclaw/googlechat-service-account.json)。
  11. 在 Google Cloud Console Chat 配置 中创建一个 Google Chat 应用:
  12. 填写 应用信息(应用名称、头像 URL、描述)。
  13. 启用 交互功能。
  14. 在 功能 下,勾选 加入空间和群聊。
  15. 在 连接设置 下,选择 HTTP 端点 URL。
  16. 在 触发器 下,选择 为所有触发器使用同一个 HTTP 端点 URL,并将其设置为你的公共网关 URL 后跟 /googlechat(参见 公共 URL)。
  17. 在 可见性 下,勾选 将此 Chat 应用提供给 <Your Domain> 中的特定人员和群组,并输入你的邮箱地址。
  18. 点击 保存。
  19. 启用应用状态:刷新页面,找到 应用状态,将其设置为 已上线 - 可供用户使用,然后再次 保存。
  20. 使用服务账号和 webhook audience 配置 OpenClaw(必须与 Chat 应用配置匹配):
  21. 环境变量:GOOGLE_CHAT_SERVICE_ACCOUNT_FILE=/path/to/service-account.json(仅默认账号),或
  22. 配置:参见 配置要点。openclaw channels add --channel googlechat 还接受 --audience-type、--audience、--webhook-path 和 --webhook-url。
  23. 启动网关。Google Chat 会向你的 webhook 路径发送 POST 请求(默认 /googlechat)。

添加到 Google Chat

当网关正在运行,且你的邮箱在可见性列表中时:

  1. 前往 Google Chat。
  2. 点击 直接消息 旁边的 +(加号)图标。
  3. 搜索你在 Google Cloud Console 中配置的 应用名称。
  4. 由于它是私有应用,该机器人不会出现在 Marketplace 浏览列表中。请通过名称搜索它。
  5. 选择该机器人,点击 添加 或 聊天,然后发送一条消息。

公共 URL(仅 Webhook)

Google Chat webhook 需要一个公共 HTTPS 端点。出于安全考虑,仅将 /googlechat 路径 暴露到互联网,并让 OpenClaw 仪表板和其他端点保持私有。

使用 Tailscale Serve 为私有仪表板提供服务,并使用 Funnel 公开 webhook 路径。

  1. 检查你的网关绑定到哪个地址:
# Linux (iproute2):
ss -tlnp | grep 18789

# macOS (no ss):
lsof -iTCP:18789 -sTCP:LISTEN

记下 IP(例如 127.0.0.1、0.0.0.0,或 Tailscale 100.x.x.x 地址)。

  1. 仅将仪表板暴露到 tailnet(端口 8443):
# If bound to localhost (127.0.0.1 or 0.0.0.0):
tailscale serve --bg --https 8443 http://127.0.0.1:18789

# If bound to a Tailscale IP only:
tailscale serve --bg --https 8443 http://100.x.x.x:18789
  1. 仅公开暴露 webhook 路径:
# If bound to localhost (127.0.0.1 or 0.0.0.0):
tailscale funnel --bg --set-path /googlechat http://127.0.0.1:18789/googlechat

# If bound to a Tailscale IP only:
tailscale funnel --bg --set-path /googlechat http://100.x.x.x:18789/googlechat
  1. 如果提示,请访问输出中显示的授权 URL,以为此节点启用 Funnel。

  2. 验证:

tailscale serve status
tailscale funnel status

你的公共 webhook URL 是 https://<node-name>.<tailnet>.ts.net/googlechat。仪表板仍仅通过 tailnet 访问,地址为 https://<node-name>.<tailnet>.ts.net:8443/。在 Google Chat 应用配置中使用公共 URL(不带 :8443)。

注意:此配置在重启后仍会保留。之后可使用 tailscale funnel reset 和 tailscale serve reset 移除。

选项 B:反向代理(Caddy)

仅代理 webhook 路径:

your-domain.com {
    reverse_proxy /googlechat* localhost:18789
}

对 your-domain.com/ 的请求会被忽略或返回 404,而 your-domain.com/googlechat 会路由到 OpenClaw。

选项 C:Cloudflare Tunnel

配置隧道入站规则,仅路由 webhook 路径:

  • 路径:/googlechat -> http://localhost:18789/googlechat
  • 默认规则:HTTP 404(未找到)

工作原理

  1. Google Chat 会向网关的 webhook 路径 POST JSON(仅 POST,要求 JSON 内容类型,按 IP 限流)。
  2. OpenClaw 在分发前对每个请求进行身份验证:
  3. Chat 应用事件携带 Authorization: Bearer <token>。在解析完整请求体之前,会先验证 token。
  4. Google Workspace Add-on 事件在 body 中携带 token(authorizationEventObject.systemIdToken)。OpenClaw 会在验证前以更严格的预认证预算(16 KB、3 秒)读取它们。
  5. token 会根据 audienceType + audience 进行检查:
  6. audienceType: "app-url" → audience 是你的 HTTPS webhook URL。
  7. audienceType: "project-number" → audience 是 Cloud 项目编号。
  8. 在 app-url 下的 Add-on token 还要求将 appPrincipal 设置为应用的数字 OAuth 2.0 client ID(21 位数字,不是邮箱)。否则验证会失败并记录警告。
  9. 消息按空间路由:
  10. 空间会获得按空间划分的会话 agent:<agentId>:googlechat:group:<spaceId>。回复会发送到消息线程。
  11. 默认情况下,DM 会合并到代理的主会话中。设置 session.dmScope 可为每个对等方创建 DM 会话(参见 会话)。
  12. 默认情况下,DM 访问采用配对方式。未知发送者会收到配对码。使用以下命令批准:
  13. openclaw pairing approve googlechat <code>
  14. 群组空间默认要求 @提及。提及会从 Chat 的 USER_MENTION 注释中检测,目标为该应用。如果检测需要应用的用户资源名称,请设置 botUser(例如 users/1234567890)。
  15. 当 exec 或插件审批从 Google Chat 发起,且已配置稳定的 users/<id> 审批人时,OpenClaw 会在源空间或线程中发布原生审批卡片(cardsV2)。卡片按钮携带不透明回调 token。仅当原生投递不可用时,才会出现手动 /approve <id> <decision> prompt。

入站持久性

请求身份验证后,OpenClaw 会从存储中移除附加组件授权对象,并在返回 200 之前将 Google Chat MESSAGE 事件持久化入队。持久化失败会返回 503,使 Google Chat 能够重试,而不是确认一个可能丢失的事件。持久化入队的 200 会携带 x-openclaw-delivery-accepted: durable。非消息操作的确认和错误响应会省略该标记,因此反向代理可以要求该标记,以区分持久化接受和普通的 200。

待处理或可重试的消息会在 Gateway 重启后保留,按 space 保持串行化,并在存在活动或保留的完成记录时,使用 Google Chat 消息资源名称来抑制重复的队列条目。非消息操作保留其现有的分离 webhook 路径,并且不会获得此持久化队列保证。在队列到代理的边界上,投递仍保持至少一次,因此交接期间的崩溃可能会重放一个回合。

目标

使用以下标识符用于投递和允许列表:

  • 直接消息:users/<userId>(推荐)。
  • 空间:spaces/<spaceId>。
  • 原始邮箱 name@example.com 是可变的,仅当 channels.googlechat.dangerouslyAllowNameMatching: true 时用于允许列表匹配。
  • 已弃用:users/<email> 被视为用户 ID,而不是邮箱允许列表条目。
  • 前缀 googlechat:、google-chat: 和 gchat: 会被接受并移除。

配置要点

{
  channels: {
    googlechat: {
      enabled: true,
      serviceAccountFile: "/path/to/service-account.json",
      // or serviceAccount: { source: "file", provider: "filemain", id: "/channels/googlechat/serviceAccount" }
      audienceType: "app-url",
      audience: "https://gateway.example.com/googlechat",
      appPrincipal: "123456789012345678901", // add-on verification only; numeric OAuth client ID
      webhookPath: "/googlechat",
      botUser: "users/1234567890", // optional; helps mention detection
      allowBots: false,
      dmPolicy: "pairing",
      allowFrom: ["users/1234567890"],
      groupPolicy: "allowlist",
      groups: {
        "spaces/AAAA": {
          enabled: true,
          requireMention: true,
          users: ["users/1234567890"],
          systemPrompt: "Short answers only.",
        },
      },
      typingIndicator: "message",
      mediaMaxMb: 20,
    },
  },
}

说明:

  • 服务账号凭据:serviceAccountFile(路径)或 serviceAccount(内联 JSON 字符串、对象,或 env/file/exec/store SecretRef)。环境变量 GOOGLE_CHAT_SERVICE_ACCOUNT(内联 JSON)和 GOOGLE_CHAT_SERVICE_ACCOUNT_FILE(路径)仅适用于默认账号。多账号配置使用 channels.googlechat.accounts.<id>,并使用相同的键,包括每个账号的 serviceAccount SecretRef。
  • 省略的账号 dmPolicy 和 groupPolicy 会继承频道根配置。显式账号策略优先。根配置默认分别为 pairing 和 allowlist。来自 accounts.default 的共享设置优先级低于根配置。其凭据、enabled 和 dangerouslyAllowNameMatching 不会被命名账号继承。
  • 当未设置 webhookPath 时,默认 webhook 路径为 /googlechat。webhookUrl 也可以提供该路径。
  • 群组键必须是稳定的 space ID(spaces/<spaceId>)。显示名称键已弃用,并会记录相应日志。
  • dangerouslyAllowNameMatching 会为允许列表重新启用可变邮箱主体匹配(紧急兼容模式)。Doctor 会对邮箱条目发出警告。
  • Google Chat 反应操作未暴露。该插件使用服务账号身份验证,而 Google Chat 反应端点需要用户身份验证。使用 openclaw doctor --fix 移除不支持的旧版反应设置。
  • 原生审批卡片使用 Google Chat cardsV2 按钮点击,而不是反应事件。审批人来自 allowFrom 或 defaultTo,并且必须是稳定的数字 users/<id> 值。
  • 消息操作仅暴露文本 send。Google Chat 附件上传需要用户身份验证,而此插件使用服务账号身份验证,因此未暴露出站文件上传。
  • typingIndicator:message(默认)会发布 _<Bot> is typing..._ 占位符,并将其编辑为第一条回复。none 会禁用它。reaction 需要用户 OAuth,目前在服务账号身份验证下会回退到 message 并记录错误。
  • OpenClaw 会通过 Chat API 将每条消息的第一个入站附件下载到媒体管道中。mediaMaxMb 限制该下载大小(默认 20)。Google Drive 文件不会被下载。代理会收到一条附件不可用通知,要求改为直接上传文件。其他不支持的附件来源会收到相同的上传指引。包含多个附件的消息会为未处理的额外附件包含一条计数通知。超大附件会保留其大小限制通知。
  • 默认情况下,机器人创建的消息会被忽略。设置 allowBots: true 后,接受的机器人消息会使用共享的机器人循环保护:配置 channels.defaults.botLoopProtection,然后使用 channels.googlechat.botLoopProtection 或 channels.googlechat.groups.<space>.botLoopProtection 进行覆盖。

自定义表情列表不可用,因为 Google Chat 的 customEmojis.list 端点需要使用 chat.customemojis 或 chat.customemojis.readonly 范围进行用户身份验证。此插件仅以服务账号身份进行身份验证,并使用 chat.bot 范围,无法访问该端点。

密钥引用详情:密钥管理。

故障排除

405 方法不允许

如果 Google Cloud Logs Explorer 显示如下错误:

status code: 405, reason phrase: HTTP error response: HTTP/1.1 405 Method Not Allowed

webhook 处理程序未注册。常见原因:

  1. 频道未配置:缺少 channels.googlechat 部分。使用以下命令验证:
openclaw config get channels.googlechat

如果返回 "Config path not found",请添加配置(参见配置要点)。

  1. 插件未启用:检查插件状态:
openclaw plugins list | grep googlechat

如果显示 "disabled",请运行 openclaw plugins enable googlechat,并检查应用结果。

  1. 配置未应用:检查热重载状态和 Gateway 日志。如果 Gateway 处于离线状态,请启动 Gateway。如果你更改了服务环境,请重启 Gateway 以加载该环境。

验证通道正在运行:

openclaw channels status
# Should show: Google Chat default: enabled, configured, ...

其他问题

  • openclaw channels status --probe 会显示认证错误以及缺失的 audience 配置(audience 和 audienceType 均为必需)。
  • 如果没有消息到达,请确认 Chat 应用的 webhook URL 和触发器配置。
  • 如果提及门控阻止回复,请将 botUser 设置为应用的 user resource name,并检查 requireMention。
  • 在发送测试消息时运行 openclaw logs --follow,可查看请求是否到达 Gateway。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw