From 2ed59c03343a048edc8eb66bbd506b91a1d9a667 Mon Sep 17 00:00:00 2001 From: highperfocused Date: Thu, 12 Mar 2026 14:44:01 +0100 Subject: [PATCH] docs: add channel integration guide --- README.md | 2 + docs/README.md | 1 + docs/channels.md | 231 +++++++++++++++++++++++++++++++++++++++++++++++ docs/gateway.md | 2 + 4 files changed, 236 insertions(+) create mode 100644 docs/channels.md diff --git a/README.md b/README.md index 8ec8602..5fe6fc2 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ You can also keep one-shot mode (`RUN_MODE=single`) for script usage. - Gateway internals: `docs/gateway.md` - Web UI internals: `docs/web-ui.md` +- Channel integrations (Web UI, Slack, Matrix, custom): `docs/channels.md` --- @@ -135,3 +136,4 @@ The gateway is transport-agnostic. For each upstream client, map its thread iden Then post messages to `/v1/chat` or `/v1/chat/stream` with that `conversationId`. This keeps one agent session per thread across transports. +For detailed setup guidance per transport, see `docs/channels.md`. diff --git a/docs/README.md b/docs/README.md index 868deb2..6f1b798 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,3 +2,4 @@ - [Gateway: how it works](./gateway.md) - [Web UI: how it works](./web-ui.md) +- [Channels: Web UI, Slack, Matrix, custom adapters](./channels.md) diff --git a/docs/channels.md b/docs/channels.md new file mode 100644 index 0000000..6a0bb02 --- /dev/null +++ b/docs/channels.md @@ -0,0 +1,231 @@ +# Channels: Web UI, Slack, Matrix, and custom adapters + +This document explains how **channels** work in the gateway and how to integrate transports like Web UI, Slack, Matrix, or your own chat source. + +--- + +## What is a "channel" in this project? + +In this gateway, a channel is not a separate server object you provision. + +A channel is simply an upstream conversation context (for example: a Slack thread, a Matrix room thread, or a browser chat tab) that maps to one stable `conversationId`. + +The gateway uses that `conversationId` to keep one long-lived agent session. + +--- + +## How channels are represented internally + +You have two integration options: + +1. **Direct chat endpoints** + - `POST /v1/chat` + - `POST /v1/chat/stream` + - You provide `conversationId` directly. + +2. **Adapter endpoints** (recommended for Slack/Matrix/etc.) + - `POST /v1/adapters/chat` + - `POST /v1/adapters/chat/stream` + - You provide channel/thread fields; the gateway derives `conversationId` for you. + +Adapter ID format: + +- `conversationId = source:workspaceId:channelId:threadId` +- `adapterKey = source:workspaceId:channelId:threadId:userId` + +Field behavior on adapter routes: + +- `source` (optional, default: `generic`) +- `workspaceId` (optional, default: `default`) +- `channelId` (**required**) +- `threadId` (optional, default: `root`) +- `userId` (optional, default: `anonymous`) + +Important constraints: + +- segment values must be strings +- `channelId` must not be empty +- segment values must not contain `:` + +If your upstream IDs contain `:` (common in Matrix), sanitize/encode them before sending to adapter routes. + +--- + +## Do I need to "create" a channel first? + +Usually: **no**. + +A conversation/session is auto-created on first message. You can optionally pre-create one via: + +- `POST /v1/conversations` + +But for most channel integrations, you just start sending messages to chat endpoints with stable IDs. + +--- + +## Requirements checklist (all channels) + +1. Gateway is running (`RUN_MODE=gateway`) +2. Model/provider credentials are configured (`PROVIDER`, `MODEL`, `API_KEY` or provider-specific key) +3. Your adapter/client can reach the gateway URL +4. If `GATEWAY_AUTH_TOKEN` is set, send `Authorization: Bearer ` +5. For browser apps on another origin, set `GATEWAY_CORS_ORIGIN` +6. If you want restart-safe sessions, set `SESSION_PERSIST=true` + +--- + +## Web UI channel + +### Built-in UI + +The built-in UI is available at `GET /` when: + +- `GATEWAY_ENABLE_WEB_UI=true` + +How it works: + +- sends messages to `/v1/chat/stream` +- stores `conversationId` in browser local storage +- "New session" clears local `conversationId` and starts a new thread + +### Custom web app + +If you build your own web frontend, call `/v1/chat` or `/v1/chat/stream` and choose your own ID format, e.g.: + +- `web::` + +Example: + +```json +{ + "conversationId": "web:user-42:chat-main", + "message": "Summarize the last response" +} +``` + +--- + +## Slack channel integration + +There is no built-in Slack bot in this repository; you run a small Slack adapter service. + +Typical adapter needs: + +- Slack bot token + app configuration (events/interactions) +- webhook/event receiver in your adapter +- code that forwards messages to gateway and posts replies back to Slack + +Recommended mapping from Slack event payload: + +- `source`: `"slack"` +- `workspaceId`: Slack team/workspace ID (e.g. `T123`) +- `channelId`: Slack channel ID (e.g. `C456`) **required** +- `threadId`: Slack `thread_ts` (or fallback strategy) +- `userId`: Slack user ID (e.g. `U789`) + +Example request to gateway: + +```bash +curl -N -X POST http://localhost:8787/v1/adapters/chat/stream \ + -H 'content-type: application/json' \ + -d '{ + "source": "slack", + "workspaceId": "T123", + "channelId": "C456", + "threadId": "1712233.991", + "userId": "U789", + "message": "Please summarize this thread" + }' +``` + +Threading strategy tip: + +- use a stable `threadId` per Slack thread to keep context isolated per thread +- if you omit `threadId`, gateway uses `root` (all messages for that channel collapse into one thread context) + +--- + +## Matrix channel integration + +There is no built-in Matrix bot in this repository; use a Matrix bot/bridge process as adapter. + +Typical adapter needs: + +- Matrix bot account + access token +- event listener for room messages +- logic to send assistant output back into room/thread + +Recommended mapping: + +- `source`: `"matrix"` +- `workspaceId`: homeserver or deployment identifier (optional but useful) +- `channelId`: Matrix `room_id` (**required**, encoded/sanitized for adapter route) +- `threadId`: Matrix thread root event ID (encoded/sanitized, or omit for `root`) +- `userId`: Matrix sender ID (encoded/sanitized) + +Because adapter segments cannot contain `:`, Matrix IDs should be encoded in the adapter, e.g.: + +```ts +const encodeSegment = (value: string) => encodeURIComponent(value); +``` + +Example payload (encoded values): + +```json +{ + "source": "matrix", + "workspaceId": "matrix.org", + "channelId": "%21roomid%3Amatrix.org", + "threadId": "%24rootEventId%3Amatrix.org", + "userId": "%40alice%3Amatrix.org", + "message": "What did we decide in this thread?" +} +``` + +Alternative: call `/v1/chat` directly and provide your own `conversationId` format if you do not want per-segment adapter normalization. + +--- + +## Custom channel template (Discord, Telegram, email, etc.) + +For any source, map your upstream identifiers into adapter fields and keep that mapping stable. + +Minimal payload: + +```json +{ + "channelId": "your-channel-id", + "message": "Hello" +} +``` + +Full payload template: + +```json +{ + "source": "custom", + "workspaceId": "tenant-a", + "channelId": "channel-123", + "threadId": "thread-456", + "userId": "user-789", + "message": "Hello" +} +``` + +--- + +## Best practices + +- Keep `threadId` stable per thread (do not generate random values per message) +- Include `userId` for audit/telemetry (`adapterKey`) even though it does not change `conversationId` +- Avoid `:` in any adapter segment value +- Use streaming endpoints for better UX (`/stream`) +- Persist sessions in production (`SESSION_PERSIST=true`) +- Add retry/backoff logic in your adapter for network failures + +--- + +## Related docs + +- Gateway internals/API: `docs/gateway.md` +- Built-in browser UI: `docs/web-ui.md` diff --git a/docs/gateway.md b/docs/gateway.md index 863e274..49681e8 100644 --- a/docs/gateway.md +++ b/docs/gateway.md @@ -139,6 +139,8 @@ Adapter request fields (`source`, `workspaceId`, `channelId`, `threadId`, `userI `channelId` is required. `:` is not allowed inside segment values. +For practical setup patterns per transport (Web UI, Slack, Matrix, custom), see `docs/channels.md`. + --- ## Streaming (SSE) behavior