Files
Cortex-Inara/docs/GOOGLE_CHAT_BOT.md
Scott Idem ddf5dd6338 docs: add Google Chat setup guide, update NC Talk for per-user routing
- 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>
2026-03-29 13:24:36 -04:00

101 lines
4.0 KiB
Markdown

# 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 invite` or `google-add`)
---
## Per-User Setup
### 1. Create the user's `channels.json`
Create `home/{username}/channels.json` on the Cortex server:
```json
{
"google_chat": {
"persona": "inara",
"audience": "https://cortex.dgrzone.com/channels/google-chat/{username}",
"backend": "claude",
"timeout": 25
}
}
```
- **`persona`** — which persona responds (must exist under `home/{username}/persona/`)
- **`audience`** — must exactly match the HTTP endpoint URL you set in Google Cloud Console (Google uses this as the JWT `aud` claim)
- **`backend`** — `"claude"` recommended; Google Chat requires a response within 30s
- **`timeout`** — keep at 25 (Google's hard limit is 30s; this leaves a 5s buffer)
### 2. Configure Google Chat API in Google Cloud Console
1. Go to [console.cloud.google.com](https://console.cloud.google.com) and select the project
2. **APIs & Services → Enabled APIs & services → Google Chat API**
3. Click the **Configuration** tab
4. Fill in **Application info:**
- App name: `Cortex` (or your persona name)
- Avatar URL: optional
- Description: optional
5. Under **Interactive features:**
- Enable **"Join spaces and group conversations"** if you want the bot in group chats, or leave it off for DM-only
6. Under **Connection settings:**
- Select **HTTP endpoint URL**
- Enter: `https://cortex.dgrzone.com/channels/google-chat/{username}`
7. 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
8. Click **Save**
> **Important:** The URL in step 6 must exactly match the `audience` value in `channels.json`. Google includes this URL as the JWT `aud` claim on every request, and Cortex rejects any request where they don't match.
---
## How It Works
1. User sends a message in Google Chat → Google POSTs a signed JSON payload to `/channels/google-chat/{username}`
2. Cortex reads the user's `channels.json`, verifies the JWT `systemIdToken` from `authorizationEventObject`
3. Sets the persona context, builds the system prompt, calls the LLM
4. 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.com`
- `aud` = the value of `audience` in `channels.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 |