# Channel Connection Guide

## Soika Channel Connection Guide

Complete reference for connecting messaging channels to your Soika AI agents.

### Table of Contents

* Overview
* Channel Status Matrix
* WhatsApp QR (Neonize)
* WhatsApp Business (Cloud API)
* Telegram
* Slack
* Discord
* LINE
* Microsoft Teams
* Signal
* Matrix
* WeChat
* IRC
* Gmail Pub/Sub
* Custom Webhook
* Troubleshooting

### Overview

Soika channels connect external messaging platforms to your AI agents. The flow is:

```
User Message → Platform → Webhook → Soika Backend → AI Agent → Response → Platform → User
```

#### General Steps (All Channels)

1. **Create a channel** in Soika Desktop App → Channels → Add Channel
2. **Select the channel type** and fill in the required credentials
3. **Test Connection** to verify credentials are valid
4. **Create the channel** — Soika auto-generates a webhook URL
5. **Bind an agent** — Go to your agent's settings and enable the channel
6. **Configure the platform** — Set the webhook URL in the platform's settings (if required)

#### Webhook URL Format

All webhook endpoints follow this pattern:

```
http://<YOUR_SERVER>:5001/console/api/webhook/<channel_type>/<channel_id>
```

The `<channel_id>` is a UUID assigned when you create the channel (visible in the channel list).

### Channel Status Matrix

| Channel           | Test Connection | Webhook Handler | Auto-Reply        | Status              |
| ----------------- | --------------- | --------------- | ----------------- | ------------------- |
| WhatsApp QR       | ✅               | ✅ (subprocess)  | ✅ Text + Media    | **Fully Working**   |
| WhatsApp Business | ✅               | ⚠️ Legacy       | ⚠️ Limited        | **Needs Migration** |
| Telegram          | ✅               | ✅               | ✅ Text            | **Fully Working**   |
| Slack             | ✅               | ✅               | ✅ Text (threaded) | **Fully Working**   |
| LINE              | ✅               | ✅               | ✅ Text            | **Fully Working**   |
| MS Teams          | ✅               | ✅               | ✅ Text            | **Fully Working**   |
| Custom Webhook    | ✅               | ✅               | ✅ Text (sync)     | **Fully Working**   |
| Discord           | ✅               | ✅ (subprocess)  | ✅ Text            | **Fully Working**   |
| Signal            | ✅               | ✅               | ✅ Text            | **Fully Working**   |
| Matrix            | ✅               | ✅ (subprocess)  | ✅ Text            | **Fully Working**   |
| WeChat            | ✅               | ✅               | ✅ Text            | **Fully Working**   |
| IRC               | ✅               | ✅ (subprocess)  | ✅ Text            | **Fully Working**   |
| Gmail Pub/Sub     | ✅               | ✅               | ✅ Text (email)    | **Fully Working**   |

### WhatsApp QR (Neonize)

Connect via WhatsApp Web QR code scanning. Supports group chats with text, images, video, audio, and files.

#### Prerequisites

* neonize library installed in the backend
* ffmpeg installed (for video transcoding)
* A phone with WhatsApp

#### Setup Steps

1. **Create Channel**: Select "WhatsApp QR" → enter your phone number → Create
2. **Connect**: Click the "Connect" button on the channel card
3. **Scan QR Code**: A QR code appears in the dialog — scan it with WhatsApp on your phone (Linked Devices → Link a Device)
4. **Select Group**: After connecting, select the WhatsApp group where the bot should respond
5. **Bind Agent**: Assign an AI agent to this channel

#### How It Works

* A background subprocess (neonize worker) connects to WhatsApp Web
* Messages from the selected group are forwarded to the Soika backend internally
* Agent responses are sent back to the group as document attachments (for media) or text
* Video files are auto-transcoded with ffmpeg for size optimization

#### Config Fields

| Field          | Required | Description                                                 |
| -------------- | -------- | ----------------------------------------------------------- |
| `phone_number` | Yes      | WhatsApp phone number with country code (e.g., +1234567890) |

#### Limitations

* One phone connection per channel
* Group chats only (not individual chats)
* Videos sent as document attachments (WhatsApp Web API limitation)

### WhatsApp Business (Cloud API)

Connect via the official Meta WhatsApp Business Cloud API.

#### Prerequisites

* Meta Business account
* WhatsApp Business API access
* A registered phone number on WhatsApp Business Platform

#### Setup Steps

1. Go to [Meta Developer Portal](https://developers.facebook.com/)
2. Create an app → select "Business" type
3. Add WhatsApp product to your app
4. Go to **WhatsApp → API Setup**:
   * Copy the **Phone Number ID**
   * Copy the **Permanent Access Token** (or generate one)
5. **Create Channel** in Soika: Select "WhatsApp Business" → enter credentials → Create
6. **Configure Webhook** in Meta Developer Portal:
   * Go to WhatsApp → Configuration → Webhook
   * Set Callback URL: `http://<SERVER>:5001/console/api/webhook/whatsapp`
   * Set Verify Token: match what you entered in Soika (or use default)
   * Subscribe to: `messages`

#### Config Fields

| Field             | Required | Description                                          |
| ----------------- | -------- | ---------------------------------------------------- |
| `phone_number_id` | Yes      | From Meta Developer Portal → WhatsApp → API Setup    |
| `access_token`    | Yes      | Permanent token from Meta Developer Portal           |
| `waba_id`         | No       | WhatsApp Business Account ID                         |
| `verify_token`    | No       | Webhook verification token (auto-generated if blank) |

#### Note

> The WhatsApp Business webhook handler currently uses a legacy architecture. For reliable operation, use **WhatsApp QR** instead.

### Telegram

Connect a Telegram bot to receive and respond to messages.

#### Prerequisites

* A Telegram account
* A bot created via @BotFather

#### Setup Steps

1. **Create Telegram Bot**:
   * Open Telegram → search for `@BotFather`
   * Send `/newbot` and follow the prompts
   * Copy the **Bot Token** (looks like `123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11`)
2. **Create Channel** in Soika:
   * Select "Telegram" → paste the Bot Token → Create
   * The webhook URL is auto-registered with Telegram
3. **Bind Agent**: Assign your AI agent to this channel
4. **Start chatting**: Find your bot on Telegram and send it a message!

#### Config Fields

| Field         | Required | Description                                                  |
| ------------- | -------- | ------------------------------------------------------------ |
| `bot_token`   | Yes      | From @BotFather (e.g., `123456:ABC-DEF1234...`)              |
| `webhook_url` | No       | Auto-generated. Override only if using a custom proxy/tunnel |

#### How It Works

* Soika auto-registers the webhook URL with Telegram on channel creation
* Telegram pushes all messages to Soika
* Agent responses are sent back via Telegram Bot API with Markdown formatting
* Long messages are automatically split to fit Telegram's 4096 char limit

#### Limitations

* Text messages only (photos, voice, stickers are silently skipped)

### Slack

Connect a Slack app to receive messages and reply in threads.

#### Prerequisites

* A Slack workspace (you need admin/app-install permissions)

#### Setup Steps

1. **Create Slack App**:
   * Go to [api.slack.com/apps](https://api.slack.com/apps) → **Create New App** → **From scratch**
   * Name your app and select your workspace
2. **Configure Bot Scopes**:
   * Go to **OAuth & Permissions** → scroll to **Bot Token Scopes** → add:
     * `chat:write`
     * `channels:history`
     * `groups:history`
     * `im:history`
     * `users:read`
3. **Install to Workspace**:
   * Go to **OAuth & Permissions** → click **Install to Workspace**
   * Copy the **Bot User OAuth Token** (starts with `xoxb-`)
4. **Get Signing Secret**:
   * Go to **Basic Information** → **App Credentials**
   * Copy the **Signing Secret**
5. **Create Channel** in Soika:
   * Select "Slack" → paste Bot Token + Signing Secret → Test Connection → Create
   * Soika auto-generates the webhook URL
6. **Configure Event Subscriptions**:
   * Go to **Event Subscriptions** → toggle **Enable Events** ON
   * Set **Request URL** to your Soika webhook URL:

     ```
     http://<YOUR_SERVER>:5001/console/api/webhook/slack/<CHANNEL_ID>
     ```
   * Slack will send a challenge — Soika handles it automatically
   * Under **Subscribe to bot events**, add:
     * `message.channels` (public channels)
     * `message.groups` (private channels)
     * `message.im` (direct messages)
   * Click **Save Changes**
7. **Invite Bot**: In the Slack channel, type `/invite @YourBotName`
8. **Bind Agent**: Assign your AI agent to this channel in Soika

#### Config Fields

| Field            | Required | Description                                  |
| ---------------- | -------- | -------------------------------------------- |
| `bot_token`      | Yes      | Bot User OAuth Token (`xoxb-...`)            |
| `signing_secret` | Yes      | From Basic Information → Signing Secret      |
| `app_token`      | No       | App-Level Token (`xapp-...`) for Socket Mode |

#### How It Works

* Slack pushes events to Soika's webhook URL
* Request signatures are verified using the signing secret
* Bot messages are automatically skipped to prevent loops
* Replies are sent in the same thread as the user's message
* User display names are fetched from Slack API

#### Limitations

* Text messages only
* The server must be publicly accessible for Slack to reach the webhook URL

### Discord

Connect a Discord bot.

#### Prerequisites

* Discord account
* A Discord server you manage

#### Setup Steps

1. **Create Discord App**:
   * Go to [discord.com/developers/applications](https://discord.com/developers/applications) → **New Application**
   * Go to **Bot** → click **Add Bot**
   * Enable **Message Content Intent** under Privileged Gateway Intents
   * Copy the **Bot Token**
2. **Get Application ID**:
   * Go to **General Information** → copy **Application ID**
3. **Invite Bot to Server**:
   * Go to **OAuth2** → **URL Generator**
   * Select scopes: `bot`
   * Select permissions: `Send Messages`, `Read Message History`, `View Channels`
   * Copy the generated URL → open in browser → select your server
4. **Create Channel** in Soika:
   * Select "Discord" → paste Bot Token + Application ID → Test Connection → Create

#### Config Fields

| Field            | Required | Description                                 |
| ---------------- | -------- | ------------------------------------------- |
| `bot_token`      | Yes      | From Discord Developer Portal → Bot → Token |
| `application_id` | Yes      | From General Information                    |
| `guild_ids`      | No       | Comma-separated server IDs to restrict to   |

#### Status

> ✅ **Fully Implemented** — Discord uses a persistent WebSocket (Gateway) worker subprocess (similar to WhatsApp QR). The worker connects to Discord Gateway, listens for messages, and forwards them to the Soika agent. Supports both Gateway messages and HTTP Interactions (slash commands with Ed25519 verification).

#### How It Works

* A **Gateway worker subprocess** connects to Discord's WebSocket Gateway with the bot token
* The worker handles IDENTIFY, HEARTBEAT, and RESUME automatically
* When a MESSAGE\_CREATE event arrives, the worker forwards it to the internal webhook endpoint
* Soika runs the AI agent and the worker sends the reply via Discord REST API
* Supports **zlib-stream** compression and automatic reconnection
* For HTTP Interactions (slash commands): Discord POSTs directly to the webhook, verified with Ed25519

#### Connection API

* **Connect**: `POST /console/api/channels/<channel_id>/discord/connect` — starts the Gateway worker
* **Disconnect**: `POST /console/api/channels/<channel_id>/discord/disconnect` — stops the worker
* **Status**: `GET /console/api/channels/<channel_id>/discord/status` — returns connection state

#### Architecture

```
Discord Gateway (WebSocket) ↔ discord_worker.py subprocess
    ↓ MESSAGE_CREATE
Internal HTTP POST → discord_webhook.py → AppGenerateService → reply via REST API
```

### LINE

Connect a LINE Messaging API bot.

#### Prerequisites

* LINE account
* LINE Developers Console access

#### Setup Steps

1. **Create LINE Channel**:
   * Go to [LINE Developers Console](https://developers.line.biz/console/) → **Create a new provider** (or select existing)
   * **Create a Messaging API channel**
   * In **Messaging API** tab → issue a **Channel access token** (long-lived)
   * In **Basic settings** tab → copy the **Channel secret**
2. **Create Channel** in Soika:
   * Select "LINE" → paste Channel Access Token + Channel Secret → Test Connection → Create
   * Soika auto-generates the webhook URL
3. **Set Webhook URL in LINE Console**:
   * Go to **Messaging API** tab → **Webhook settings**
   * Set Webhook URL:

     ```
     http://<YOUR_SERVER>:5001/console/api/webhook/line/<CHANNEL_ID>
     ```
   * Toggle **Use webhook** ON
   * Click **Verify** to test it
4. **Disable auto-reply messages**:
   * In LINE Console → **Messaging API** → click **LINE Official Account Manager**
   * Go to **Response settings** → disable **Auto-response** and **Greeting messages**
5. **Add bot as friend**: Scan the QR code from the LINE Console to add the bot
6. **Bind Agent**: Assign your AI agent in Soika

#### Config Fields

| Field                  | Required | Description                                   |
| ---------------------- | -------- | --------------------------------------------- |
| `channel_access_token` | Yes      | From LINE Developers Console → Messaging API  |
| `channel_secret`       | Yes      | From LINE Developers Console → Basic Settings |

#### How It Works

* LINE pushes webhook events to Soika
* Signatures are verified using the channel secret
* Agent responses are sent via LINE Reply API (within 1 minute) or Push API (for long responses)
* Messages are capped at 5000 characters per bubble (LINE limit)

### Microsoft Teams

Connect a Microsoft Teams bot via Azure Bot Service.

#### Prerequisites

* Microsoft 365 account with Teams
* Azure subscription (free tier works)

#### Setup Steps

1. **Create Azure Bot**:
   * Go to [Azure Portal](https://portal.azure.com) → **Create a resource** → search "Azure Bot"
   * Fill in:
     * **Bot handle**: unique name
     * **Pricing tier**: F0 (free)
     * **Microsoft App ID**: Create new (or use existing)
   * Click **Create**
2. **Get Credentials**:
   * Go to your Bot → **Configuration**
   * Copy **Microsoft App ID**
   * Click **Manage Password** → **New client secret** → copy the **Value** (this is your App Password)
3. **Set Messaging Endpoint**:
   * In Bot **Configuration** → **Messaging endpoint**, set:

     ```
     http://<YOUR_SERVER>:5001/console/api/webhook/msteams/<CHANNEL_ID>
     ```
4. **Add Teams Channel**:
   * Go to your Bot → **Channels** → click **Microsoft Teams** → Save
5. **Create Channel** in Soika:
   * Select "MS Teams" → paste App ID + App Password → Test Connection → Create
6. **Install Bot in Teams**:
   * In Teams → **Apps** → **Upload a custom app** (or use the App Studio)
   * Search for your bot and add it to a team or chat
7. **Bind Agent**: Assign your AI agent in Soika

#### Config Fields

| Field          | Required | Description                               |
| -------------- | -------- | ----------------------------------------- |
| `app_id`       | Yes      | Microsoft App ID from Azure Bot Service   |
| `app_password` | Yes      | Client secret from Azure Bot Service      |
| `tenant_id`    | No       | Azure Tenant ID (single-tenant apps only) |

#### How It Works

* Teams sends activities to Soika via the Bot Framework messaging endpoint
* Bot authenticates with Microsoft OAuth to send replies
* @mentions are automatically stripped from the message text
* Replies are sent back in the same conversation thread

### Signal

Connect via Signal using signal-cli.

#### Prerequisites

* signal-cli installed ([github.com/AsamK/signal-cli](https://github.com/AsamK/signal-cli))
* Or signal-cli REST API running ([github.com/bbernhard/signal-cli-rest-api](https://github.com/bbernhard/signal-cli-rest-api))

#### Config Fields

| Field             | Required | Description                                                |
| ----------------- | -------- | ---------------------------------------------------------- |
| `phone_number`    | Yes      | Signal phone number with country code                      |
| `signal_cli_path` | No       | Path to signal-cli binary                                  |
| `signal_api_url`  | No       | URL of signal-cli REST API (e.g., `http://localhost:8080`) |

#### Status

> ✅ **Fully Implemented** — Signal uses signal-cli-rest-api callbacks to receive messages via webhook. Supports both direct messages and group messages. Replies are sent via the `/v2/send` endpoint.

#### Setup Steps

1. **Run signal-cli-rest-api** (Docker recommended):

   ```bash
   docker run -d --name signal-api \
     -p 8080:8080 \
     -v /path/to/signal-cli:/home/.local/share/signal-cli \
     bbernhard/signal-cli-rest-api
   ```
2. **Register/Link** your Signal number via the API
3. **Create Channel** in Soika:
   * Select "Signal" → paste phone number + API URL → Test Connection → Create
   * Soika auto-generates the webhook URL
4. **Register Webhook** on signal-cli-rest-api:

   ```bash
   curl -X POST http://localhost:8080/v1/webhook \
     -H "Content-Type: application/json" \
     -d '{"url":"http://<YOUR_SERVER>:5001/console/api/webhook/signal/<CHANNEL_ID>"}'
   ```
5. **Bind Agent**: Assign your AI agent

#### How It Works

* signal-cli-rest-api sends incoming messages as callbacks to the webhook URL
* The handler parses the envelope format and extracts the message text
* Agent processes the message and reply is sent via `/v2/send` endpoint
* Supports both 1:1 and group message contexts

### Matrix

Connect to Matrix protocol rooms.

#### Prerequisites

* A Matrix account on any homeserver (matrix.org, Element, etc.)
* A bot user with an access token

#### Config Fields

| Field            | Required | Description                                        |
| ---------------- | -------- | -------------------------------------------------- |
| `homeserver_url` | Yes      | Matrix homeserver URL (e.g., `https://matrix.org`) |
| `access_token`   | Yes      | Bot user access token                              |
| `user_id`        | Yes      | Full Matrix user ID (e.g., `@bot:matrix.org`)      |

#### How to Get an Access Token

```bash
curl -X POST "https://matrix.org/_matrix/client/v3/login" \
  -H "Content-Type: application/json" \
  -d '{"type":"m.login.password","user":"@bot:matrix.org","password":"your-password"}'
```

Copy the `access_token` from the response.

#### Status

> ✅ **Fully Implemented** — Matrix uses a sync worker subprocess that long-polls the `/sync` endpoint (similar to WhatsApp QR pattern). Also supports Matrix Application Service (appservice) mode for homeserver-pushed events. Replies are sent via the Matrix Client-Server API.

#### Setup Steps

1. **Create a Bot User** on your Matrix homeserver (or matrix.org)
2. **Get Access Token** (see above curl command)
3. **Create Channel** in Soika:
   * Select "Matrix" → paste homeserver URL + access token + user ID → Test Connection → Create
4. **Connect the worker**: Use the API or Soika UI to start the sync worker
5. **Invite**: Invite the bot user to the Matrix rooms you want it to monitor
6. **Bind Agent**: Assign your AI agent

#### Connection API

* **Connect**: `POST /console/api/channels/<channel_id>/matrix/connect` — starts the sync worker
* **Disconnect**: `POST /console/api/channels/<channel_id>/matrix/disconnect` — stops the worker
* **Status**: `GET /console/api/channels/<channel_id>/matrix/status` — returns connection state

#### How It Works

* A **sync worker subprocess** long-polls the Matrix `/sync` endpoint (30s timeout)
* When `m.room.message` events arrive, the worker forwards them to the internal webhook
* Soika runs the AI agent and sends the reply via Matrix Client-Server API
* Supports filtering by `room_ids` to limit which rooms the bot responds in
* Worker saves `sync_token` for resume after restart

#### Architecture

```
Matrix Homeserver /sync (long-poll) ↔ matrix_worker.py subprocess
    ↓ m.room.message
Internal HTTP POST → matrix_webhook.py → AppGenerateService → reply via PUT /send
```

### WeChat

Connect a WeChat Official Account (Service or Subscription).

#### Prerequisites

* A verified WeChat Official Account with API access
* WeChat Developer portal access

#### Config Fields

| Field              | Required | Description                                                    |
| ------------------ | -------- | -------------------------------------------------------------- |
| `app_id`           | Yes      | From WeChat Official Account → Basic Configuration → AppID     |
| `app_secret`       | Yes      | From WeChat Official Account → Basic Configuration → AppSecret |
| `token`            | Yes      | Verification token you set in WeChat server configuration      |
| `encoding_aes_key` | No       | 43-character key for message encryption                        |
| `webhook_url`      | No       | Auto-generated callback URL                                    |

#### Status

> ✅ **Fully Implemented** — WeChat Official Account webhook handles XML-based payloads with SHA1 signature verification. Supports AES-CBC encrypted messages. Short replies (<600 chars) use passive XML response; longer replies use Customer Service API.

#### Setup Steps

1. **Log in** to [WeChat Official Account Admin Platform](https://mp.weixin.qq.com/)
2. **Enable Developer Mode**: Go to **Development** → **Basic Configuration**
3. **Set Server Configuration**:
   * URL: `http://<YOUR_SERVER>:5001/console/api/webhook/wechat/<CHANNEL_ID>`
   * Token: choose any random string → copy for Soika config
   * EncodingAESKey: generate one (43 chars) → copy for Soika config
   * Message Encryption: choose "Safe Mode" for encrypted payloads
4. **Create Channel** in Soika:
   * Select "WeChat" → paste AppID + AppSecret + Token + EncodingAESKey → Test Connection → Create
5. **Click Enable** in WeChat console (triggers URL verification via GET request)
6. **Bind Agent**: Assign your AI agent

#### How It Works

* WeChat sends XML-format webhook POST requests to Soika
* Signature verified via SHA1(sort(token, timestamp, nonce))
* Encrypted messages are decrypted with AES-CBC using the EncodingAESKey
* Short replies (<600 chars) return instantly as passive XML response
* Longer replies use WeChat Customer Service API (`/cgi-bin/message/custom/send`)
* Access tokens are cached in-memory with auto-refresh

### IRC

Connect to IRC servers and channels.

#### Config Fields

| Field      | Required | Description                                                  |
| ---------- | -------- | ------------------------------------------------------------ |
| `server`   | Yes      | IRC server hostname (e.g., `irc.libera.chat`)                |
| `port`     | No       | Server port (default: 6697 TLS, 6667 plain)                  |
| `nickname` | Yes      | Bot nickname                                                 |
| `channels` | No       | Comma-separated channels to join (e.g., `#general,#support`) |
| `use_tls`  | No       | Enable TLS/SSL encryption                                    |
| `password` | No       | Server password if required                                  |

#### Status

> ✅ **Fully Implemented** — IRC uses a persistent TCP worker subprocess (similar to WhatsApp QR pattern). The worker maintains the IRC connection, handles PING/PONG, channel JOIN, and forwards PRIVMSG events to the agent. Supports TLS, password auth, and auto-reconnect.

#### Setup Steps

1. **Choose an IRC server** (e.g., `irc.libera.chat`, `irc.rizon.net`)
2. **Create Channel** in Soika:
   * Select "IRC" → configure server, port, nickname, channels → Test Connection → Create
3. **Connect the worker**: Use the API or Soika UI to start the IRC worker
4. **Bind Agent**: Assign your AI agent

#### Connection API

* **Connect**: `POST /console/api/channels/<channel_id>/irc/connect` — starts the IRC worker
* **Disconnect**: `POST /console/api/channels/<channel_id>/irc/disconnect` — stops the worker
* **Status**: `GET /console/api/channels/<channel_id>/irc/status` — returns connection state

#### How It Works

* A **TCP worker subprocess** connects to the IRC server and handles NICK/USER registration
* The worker JOINs specified channels and listens for PRIVMSG events
* Messages are forwarded to the internal webhook via HTTP POST
* Soika runs the agent and returns replies; the worker sends them as PRIVMSG
* Rate-limited sending (0.5s between lines) to avoid IRC flooding
* Auto-reconnect on disconnect with exponential backoff
* Supports TLS/SSL and server password authentication

#### Architecture

```
IRC Server (TCP) ↔ irc_worker.py subprocess
    ↓ PRIVMSG
Internal HTTP POST → irc_webhook.py → AppGenerateService → PRIVMSG reply
```

### Gmail Pub/Sub

Receive Gmail messages via Google Cloud Pub/Sub.

#### Prerequisites

* Google Cloud Platform project
* Gmail API enabled
* Cloud Pub/Sub API enabled
* Service account with appropriate permissions

#### Config Fields

| Field                  | Required | Description                                                                 |
| ---------------------- | -------- | --------------------------------------------------------------------------- |
| `service_account_json` | Yes      | Full JSON key file from GCP Console → IAM → Service Accounts                |
| `topic_name`           | Yes      | Full Pub/Sub topic (e.g., `projects/my-project/topics/gmail-notifications`) |
| `subscription_name`    | No       | Full subscription name (auto-created if blank)                              |
| `gmail_address`        | Yes      | Gmail address to watch                                                      |
| `label_filter`         | No       | Only watch messages with this label (default: INBOX)                        |

#### Status

> ✅ **Fully Implemented** — Gmail uses Google Cloud Pub/Sub push notifications. When a new email arrives, Pub/Sub sends a push to the webhook. The handler fetches the email via Gmail API, runs the agent, and sends a reply email in the same thread.

#### Setup Steps

1. **Enable APIs** in [Google Cloud Console](https://console.cloud.google.com/):
   * Gmail API
   * Cloud Pub/Sub API
2. **Create Service Account**: IAM → Service Accounts → Create → download JSON key
3. **Create Pub/Sub Topic**: Pub/Sub → Create Topic (e.g., `gmail-notifications`)
4. **Grant gmail access**: Add `gmail-api-push@system.gserviceaccount.com` with **Pub/Sub Publisher** role on the topic
5. **Create Push Subscription** pointing to your Soika webhook:

   ```bash
   gcloud pubsub subscriptions create gmail-soika-sub \
     --topic=gmail-notifications \
     --push-endpoint=http://<YOUR_SERVER>:5001/console/api/webhook/gmail/<CHANNEL_ID>
   ```
6. **Watch the mailbox**:

   ```bash
   curl -X POST "https://gmail.googleapis.com/gmail/v1/users/me/watch" \
     -H "Authorization: Bearer <ACCESS_TOKEN>" \
     -H "Content-Type: application/json" \
     -d '{"topicName":"projects/<PROJECT>/topics/gmail-notifications","labelIds":["INBOX"]}'
   ```
7. **Create Channel** in Soika:
   * Select "Gmail Pub/Sub" → paste service account JSON + topic + Gmail address → Create
8. **Bind Agent**: Assign your AI agent

#### How It Works

* Google Pub/Sub sends push notifications when new emails arrive in the watched mailbox
* The webhook decodes the Pub/Sub payload to get `{emailAddress, historyId}`
* Soika fetches the actual email content via Gmail API history endpoint
* The AI agent processes the email body and generates a reply
* Reply is sent as an email in the same thread using Gmail's `messages/send` API
* History IDs are tracked to avoid reprocessing the same messages

### Custom Webhook

Generic webhook integration for any messaging platform or custom service.

#### How It Works

Soika exposes a webhook endpoint that accepts JSON messages and returns the AI agent's response synchronously.

#### Setup Steps

1. **Create Channel** in Soika: Select "Custom" → enter your webhook URL → Create
2. **Bind Agent**: Assign your AI agent
3. **Send Messages** to the Soika webhook endpoint

#### Webhook Endpoint

```
POST http://<YOUR_SERVER>:5001/console/api/webhook/custom/<CHANNEL_ID>
Content-Type: application/json
```

#### Request Format

```json
{
    "message": "Hello, what's the weather like?",
    "user_id": "user123",
    "user_name": "John Doe",
    "secret": "your-webhook-secret"
}
```

| Field                            | Required | Description                                   |
| -------------------------------- | -------- | --------------------------------------------- |
| `message` (or `text` or `query`) | Yes      | The user's message text                       |
| `user_id`                        | No       | Unique user identifier (default: "anonymous") |
| `user_name`                      | No       | Display name for the user                     |
| `secret`                         | No       | Webhook secret for authentication             |

#### Authentication Methods

**Option 1: Secret in body**

```json
{"message": "hello", "secret": "your-webhook-secret"}
```

**Option 2: Secret in header**

```
X-Webhook-Secret: your-webhook-secret
```

**Option 3: HMAC signature**

```
X-Webhook-Signature: <sha256 HMAC of request body using webhook_secret>
```

#### Response Format

```json
{
    "status": "ok",
    "answer": "The weather in your area is currently sunny with a high of 72°F."
}
```

#### Outgoing URL (Optional)

If you configure an **Outgoing URL**, Soika will also POST the agent's response there:

```json
{
    "channel_id": "uuid",
    "user_id": "user123",
    "original_message": "Hello, what's the weather like?",
    "answer": "The weather is currently sunny..."
}
```

#### Config Fields

| Field            | Required | Description                                                 |
| ---------------- | -------- | ----------------------------------------------------------- |
| `webhook_url`    | Yes      | Your service's incoming webhook URL (for test connectivity) |
| `webhook_secret` | No       | Secret for verifying requests                               |
| `outgoing_url`   | No       | URL to forward agent responses to                           |
| `headers`        | No       | Custom HTTP headers as JSON for outgoing requests           |

#### Example: cURL

```bash
curl -X POST "http://localhost:5001/console/api/webhook/custom/<CHANNEL_ID>" \
  -H "Content-Type: application/json" \
  -d '{"message": "What is Soika?", "user_id": "test-user"}'
```

#### Example: Python

```python
import requests

resp = requests.post(
    "http://localhost:5001/console/api/webhook/custom/<CHANNEL_ID>",
    json={
        "message": "What is Soika?",
        "user_id": "my-app-user-123",
        "user_name": "Test User",
        "secret": "your-webhook-secret",
    }
)
print(resp.json()["answer"])
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://soika-labs.gitbook.io/soika-mockingjay/channel-connection-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
