CortexDB Docs
Docs for CortexDB 0.12.8, the version running on CortexDB Cloud (api.cortexdb.ai).
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-hosted — pip 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, so shared files are skipped. 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 (e.g. org:<org>/source:slack/project:{channel}; channel is not an allowed scope type; 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/project:engineering",
  "modality": "conversation",
  "observed_actor": "user:alice@acme.com",
  "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": "cxsrc:<56 hex>",
  "source": { "schema_version": 2, "source_id": "connector:<digest>:<digest>", "...": "..." }
}

The connector's internal record identity for this message is slack:C123:1710502200.000100:a1b2c3; the key on the wire is the derived cxsrc: value (see the callout below).

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

Record keys and threads

  • 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.

The key on the wire is derived

The key format above is this connector's internal record identity: it decides which source record an event belongs to. The idempotency_key actually sent to CortexDB is a derived cxsrc:<56 hex> value that also hashes the content, labels, observed time and actor, so an unchanged redelivery converges on the same event while any edit lands as a new one, even where the key format itself is not content-versioned. Every event also carries a source descriptor with the record's fingerprint. See Source identity and keys.

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, after pip install 'cortexdb-connectors[slack,webhooks]' (serve needs the webhooks extra).

Optional settings

Set these as environment variables (or the matching keys in the cortexdb-sync YAML config). Lists are comma-separated. For on/off settings, 1, true, yes or on turns the setting on and any other value turns it off.

SettingWhat it doesDefault
SLACK_CHANNELSChannel IDs to syncEvery channel the bot is a member of
SLACK_INGEST_FILESIngest files shared in the synced channels (needs the files:read scope)On
SLACK_FILE_TYPESFile types to ingest when files are onAll types

See also

On this page