- docs/GOOGLE_CHAT_BOT.md: new step-by-step guide covering channels.json,
Google Cloud Console config, JWT audience, and troubleshooting
- docs/NEXTCLOUD_TALK_BOT.md: updated for per-user endpoints
(/webhook/nextcloud/{username}), channels.json config, removed old
server-level .env references, updated Multi-User note
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.0 KiB
Google Chat Bot Integration
Cortex connects to Google Chat as a Workspace Add-on — each Cortex user gets their own webhook endpoint routed to their chosen persona.
Status: Live and confirmed working (2026-03-27)
Prerequisites
- A Google Cloud project with Google Chat API enabled
- The Cortex server reachable at a public HTTPS URL
- The user pre-registered in Cortex (
manage_passwords.py inviteorgoogle-add)
Per-User Setup
1. Create the user's channels.json
Create home/{username}/channels.json on the Cortex server:
{
"google_chat": {
"persona": "inara",
"audience": "https://cortex.dgrzone.com/channels/google-chat/{username}",
"backend": "claude",
"timeout": 25
}
}
persona— which persona responds (must exist underhome/{username}/persona/)audience— must exactly match the HTTP endpoint URL you set in Google Cloud Console (Google uses this as the JWTaudclaim)backend—"claude"recommended; Google Chat requires a response within 30stimeout— keep at 25 (Google's hard limit is 30s; this leaves a 5s buffer)
2. Configure Google Chat API in Google Cloud Console
- Go to console.cloud.google.com and select the project
- APIs & Services → Enabled APIs & services → Google Chat API
- Click the Configuration tab
- Fill in Application info:
- App name:
Cortex(or your persona name) - Avatar URL: optional
- Description: optional
- App name:
- Under Interactive features:
- Enable "Join spaces and group conversations" if you want the bot in group chats, or leave it off for DM-only
- Under Connection settings:
- Select HTTP endpoint URL
- Enter:
https://cortex.dgrzone.com/channels/google-chat/{username}
- Under Visibility:
- Add the specific Google accounts that should be able to use this bot
- For One Sky IT Workspace users: add individuals or the whole domain
- Click Save
Important: The URL in step 6 must exactly match the
audiencevalue inchannels.json. Google includes this URL as the JWTaudclaim on every request, and Cortex rejects any request where they don't match.
How It Works
- User sends a message in Google Chat → Google POSTs a signed JSON payload to
/channels/google-chat/{username} - Cortex reads the user's
channels.json, verifies the JWTsystemIdTokenfromauthorizationEventObject - Sets the persona context, builds the system prompt, calls the LLM
- Returns the response wrapped in
hostAppDataAction → chatDataAction → createMessageAction
The response must be returned synchronously (Google Chat does not support async/background replies like NC Talk does). The 25s timeout is a hard constraint.
JWT Verification
Google Chat Workspace Add-ons send a systemIdToken in the request body at:
body["authorizationEventObject"]["systemIdToken"]
Claims verified by Cortex:
iss=https://accounts.google.comaud= the value ofaudienceinchannels.json
If audience is empty, verification is skipped (useful for local testing, never in production).
Nginx
The /channels/ prefix is already public in auth_middleware.py — no Nginx changes needed if you're already proxying all traffic to Cortex. Verify the path isn't blocked by basic auth or IP restrictions.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| 404 on the webhook | channels.json missing or no google_chat key |
Create/check home/{username}/channels.json |
| 401 Invalid token | audience in channels.json doesn't match the endpoint URL |
Make them identical — copy the URL exactly |
| 401 Missing token | No systemIdToken in request |
Bot may not be a Workspace Add-on; check connection settings type |
| Timeout / no response | LLM too slow | backend: "claude" recommended; reduce context tier if needed |
| Bot not receiving messages | Visibility not configured | Add the user's Google account under Visibility in Cloud Console |