Google Chat Integration: Plugin Setup and Configuration
This page covers the official Google Chat plugin for OpenClaw, including installation and configuration steps. It is intended for users who need to connect Google Chat spaces and DMs via webhooks.
Read this when
- Working on Google Chat channel features
Google Chat is available as the official @openclaw/googlechat plugin. It handles 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)
- Create a Google Cloud project and enable the Google Chat API.
- Go to: Google Chat API Credentials
- Enable the API if it is not already enabled.
- Create a Service Account:
- Click Create Credentials > Service Account.
- Give it any name (for example,
openclaw-chat). - Leave permissions and principals empty (Continue, then Done).
- Create and download the JSON key:
- Select the new service account > Keys tab > Add Key > Create new key > JSON > Create.
- Save the downloaded JSON file on your gateway host (for example,
~/.openclaw/googlechat-service-account.json). - Create a Google Chat app in the Google Cloud Console Chat Configuration:
- Fill in Application info (app name, avatar URL, description).
- Turn on Interactive features.
- Under Functionality, check Join spaces and group conversations.
- Under Connection settings, choose HTTP endpoint URL.
- Under Triggers, choose 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.
- Enable the app status: refresh the page, find App status, set it to Live - available to users, and Save again.
- 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 googlechatalso accepts--audience-type,--audience,--webhook-path, and--webhook-url.
- Env:
- 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:
- Go to Google Chat.
- Click the + (plus) icon next to Direct Messages.
- 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.
- 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.
Option A: Tailscale Funnel (Recommended)
Use Tailscale Serve for the private dashboard and Funnel for the public webhook path.
-
Check what address your gateway is bound to:
ss -tlnp | grep 18789Note the IP (for example,
127.0.0.1,0.0.0.0, or a Tailscale100.x.x.xaddress). -
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 -
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 -
If prompted, visit the authorization URL shown in the output to enable Funnel for this node.
-
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 resetandtailscale 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 return 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
- Google Chat POSTs JSON to the gateway webhook path (POST only, JSON content type required, per-IP rate limited).
- 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.
- Chat app events carry
- 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-urladditionally requireappPrincipalset to the app's numeric OAuth 2.0 client ID (21 digits, not an email); otherwise verification fails with a logged warning.
- 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.dmScopefor per-peer DM sessions (see Session).
- Spaces get per-space sessions
- DM access is pairing by default. Unknown senders receive a pairing code; approve with:
openclaw pairing approve googlechat <code>
- Group spaces require @-mention by default. Mentions are detected from Chat
USER_MENTIONannotations targeting the app; setbotUser(for example,users/1234567890) if detection needs the app's user resource name. - 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.
Inbound durability
After request authentication, OpenClaw removes the add-on authorization object from storage and durably queues Google Chat MESSAGE events before returning 200. A persistence failure returns 503, allowing Google Chat to retry instead of acknowledging an event that could be lost.
Pending or retryable messages survive a Gateway restart, remain serialized per space, and use the Google Chat message resource name to suppress duplicate queue entries while the active or retained completion record exists. Non-message actions keep their existing detached webhook path and do not receive this durable-queue guarantee. Delivery remains at least once across the queue-to-agent boundary, so a crash during handoff can replay a turn.
Targets
Use these identifiers for delivery and allowlists:
- Direct messages:
users/<userId>(recommended). - Spaces:
spaces/<spaceId>. - Raw email
name@example.comis mutable and only used for allowlist matching whenchannels.googlechat.dangerouslyAllowNameMatching: true. - Deprecated:
users/<email>is treated as a user id, not an email allowlist entry. - Prefixes
googlechat:,google-chat:, andgchat: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,
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,
},
},
}
Notes:
- Service account credentials:
serviceAccountFile(path),serviceAccount(inline JSON string or object), orserviceAccountRef(env/file SecretRef). Env varsGOOGLE_CHAT_SERVICE_ACCOUNT(inline JSON) andGOOGLE_CHAT_SERVICE_ACCOUNT_FILE(path) apply to the default account only. Multi-account setups usechannels.googlechat.accounts.<id>with the same keys, including per-accountserviceAccountRef. - Default webhook path is
/googlechatwhenwebhookPathis unset;webhookUrlcan supply the path instead. - Group keys must be stable space ids (
spaces/<spaceId>). Display-name keys are deprecated and logged as such. dangerouslyAllowNameMatchingre-enables mutable email principal matching for allowlists (break-glass compatibility mode); doctor warns about email entries.- Google Chat reaction actions are not exposed. The plugin uses service-account authentication, while Google Chat reaction endpoints require user authentication. Existing
actions.reactionsconfig is accepted for compatibility but has no effect. - Native approval cards use Google Chat
cardsV2button clicks, not reaction events. Approvers come fromallowFromordefaultToand must be stable numericusers/<id>values. - Message actions expose text
sendonly. Google Chat attachment upload requires user authentication, while this plugin uses service-account authentication, so outbound file upload is not exposed. typingIndicator:message(default) posts a_<Bot> is typing..._placeholder and edits it into the first reply;nonedisables it;reactionrequires user OAuth and currently falls back tomessagewith 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: configurechannels.defaults.botLoopProtection, then override withchannels.googlechat.botLoopProtectionorchannels.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:
-
Channel not configured: the
channels.googlechatsection is missing. Verify with:openclaw config get channels.googlechatIf it returns "Config path not found", add the configuration (see Config highlights).
-
Plugin not enabled: check plugin status:
openclaw plugins list | grep googlechatIf it shows "disabled", add
plugins.entries.googlechat.enabled: trueto your config. -
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 --probesurfaces auth errors and missing audience config (audienceandaudienceTypeare both required).- If no messages arrive, confirm the Chat app's webhook URL and trigger configuration.
- If mention gating blocks replies, set
botUserto the app's user resource name and checkrequireMention. openclaw logs --followwhile sending a test message shows whether requests reach the gateway.
Related
- Channels Overview, all supported channels
- Channel Routing, session routing for messages
- Gateway configuration
- Groups, group chat behavior and mention gating
- Pairing, DM authentication and pairing flow
- Security, access model and hardening