CortexDB Docs
Connectors

Slack Connector

Continuously ingest Slack messages into CortexDB as conversation experiences.

The Slack connector tails messages from configured channels and writes them to CortexDB as conversation experiences. Threads and file shares are preserved.

Two ways to run this connector

Self-hostedpip install 'cortexdb-connectors[slack]' then cortexdb-sync sync slack. Reads your token from ~/.cortexdb/state.json (written by cortexdb init) or from env. Managed — CortexDB runs the connector as a worker; configure it once from your dashboard. See the Connectors overview.

1. Prepare credentials in Slack

  1. api.slack.com/apps → create a new app from scratch.
  2. Add Bot Token Scopes:
    • channels:history — read public channels
    • channels:read — view channel info
    • groups:history — read private channels (optional)
    • users:read — resolve author names
    • files:read — download shared files (required for file ingestion)
  3. Install the app to your workspace and copy the Bot User OAuth Token (xoxb-...).

files:read is required for file shares

Without the files:read bot scope, Slack answers file downloads with a 200 HTML login page instead of the file, and shared files are silently dropped. Add it if you rely on file ingestion.

2. Configure (managed dashboard)

Settings → Connectors → Add Connector → Slack. Paste the bot token, choose channels (default: all public), set the scope template (default org:<org>/source:slack/channel:{channel}; placeholders {channel}, {author}, {workspace}, {thread_ts}), pick Real-time (Events API webhook) or Polling (default 10 s), and Start sync. Backfill preserves original message timestamps as observed_at for bi-temporal correctness.

What gets written

Each Slack message becomes a POST /v1/experience:

{
  "scope":    "org:acme/source:slack/channel:engineering",
  "modality": "conversation",
  "observed_actor": "user:[email protected]",
  "content": {
    "kind": "message",
    "role": "user",
    "text": "We should migrate the payments service to CockroachDB."
  },
  "context": {
    "observed_at": "2026-03-15T10:30:00.123Z",
    "labels":      ["channel:engineering", "workspace:acme-corp", "thread=C123:1710502200.000100"],
    "intent":      "discussion"
  },
  "idempotency_key": "slack:C123:1710502200.000100:a1b2c3"
}
Slack eventMaps to
Channel messageexperience with content.kind=message
Thread replySame, plus a thread=<channel>:<thread_ts> label (see below)
File shareexperience with content.kind=blob_ref (file uploaded via POST /v1/blobs first; needs files:read)
Bot messagesSkipped by default; toggle "Include bots" to enable

Corrected fields (vs older docs)

  • idempotency_key is slack:{channel}:{ts}:{content-hash} for messages (the trailing content-version hash lets an edit land as a new version instead of colliding — there is no team-id segment). Files use slack:file:{channel}:{file_id}:{version}.
  • Thread replies attach a thread=<channel>:<thread_ts> label, not context.preceded_by (the connector doesn't have the parent's evt_… id at emit time).
  • Reactions are not ingested — emoji reactions never become content.

Run it yourself

pip install 'cortexdb-connectors[slack]'

# One-time: get a CortexDB token + actor
pip install cortexdb-cli
cortexdb init

# Supply the connector's credentials
export SLACK_BOT_TOKEN=xoxb-...          # required

# Sync once, or watch on a poll loop (point at your instance if self-hosted)
cortexdb-sync --api-url http://localhost:3141 sync slack
cortexdb-sync --api-url http://localhost:3141 watch slack --interval 60

Cursor state persists in ~/.cortexdb/sync_state.json. For real-time ingestion, run cortexdb-sync serve with SLACK_SIGNING_SECRET set.

See also

On this page