---
title: Slack integration (triage Slack from Omniscio)
---
# Slack integration (triage Slack from Omniscio)

## What it is

Omniscio's Slack integration pulls selected channels and DMs into the unified inbox so you can read, triage, and reply to Slack messages without switching apps. It connects to your workspace through Slack's Socket Mode (a WebSocket connection — no public webhook URL needed), so messages arrive in real time. Each conversation appears as a row in the Omniscio sidebar/inbox alongside your Gmail, SMS, and Telegram threads, and you reply with the same Quick Responses + AI-suggested reply chips you use everywhere else. Sending goes back through the Slack Web API as your bot user.

## Where to find it

**Settings → Slack** — paste the bot and app tokens and toggle the integration on, then pick which channels and DMs to follow in the same panel.

## How it behaves

### How to use it

1. **Create a Slack app.** Go to api.slack.com/apps → **Create New App** → **From scratch**. Add the OAuth scopes you want the bot to read/write (`channels:history`, `channels:read`, `chat:write`, `users:read`, plus `im:*` for DMs), enable **Socket Mode**, and generate an **App-Level Token** with `connections:write`.
2. **Connect Omniscio.** Settings → **Slack** → paste the **Bot Token** (`xoxb-…`), the **App Token** (`xapp-…`), and optionally a **User Token** (`xoxp-…`) for sending as yourself instead of as the bot. Toggle `slackEnabled` on. Omniscio opens the Socket Mode WebSocket and starts receiving message events.
3. **Pick which channels show up.** In the same settings panel, choose the channels and DMs you want to follow. Only selected conversations sync — the goal is to keep your Omniscio inbox curated, not mirror your entire workspace.
4. **Triage from the inbox.** New Slack messages appear as inbox rows. Click one to open the conversation panel — full thread history, thread replies, reactions on hover. Reply inline; sends post back through Slack as the bot (or as you, if a user token is configured).
5. **Pair with automations.** Slack messages flow through the same Automation/Auto-replies engine, so you can auto-reply to keywords, forward urgent threads via email, or route specific channels to the daily digest.

### How it works

Slack lives in [/src/main/services/slack-service.ts](/src/main/services/slack-service.ts) — direct `fetch` calls to `https://slack.com/api/*` for channel listing, message send, and user resolution, plus a long-running WebSocket connection from `apps.connections.open` (Slack's Socket Mode endpoint, called with the app-level token) for incoming events. The WebSocket reconnects with exponential backoff + jitter (2s base, 60s cap) and pings every 30s; user lookups are cached for 15 minutes to stay under Slack's rate limits. Response shapes are validated by [/src/main/services/slack-response-schemas.ts](/src/main/services/slack-response-schemas.ts) so a malformed Slack reply can't poison the cache. Tokens are encrypted at rest via `safeStorage` and read through [/src/main/services/config-store/accessors-integrations.ts](/src/main/services/config-store/accessors-integrations.ts) (`getSlackBotToken`, `getSlackAppToken`, `getSlackUserToken`). The unified-inbox bridge is [/src/main/services/channels/slack-adapter.ts](/src/main/services/channels/slack-adapter.ts), which translates Slack-specific shapes into the shared `UnifiedConversation` / `UnifiedMessage` types in [/src/shared/channel-types.ts](/src/shared/channel-types.ts). Persistence lives in [/src/main/db/queries-slack.ts](/src/main/db/queries-slack.ts).

### Scope and limits

- **Reachable from the localhost CLI — setup is the exception.** The control server (`127.0.0.1:19519`) does reach Slack: `GET /slack/status` (connection health — connected / disconnected / re-auth-needed), `POST /slack/sync` (pull the selected channels' history into the local DB), `POST /slack/conversations/:channelId/backfill` (one conversation's older messages, `?limit=` default 50 / max 200), `POST /slack/dm` (open or create a DM with a workspace member) and `DELETE /slack/conversations/:channelId` (erase one conversation's stored archive). Sending is `POST /slack/send` — **approval-gated**: a `202` means the message is QUEUED for the user to approve in the inbox and transmits only on that approval, the same posture as `/sms/send` and `/telegram/send`. Still in-app only: connecting/disconnecting, entering or clearing tokens, and **choosing which channels to follow** — the classified `messaging-client` (and `feature-scoped-surface`, for the import wizard) desktop-only exemptions in the CLI-parity manifest.
- **Reading is two-layered; mark-read is not exposed.** Synced Slack messages are searchable via Global Search (Ctrl+K lists Slack alongside every channel), so an agent can _find_ Slack content, and `GET /slack/status` reports the connection state before an action. Marking a conversation read is the one triage action with no route — the control server exposes no Slack mark-read route, so unread state is cleared in the conversation panel.

## Related

- [INDEX.md](INDEX.md) — full library index
- [gmail-integration.md](gmail-integration.md) — parallel email integration
- [automations-and-auto-replies.md](automations-and-auto-replies.md) — auto-reply rules that run against Slack messages
- [global-search.md](global-search.md) — Ctrl+K searches Slack messages alongside every other channel
