- 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>
101 lines
4.0 KiB
Markdown
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 |
|