Google Chat Channel Setup
Connect OpenClaw to Google Chat via HTTP webhooks. Unlike WhatsApp (QR pairing) or Signal (CLI linking), Google Chat uses a GCP service account and webhook endpoint — your gateway needs a public HTTPS URL.
Prerequisites
- Phase 1 completed (working agent)
- A Google Workspace domain (Chat apps require Workspace — free Gmail accounts can’t use them)
- Google Workspace admin access (to enable Chat apps at the org level)
- A public HTTPS URL for the webhook endpoint (Tailscale Funnel recommended — see Phase 6 )
- A GCP project with the Google Chat API enabled
Personal Google accounts (gmail.com) can’t use Google Chat apps. This channel requires Google Workspace (Business, Enterprise, Education, etc.).
How It Works
Google Chat → HTTPS POST /googlechat → OpenClaw Gateway → AI Provider → Response → Google ChatGoogle Chat sends webhook POSTs to your gateway. Each request includes an Authorization: Bearer <token> header — an OIDC ID token issued by accounts.google.com (for apps created via the new GCP Console) or a service account JWT signed by chat@system.gserviceaccount.com (legacy). OpenClaw verifies the token against your configured audience before processing.
Key differences from WhatsApp/Signal:
- Webhook-based — requires a publicly reachable HTTPS endpoint (WhatsApp/Signal connect outbound)
- Service account auth — no QR code or CLI linking; uses a GCP service account JSON key
- Audience verification — two modes:
app-url(webhook URL) orproject-number(GCP project number) - Space-based sessions — session keys use
agent:<agentId>:googlechat:direct:<spaceId>oragent:<agentId>:googlechat:group:<spaceId> - Threaded replies — in spaces (group chats), replies are always posted in the thread of the original message. No config option to post top-level instead (OpenClaw limitation — the Google Chat API does support it via
messageReplyOption). - Mention-only in spaces — Google Chat only forwards @mention messages (and slash commands) to HTTP endpoint apps in group spaces. Non-mention messages never reach the webhook — this is a Google Chat platform constraint
, not an OpenClaw limitation.
requireMention: falsein OpenClaw config has no practical effect for spaces since Google never delivers non-mention messages. All-message monitoring would require the separate Workspace Events API + Pub/Sub architecture. DMs always arrive regardless. - Plugin required —
plugins.entries.googlechat.enabled: truemust be set (WhatsApp/Signal also need their plugin enabled)
Step 1: GCP Project Setup
Create service account
- Go to Google Chat API Credentials
- Enable the Google Chat API if not already enabled
- Create Credentials > Service Account
- Name: e.g.,
openclaw-chat - Leave permissions and principals blank
- Name: e.g.,
- In the service account list, click the one you created
- Keys tab > Add Key > Create new key > JSON
- Store the downloaded file on your gateway host:
# Docker isolation (production — macOS; on Linux, replace /Users/openclaw/ with /home/openclaw/)
sudo -u openclaw mkdir -p /Users/openclaw/.openclaw/credentials/googlechat
sudo mv ~/Downloads/openclaw-chat-*.json \
/Users/openclaw/.openclaw/credentials/googlechat/service-account.json
sudo chown openclaw:staff /Users/openclaw/.openclaw/credentials/googlechat/service-account.json
sudo chmod 600 /Users/openclaw/.openclaw/credentials/googlechat/service-account.json
# Quick start (personal user)
mkdir -p ~/.openclaw/credentials/googlechat
mv ~/Downloads/openclaw-chat-*.json ~/.openclaw/credentials/googlechat/service-account.json
chmod 600 ~/.openclaw/credentials/googlechat/service-account.jsonCreate Chat app
- Go to Google Chat Configuration
- Fill in Application info:
- App name: e.g.,
OpenClaw(users search this exact name to find the bot) - Avatar URL: e.g.,
https://openclaw.ai/logo.png - Description: e.g.,
AI Assistant
- App name: e.g.,
- Enable Interactive features
- Under Functionality: check Join spaces and group conversations
- Under Connection settings: select HTTP endpoint URL
- GCP will display a read-only Service Account Email below the radio button (e.g.,
service-205049784124@gcp-sa-gsuiteaddons.iam.gserviceaccount.com). This is Google’s internal signing account and is purely informational — it does not need to be configured in OpenClaw.
- GCP will display a read-only Service Account Email below the radio button (e.g.,
- Under Triggers: select Use a common HTTP endpoint URL for all triggers and set to your gateway’s public webhook URL (e.g.,
https://<node>.ts.net/googlechat) - Under Visibility: check Make this Chat app available to specific people and groups in <Your Domain> and add your email (type it into the text field and press Enter)
- Click Save
- Refresh the page, find App status, set to Live - available to users, and Save again
The bot is a private app. It won’t appear in the Marketplace browse list. Users must search for it by exact name in Google Chat’s “+” menu.
Step 2: Workspace Admin Setup
A Google Workspace administrator must enable Chat apps for the organization:
- Go to admin.google.com > Apps > Google Workspace > Google Chat
- Under Chat apps, ensure they’re enabled for the top-level organizational unit (OU)
- If using sub-OUs, make sure the users who need the bot are in an OU where Chat apps are allowed
No Marketplace publishing required. Internal-only apps with “Specific people and groups” visibility work without Marketplace review.
App installation policies: If the org has a Marketplace allowlist, the OpenClaw Chat app may need to be explicitly allowlisted by the admin — or it can operate under Google’s 5-user development app exemption. Some Chat API features also require top-level OU access to be enabled. Coordinate with the Workspace admin if you encounter installation issues.
Step 3: Webhook Exposure
Google Chat webhooks require a public HTTPS endpoint. Only expose the /googlechat path — keep the dashboard and API on your private network.
Tailscale Funnel (Recommended)
# Expose only the webhook path publicly
tailscale funnel --bg --set-path /googlechat http://127.0.0.1:18789/googlechat
# If gateway is bound to Tailscale IP:
tailscale funnel --bg --set-path /googlechat http://100.x.x.x:18789/googlechat
# Verify
tailscale funnel statusYour public webhook URL: https://<node-name>.<tailnet>.ts.net/googlechat
Keep the dashboard tailnet-only:
tailscale serve --bg --https 8443 http://127.0.0.1:18789This configuration persists across reboots. To remove:
tailscale funnel resetandtailscale serve reset.
Caddy (Alternative)
Only proxy the webhook path:
your-domain.com {
reverse_proxy /googlechat* localhost:18789
}Cloudflare Tunnel (Alternative)
Route only /googlechat → http://localhost:18789/googlechat. Default rule: 404.
Step 4: Gateway Configuration
Single-agent setup (Phase 1)
Add to ~/.openclaw/openclaw.json:
{
"channels": {
"googlechat": {
"enabled": true,
"serviceAccountFile": "~/.openclaw/credentials/googlechat/service-account.json",
"audienceType": "app-url",
"audience": "https://<node-name>.<tailnet>.ts.net/googlechat",
// Required for @mention detection in spaces — see "Finding the bot user ID" below
"botUser": "users/<bot-numeric-id>",
"dm": {
"policy": "pairing",
// Use stable user IDs (users/<id>) once known — email matching is fragile.
// Start with email, then replace after first DM (ID appears in pairing request + session logs).
"allowFrom": ["user@yourdomain.com"]
},
"groupPolicy": "allowlist",
"groups": { "*": { "requireMention": true } },
"mediaMaxMb": 20
}
},
"plugins": {
"entries": {
"googlechat": { "enabled": true }
}
}
}Both
channels.googlechatandplugins.entries.googlechatare required. Missing either causes a 405 error on the webhook endpoint.Start with DMs, add spaces later. You can omit
botUserinitially — DMs work without it. Once you have the bot’s user ID (see below), addbotUserand test spaces.
Multi-agent setup (Phase 4+)
Add a dedicated Google Chat agent alongside the existing WhatsApp/Signal agents:
{
"agents": {
"list": [
// ... existing agents (main, whatsapp, signal, search, googlechat) ...
{
// GOOGLE CHAT AGENT — same pattern as WhatsApp/Signal agents
// No exec/process/web — delegates to search/main.
"id": "googlechat",
"workspace": "/Users/openclaw/.openclaw/workspaces/googlechat",
"agentDir": "/Users/openclaw/.openclaw/agents/googlechat/agent",
"tools": {
"deny": ["web_search", "web_fetch", "browser", "exec", "process"],
"elevated": { "enabled": false }
},
"subagents": { "allowAgents": ["main", "search", "browser"] }
}
]
},
"bindings": [
{ "agentId": "whatsapp", "match": { "channel": "whatsapp" } },
{ "agentId": "signal", "match": { "channel": "signal" } },
{ "agentId": "googlechat", "match": { "channel": "googlechat" } }
]
}The Google Chat agent follows the same pattern as WhatsApp/Signal agents: no web tools, no exec, delegates to search/main via sessions_send. Docker sandbox (from agents.defaults) applies automatically.
Credential resolution order
OpenClaw resolves Google Chat credentials in this order (standard OpenClaw credential resolution):
serviceAccount— inline JSON string in configserviceAccountFile— path to JSON fileGOOGLE_CHAT_SERVICE_ACCOUNT— env var (JSON string)GOOGLE_CHAT_SERVICE_ACCOUNT_FILE— env var (file path)
For production, use serviceAccountFile or the env var — keeps secrets out of openclaw.json.
Config options reference
| Key | Default | Description |
|---|---|---|
enabled | false | Enable the channel |
serviceAccountFile | — | Path to service account JSON key |
audienceType | "app-url" | Token verification mode: "app-url" or "project-number" |
audience | — | Webhook URL or GCP project number (matches audienceType) |
webhookPath | "/googlechat" | HTTP path the gateway registers for incoming webhooks |
botUser | — | App’s user resource name (e.g., "users/1234567890"); helps mention detection |
dm.policy | "pairing" | DM access: "pairing", "allowlist", "open", "disabled" |
dm.allowFrom | [] | Allowed senders: "users/<id>" or "user@domain.com" |
groupPolicy | "allowlist" | Space access: "allowlist", "open", "disabled" |
groups | {} | Per-space config (keys: "spaces/<id>" or "*") |
actions.reactions | false | Enable reactions (requires user OAuth — see known issues) |
typingIndicator | "message" | Typing indicator: "none", "message", "reaction" |
mediaMaxMb | 20 | Max attachment size in MB |
dangerouslyAllowNameMatching | false | Allow email/name matching in dm.allowFrom — use only until you have the user’s stable sender ID from logs |
Step 5: Verify
Start/restart the gateway:
openclaw start # Foreground (development) # or restart the LaunchAgent/systemd service (production)Check channel status:
openclaw channels status # Should show: Google Chat default: enabled, configured, ...Add the bot in Google Chat:
- Open Google Chat
- Click + next to Direct Messages
- Search for your app name (exact match required — it’s a private app)
- Select and click Add or Chat
- Send “Hello”
Approve pairing (if using
pairingDM policy):openclaw pairing list googlechat openclaw pairing approve googlechat <CODE>Run diagnostics:
openclaw doctor # Config issues openclaw status --deep # Full health check including channel probe + security auditHarden
dm.allowFrom: After the first DM, replace email with the stable user ID:# Find sender ID in session store cat ~/.openclaw/agents/main/sessions/sessions.json | python3 -m json.tool | grep -A2 '"from"' # Output: "from": "googlechat:users/111261968043283685958" # Use the users/<id> part in allowFrom, then remove dangerouslyAllowNameMatching if set
Finding the bot user ID
botUser is required for @mention detection in spaces (#25639
). The bot’s numeric user ID is not visible in the GCP Console or gateway logs. To find it, send a message as the bot via the Google Chat API and read sender.name from the response:
# One-time setup (use a Python venv to avoid system package conflicts)
python3 -m venv /tmp/gapi && /tmp/gapi/bin/pip install -q google-auth google-api-python-client
# Get bot user ID (replace the space ID with any space the bot is in)
/tmp/gapi/bin/python3 -c "
from google.oauth2 import service_account
from googleapiclient.discovery import build
creds = service_account.Credentials.from_service_account_file(
'$HOME/.openclaw/credentials/googlechat/service-account.json',
scopes=['https://www.googleapis.com/auth/chat.bot'])
service = build('chat', 'v1', credentials=creds)
# Send a message to any DM space, read sender.name, then delete it
spaces = service.spaces().list(pageSize=1).execute()
space = spaces['spaces'][0]['name']
msg = service.spaces().messages().create(parent=space, body={'text': '(bot identity probe)'}).execute()
print(f'botUser: {msg[\"sender\"][\"name\"]}')
service.spaces().messages().delete(name=msg['name']).execute()
"
# Output: botUser: users/104817664214523572409
# Add this to channels.googlechat.botUser in your configKnown Issues
| Issue | Impact | Status |
|---|---|---|
| OIDC token 401 regression (#35095 ) — affects 2026.3.2–2026.3.7 | The new GCP Console creates Chat apps that issue Google ID tokens (iss: accounts.google.com, signed by /oauth2/v3/certs) instead of service account JWTs (iss: chat@system.gserviceaccount.com). OpenClaw 2026.3.2–2026.3.7 verifies against the wrong key set, returning 401 for every webhook. Fixed in #35204
— upgrade to 2026.3.8+. With the fix, audienceType: "app-url" with the webhook URL is correct. | Fixed in 2026.3.8 |
@mention detection fails without botUser (#25639
) | In spaces with requireMention: true, @mentions are silently dropped because OpenClaw checks for users/app alias but Google Chat sends the bot’s numeric user ID. Workaround: set botUser: "users/<numeric-id>" in channels.googlechat config. Get the bot’s user ID via the Google Chat API (spaces.messages.create response includes sender.name). | Open |
requireMention: false broken (#29855
) | requireMention: false has no effect in spaces — messages are still ignored unless @mentioned. Fix merged in PR #29917 but may not be released yet. Note: even when fixed, this only affects OpenClaw’s filter — Google Chat only forwards @mention messages
to HTTP endpoint apps in spaces, so non-mention messages never arrive regardless. | Open (fix merged) |
| No all-message reception in spaces (#44347 ) | HTTP endpoint apps only receive @mention/DM messages from Google Chat — this is a platform constraint . Receiving all space messages would require the Workspace Events API + Pub/Sub architecture (not supported by OpenClaw). | Open |
| OAuth limitations (#9764 ) | Service account auth can’t do reactions, media uploads, or proactive DMs. These require user OAuth (not yet supported). | Open |
| Per-space rate limit | 1 write/sec (60/min standard). The 600/min figure in some docs applies only to data import operations. | By design |
Multi-Organization Setup
Google Chat apps are scoped to a single Workspace domain. To serve multiple organizations, create a separate GCP project and Chat app per domain.
Architecture
GCP Project A (org-a.com) GCP Project B (org-b.com)
└── Chat App "OpenClaw" └── Chat App "OpenClaw"
│ │
└──────────────┐ ┌──────────────────┘
▼ ▼
Same OpenClaw Gateway
(shared webhook endpoint)Both Chat apps point to the same gateway webhook URL. OpenClaw routes by space ID, not by GCP project — sessions are naturally isolated per space.
Per-org setup
For each organization:
- Create a GCP project in that org’s Google Cloud console
- Create service account + Chat app (repeat Step 1 )
- Workspace admin enables Chat apps (repeat Step 2 )
- Store each org’s service account key separately:
~/.openclaw/credentials/googlechat/ ├── org-a-service-account.json └── org-b-service-account.json
Current limitations
OpenClaw’s channels.googlechat config supports a single service account. For multi-org with different service accounts:
- Single org active at a time: Switch
serviceAccountFilebetween orgs (not practical for simultaneous use) - Separate gateway instances: Run one gateway per org, each with its own service account and port. See Multi-Gateway Deployments for setup options.
- Shared service account: If both orgs trust the same GCP project, a single service account works — but this requires cross-org GCP access.
Monitor OpenClaw docs for native multi-tenant Google Chat support.
Security Considerations
Webhook authentication
Google Chat signs every webhook POST with a bearer token. OpenClaw verifies this automatically using audienceType + audience. Two modes:
audienceType | audience value | When to use |
|---|---|---|
app-url | Your webhook URL (e.g., https://node.ts.net/googlechat) | Default — matches the URL Google sends to |
project-number | GCP project number (e.g., 123456789) | If your URL changes frequently |
Service account key security
The JSON key file grants identity to your Chat app. Protect it:
sudo chmod 600 ~/.openclaw/credentials/googlechat/service-account.jsonFor production, prefer the env var approach:
# In LaunchAgent plist or systemd env file:
GOOGLE_CHAT_SERVICE_ACCOUNT_FILE=/Users/openclaw/.openclaw/credentials/googlechat/service-account.jsonPublic endpoint hardening
- Only expose
/googlechat— never expose the full gateway - Tailscale Funnel keeps the rest of your gateway private
- Caddy/Cloudflare can add rate limiting at the reverse proxy layer
- Google Chat’s own bearer token authentication prevents unauthorized POSTs
- If using a custom reverse proxy (not Tailscale Funnel), strip
Tailscale-User-LoginandTailscale-User-Nameheaders — see Reverse Proxy Configuration
Channel-guard compatibility
The channel-guard plugin
scans inbound channel messages for prompt injection. Google Chat messages flow through the same message_received hook as WhatsApp/Signal — channel-guard works with Google Chat if the channel bridge is configured.
Troubleshooting
405 Method Not Allowed
Google Cloud Logs shows status code: 405:
Channel not configured — verify:
openclaw config get channels.googlechatIf “Config path not found”, add the channel configuration.
Plugin not enabled — verify:
openclaw plugins list | grep googlechatIf “disabled”, add
plugins.entries.googlechat.enabled: trueto config.Gateway not restarted after adding config:
openclaw gateway restart # Development # or restart LaunchAgent/systemd # Production
No messages arriving
- Verify the Chat app’s webhook URL matches your public URL exactly
- Check
openclaw channels status --probefor auth errors or missing audience - Confirm the Chat app status is Live (not Draft) in GCP Console
- Run
openclaw logs --follow | grep -E '(googlechat|error|webhook)'while sending a test message to filter for Google Chat activity
Mention gating blocks replies in spaces
@mention messages arrive at the gateway but are silently dropped as “mention required” (#25639
). This happens because OpenClaw checks for the users/app alias, but Google Chat sends the bot’s numeric user ID in message annotations.
Fix: Set botUser to the bot’s numeric user resource name (see Finding the bot user ID
):
{
"channels": {
"googlechat": {
"botUser": "users/104817664214523572409"
}
}
}Diagnosis: Check openclaw logs --follow for "drop group message (mention required)" entries — if you see these when @mentioning the bot, botUser is missing or wrong.
401 Unauthorized on every message (new GCP Console setup)
If every message returns 401 despite audience matching the webhook URL exactly, you are likely hitting the OIDC token regression (#35095
) that affects 2026.3.2 when the app was created via the new GCP Console.
To confirm: temporarily capture an incoming webhook request and decode the JWT’s iss claim. If iss is "https://accounts.google.com" (not "chat@system.gserviceaccount.com"), your app issues OIDC ID tokens. Upgrade to OpenClaw 2026.3.8+ (fix shipped in #35204
).
Auth errors
- “audience mismatch” — your
audienceconfig doesn’t match the webhook URL in GCP Console - “token verification failed” — wrong service account file or the Chat API isn’t enabled
- Run
openclaw status --deepfor detailed channel health diagnostics
Next Steps
→ Phase 3: Security — apply security baseline to your Google Chat deployment
Or:
- Phase 4: Channels & Multi-Agent — add a dedicated Google Chat agent
- Phase 5: Web Search Isolation — safe internet access for your agent
- Phase 6: Deployment — production service with webhook exposure
- Reference — config cheat sheet, gotchas