Files
openclaw-openclaw/docs/channels/googlechat.md
Peter Steinberger f7d7148cf0 docs: rewrite published docs grounded in current source (#100142)
Source-grounded rewrite of 529 published docs pages with per-unit information-loss verification: 1,713 factual corrections cited to src/**, generated surfaces regenerated, frontmatter titles preserved for i18n, release notes pages untouched. All docs gates green.

Closes #100141
2026-07-05 00:32:47 -04:00

12 KiB

summary, read_when, title
summary read_when title
Google Chat app support status, capabilities, and configuration
Working on Google Chat channel features
Google Chat

Google Chat runs as the official @openclaw/googlechat plugin: DMs and spaces through Google Chat API webhooks (HTTP endpoint only, no Pub/Sub).

Install

openclaw plugins install @openclaw/googlechat

Local checkout (when running from a git repo):

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

Quick setup (beginner)

  1. Create a Google Cloud project and enable the Google Chat API.
  2. Create a Service Account:
    • Press Create Credentials > Service Account.
    • Name it whatever you want (e.g., openclaw-chat).
    • Leave permissions and principals blank (Continue, then Done).
  3. Create and download the JSON key:
    • Click the new service account > Keys tab > Add Key > Create new key > JSON > Create.
  4. Store the downloaded JSON file on your gateway host (e.g., ~/.openclaw/googlechat-service-account.json).
  5. Create a Google Chat app in the Google Cloud Console Chat Configuration:
    • Fill in Application info (app name, avatar URL, description).
    • Enable Interactive features.
    • Under Functionality, check Join spaces and group conversations.
    • Under Connection settings, select HTTP endpoint URL.
    • Under Triggers, select Use a common HTTP endpoint URL for all triggers and set it to your public gateway URL followed by /googlechat (see Public URL).
    • Under Visibility, check Make this Chat app available to specific people and groups in <Your Domain> and enter your email address.
    • Click Save.
  6. Enable the app status: refresh the page, find App status, set it to Live - available to users, and Save again.
  7. Configure OpenClaw with the service account and the webhook audience (must match the Chat app config):
    • Env: GOOGLE_CHAT_SERVICE_ACCOUNT_FILE=/path/to/service-account.json (default account only), or
    • Config: see Config highlights. openclaw channels add --channel googlechat also accepts --audience-type, --audience, --webhook-path, and --webhook-url.
  8. Start the gateway. Google Chat will POST to your webhook path (default /googlechat).

Add to Google Chat

Once the gateway is running and your email is on the visibility list:

  1. Go to Google Chat.
  2. Click the + (plus) icon next to Direct Messages.
  3. Search for the App name you configured in the Google Cloud Console.
    • The bot does not appear in the Marketplace browse list because it is a private app; search for it by name.
  4. Select the bot, click Add or Chat, and send a message.

Public URL (Webhook-only)

Google Chat webhooks require a public HTTPS endpoint. For security, expose only the /googlechat path to the internet and keep the OpenClaw dashboard and other endpoints private.

Use Tailscale Serve for the private dashboard and Funnel for the public webhook path.

  1. Check what address your gateway is bound to:

    ss -tlnp | grep 18789
    

    Note the IP (e.g., 127.0.0.1, 0.0.0.0, or a Tailscale 100.x.x.x address).

  2. Expose the dashboard to the tailnet only (port 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
    
  3. Expose only the webhook path publicly:

    # 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
    
  4. If prompted, visit the authorization URL shown in the output to enable Funnel for this node.

  5. Verify:

    tailscale serve status
    tailscale funnel status
    

Your public webhook URL is https://<node-name>.<tailnet>.ts.net/googlechat; the dashboard stays tailnet-only at https://<node-name>.<tailnet>.ts.net:8443/. Use the public URL (without :8443) in the Google Chat app config.

Note: This configuration persists across reboots. Remove it later with tailscale funnel reset and tailscale serve reset.

Option B: Reverse Proxy (Caddy)

Proxy only the webhook path:

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

Requests to your-domain.com/ are ignored or 404, while your-domain.com/googlechat routes to OpenClaw.

Option C: Cloudflare Tunnel

Configure the tunnel ingress rules to route only the webhook path:

  • Path: /googlechat -> http://localhost:18789/googlechat
  • Default rule: HTTP 404 (Not Found)

How it works

  1. Google Chat POSTs JSON to the gateway webhook path (POST only, JSON content type required, per-IP rate limited).
  2. OpenClaw authenticates every request before dispatch:
    • Chat app events carry Authorization: Bearer <token>; the token is verified before the full body is parsed.
    • Google Workspace Add-on events carry the token in the body (authorizationEventObject.systemIdToken) and are read under a stricter pre-auth budget (16 KB, 3 s) before verification.
  3. The token is checked against audienceType + audience:
    • audienceType: "app-url" → audience is your HTTPS webhook URL.
    • audienceType: "project-number" → audience is the Cloud project number.
    • Add-on tokens under app-url additionally require appPrincipal set to the app's numeric OAuth 2.0 client ID (21 digits, not an email); otherwise verification fails with a logged warning.
  4. Messages route by space:
    • Spaces get per-space sessions agent:<agentId>:googlechat:group:<spaceId>; replies go to the message thread.
    • DMs collapse into the agent's main session by default; set session.dmScope for per-peer DM sessions (see Session).
  5. DM access is pairing by default. Unknown senders receive a pairing code; approve with:
    • openclaw pairing approve googlechat <code>
  6. Group spaces require @-mention by default. Mentions are detected from Chat USER_MENTION annotations targeting the app; set botUser (e.g., users/1234567890) if detection needs the app's user resource name.
  7. When an exec or plugin approval starts from Google Chat and a stable users/<id> approver is configured, OpenClaw posts a native approval card (cardsV2) in the originating space or thread. Card buttons carry opaque callback tokens; the manual /approve <id> <decision> prompt appears only when native delivery is unavailable.

Targets

Use these identifiers for delivery and allowlists:

  • Direct messages: users/<userId> (recommended).
  • Spaces: spaces/<spaceId>.
  • Raw email name@example.com is mutable and only used for allowlist matching when channels.googlechat.dangerouslyAllowNameMatching: true.
  • Deprecated: users/<email> is treated as a user id, not an email allowlist entry.
  • Prefixes googlechat:, google-chat:, and gchat: are accepted and stripped.

Config highlights

{
  channels: {
    googlechat: {
      enabled: true,
      serviceAccountFile: "/path/to/service-account.json",
      // or serviceAccountRef: { 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,
      dm: {
        policy: "pairing",
        allowFrom: ["users/1234567890"],
      },
      groupPolicy: "allowlist",
      groups: {
        "spaces/AAAA": {
          enabled: true,
          requireMention: true,
          users: ["users/1234567890"],
          systemPrompt: "Short answers only.",
        },
      },
      actions: { reactions: true },
      typingIndicator: "message",
      mediaMaxMb: 20,
    },
  },
}

Notes:

  • Service account credentials: serviceAccountFile (path), serviceAccount (inline JSON string or object), or serviceAccountRef (env/file SecretRef). Env vars GOOGLE_CHAT_SERVICE_ACCOUNT (inline JSON) and GOOGLE_CHAT_SERVICE_ACCOUNT_FILE (path) apply to the default account only. Multi-account setups use channels.googlechat.accounts.<id> with the same keys, including per-account serviceAccountRef.
  • Default webhook path is /googlechat when webhookPath is unset; webhookUrl can supply the path instead.
  • Group keys must be stable space ids (spaces/<spaceId>). Display-name keys are deprecated and logged as such.
  • dangerouslyAllowNameMatching re-enables mutable email principal matching for allowlists (break-glass compatibility mode); doctor warns about email entries.
  • Reactions are enabled by default and exposed through the reactions tool and channels action; disable with actions.reactions: false.
  • Native approval cards use Google Chat cardsV2 button clicks, not reaction events. Approvers come from dm.allowFrom or defaultTo and must be stable numeric users/<id> values.
  • Message actions expose send for text and upload-file for explicit attachment sends. upload-file accepts media / filePath / path plus optional message, filename, and thread targeting (threadId / replyTo).
  • typingIndicator: message (default) posts a _<Bot> is typing..._ placeholder and edits it into the first reply; none disables it; reaction requires user OAuth and currently falls back to message with a logged error under service-account auth.
  • Inbound attachments (first attachment per message) are downloaded through the Chat API into the media pipeline, capped by mediaMaxMb (default 20).
  • Bot-authored messages are ignored by default. With allowBots: true, accepted bot messages use shared bot loop protection: configure channels.defaults.botLoopProtection, then override with channels.googlechat.botLoopProtection or channels.googlechat.groups.<space>.botLoopProtection.

Secrets reference details: Secrets Management.

Troubleshooting

405 Method Not Allowed

If Google Cloud Logs Explorer shows errors like:

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

The webhook handler is not registered. Common causes:

  1. Channel not configured: the channels.googlechat section is missing. Verify with:

    openclaw config get channels.googlechat
    

    If it returns "Config path not found", add the configuration (see Config highlights).

  2. Plugin not enabled: check plugin status:

    openclaw plugins list | grep googlechat
    

    If it shows "disabled", add plugins.entries.googlechat.enabled: true to your config.

  3. Gateway not restarted after config changes:

    openclaw gateway restart
    

Verify the channel is running:

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

Other issues

  • openclaw channels status --probe surfaces auth errors and missing audience config (audience and audienceType are both required).
  • If no messages arrive, confirm the Chat app's webhook URL and trigger configuration.
  • If mention gating blocks replies, set botUser to the app's user resource name and check requireMention.
  • openclaw logs --follow while sending a test message shows whether requests reach the gateway.