Skip to content
CortexDocs
Cortex documentation

Connect Slack to Cortex

Capture channel messages with bot and app-level tokens.

All connectors

Slack

Content and access

Captured public-channel content is available to organization-wide Search. Direct messages and private-channel messages are excluded from that Search scope.

Set up Slack

An admin connects this app for the Cortex organization. Grant access only to content appropriate for the whole organization.

What you need: permission to create and install a Slack app in the workspace.

Stage 1: configure the Slack app in Slack

Create a Slack app for the workspace. Under OAuth & Permissions, add these Bot Token Scopes:

text
channels:history
channels:read
groups:read
im:read
mpim:read
users:read
users:read.email

All seven scopes are required. Cortex does not read direct messages, but Slack requires im:read and mpim:read for the channel-list request; omitting either produces an empty list.

Slack's live message search API accepts a user token only. Add these User Token Scopes if your deployment uses live Slack message search:

text
search:read
users:read.email

Then finish the Slack app:

  1. Enable Socket Mode.
  2. Enable Event Subscriptions and subscribe to the message.channels and message.groups bot events.
  3. Create an app-level token with the connections:write scope.
  4. Install the app to the workspace. If you change scopes after installing, reinstall it.
  5. Copy the bot token (xoxb-…), the app-level token (xapp-…), and the user token (xoxp-…) if you configured one.

Stage 2: connect Slack to Cortex

  1. In Cortex, open Organization → Apps and add Slack.
  2. Enter the bot token in Bot token and the app-level token in App-level token (optional). Add the search user token under Search user token (optional) if you created one.
  3. Select Test & preview and confirm the expected Slack workspace.
  4. Select Configure channels, review the channels Cortex found, and turn ingest off for any it should not use.
For channel capture, enter Bot token (xoxb-…) and App-level token (optional) (xapp-…) together. Despite its label, the app-level token is required for this Socket Mode connection. Without it, verification expects a search-only user token (xoxp-…) in the first field and rejects a bot token.

The search user token is optional and supports live Slack message search. Organization-wide Cortex Search reads captured public-channel content, so channel capture and those Search results work with the bot and app-level tokens.

What Search returns

Organization-wide Search returns public-channel content. Direct messages and private-channel messages are not shown in organization-wide Search.

In Slack channels, ingest state is on each row. Turning ingest off hides that channel from Search and Ask.

Technical details

Cortex reaches Slack only through outbound connections: Web API calls and a Socket Mode WebSocket to slack.com, plus Slack's CDN (slack-edge.com) only when an admin imports profile photos. Cortex has no Slack request URL, so Slack never calls into Cortex.

Authentication

  • On save, Cortex calls auth.test with the token, reads the granted scopes from Slack's x-oauth-scopes response header, and rejects the token if any required scope is missing. It keeps the verified workspace ID, name and URL, the bot's user name, and the granted scope list.
  • Tokens are encrypted at rest with a Cortex-held key before they are written to Cortex's Postgres database. The API returns only which token names are stored, never their values, which is why the UI shows Stored.
  • Each token has one job. The bot token lists channels and reads channel history and the user directory (users.list, users.lookupByEmail, users.info). The app-level token only opens the Socket Mode connection. The optional user token is used only for Slack's search.messages.

What Cortex reads

  • Channel scope. On connect, Cortex lists channels with conversations.list, registers every channel the bot can see, and joins every public channel itself. Ingest is on by default; an admin turns individual channels off, or removes them, in Configure channels. Slack does not let a bot join a private channel; if a member invites the bot, that channel is captured too, but its messages stay out of organization-wide Search.
  • Live events. With the app-level token, the Cortex Slack listener opens the Socket Mode connection and receives message events (new, edited, deleted) for channels the bot is in. Events from direct messages and group direct messages are discarded before they are queued. im:read and mpim:read are required only because Slack's channel-list call fails without them; those conversations are never read.
  • Content. The listener then fetches the full thread with the bot token through conversations.replies and conversations.history. When a channel is first registered, Cortex backfills up to the newest 3,000 messages, then follows new activity; a periodic reconciliation sweep fills gaps.
  • Directory. users.list and users.lookupByEmail map Slack user IDs to Cortex people by work email. An admin can also import profile photos from Slack.

Cortex does not download message files or attachments; file names and link previews that arrive inside a message payload are stored with it. The only binary content Cortex fetches is profile photos, when an admin runs the import. Cortex does not read direct messages.

Where data is stored

Messages are written to Cortex's Postgres database, in tables keyed by your Cortex organization ID: channel ID, message timestamp, thread timestamp, Slack user ID, message text, the message payload as received, and a permalink when one appears in a linked pull request. Thread rollups (participants, counts, last activity) and per-channel settings sit beside them. An edit in Slack updates the stored row; when Slack delivers a deletion event, the message is marked deleted and leaves Search. Search runs over this stored copy with Postgres full-text search, and a channel is searchable only while Cortex has recent proof from Slack that it is public. Retrieval indexes for Search and Ask are built from these stored rows and kept in the same database; model calls run through Cortex's model gateway under the providers agreed for your deployment. Connection changes are written to the audit log.

Revoke and delete

Turning ingest off for a channel hides it from Search and Ask and keeps its stored messages. Remove on a channel marks its stored messages deleted so they are not served again. Revoke or Delete on the connection closes the Socket Mode connection within a minute, stops token use and Search for that workspace, and is written to the audit log. Neither uninstalls the Slack app: remove it under your workspace's Manage apps. Messages already captured stay under your organization's retention terms until removed per channel or purged by Chaos Labs.

Manage this connection

After changing permissions in Slack, return to Organization → Apps and run Test & preview. A preview is a limited sample of accessible content.

See the shared connection management guide for credential updates, reauthorization, and revocation. The complete Slack procedure is also available in Workplace connections.

Was this helpful?