> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognee.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Slack

> Ask, save, and recall your Cognee memory from Slack.

Connect Slack to Cognee so your team can query and grow the knowledge graph without leaving a channel or DM. Once a workspace is connected, anyone in it can search memory with `/cognee-ask`, save new facts with `/cognee-remember`, capture existing messages with the **Remember this** shortcut, and review every answer privately before sharing it with the channel.

<Info>
  This integration is for self-hosted Cognee deployments — you create and own the Slack app, so it lives entirely inside your own Slack workspace and your own Cognee backend. It is a **separate app from the cloud/SaaS Slack integration** (different manifest, different scopes, different backend) — do not point one at the other's server.
</Info>

**Requires `cognee >= 1.5.0`.** On older releases `/cognee-remember` falls through to *"Command `/cognee-remember` is not yet supported."* while `/cognee-ask` and **Remember this** work.

```bash theme={null}
# consuming cognee as a dependency
pip install -U cognee

# working on cognee itself — run the checkout, not a release
git checkout dev && uv sync
```

## Why Use This Integration

* **Ask from anywhere in Slack**: `/cognee-ask <question>` searches your memory and replies privately, with a **Share** button to post the answer to the channel once you've checked it, or **Discard** to drop it.
* **Save what Slack never saw**: `/cognee-remember <text>` stores free text nobody typed into Slack yet — a decision from a call, a conclusion recorded after the fact.
* **Save what Slack already has**: the **Remember this** message shortcut (in a message's ⋯ menu) stores any Slack message into Cognee memory, tagged with who said it and where.
* **Per-user, not per-workspace**: each member runs `/cognee-link` once so their asks and saves use *their own* Cognee account — without it, Cognee refuses to act for them rather than falling back to anyone else's memory.
* **Self-hosted, no middleman**: your Slack app talks directly to your Cognee backend. No data passes through a third-party relay.

<Note>
  One Slack **app** is installed once per workspace, but memory is per-**person** — that's what `/cognee-link` exists to resolve. A member who skips it is **refused, not silently attributed**: the only unlinked member Cognee will act for is the one who completed the workspace's OAuth Connect (their own account is used), and everyone else gets *"I don't know which Cognee account you are yet. Run `/cognee-link` to connect yours, then try again."* — for `/cognee-ask`, `/cognee-remember`, and **Remember this** alike. Nothing is written into someone else's memory as a fallback. Workspaces connected before the installer's Slack id was recorded have no installer exception at all, so every member there must link.
</Note>

All replies are ephemeral (visible only to the person who triggered them) except a shared answer, which posts to the channel.

## Prerequisites

* Cognee **`>= 1.5.0`** or a `dev` checkout — see the version note above.
* A running Cognee backend (and frontend, for the `/cognee-link` confirmation page) reachable over HTTPS from the public internet — Slack will not call `localhost`. For local development, use a tunnel like ngrok (below); for production, this is your deployment's normal public domain.
* A Cognee account for each Slack member who wants to link their own memory.

## Local Development: ngrok Tunnel

Slack requires a public HTTPS URL for every request URL. ngrok tunnels a public HTTPS host to your local port 8000 — that host is what every `<public-host>` placeholder below refers to. Skip this section if your backend already has a public domain.

1. Install ngrok: `brew install ngrok` on macOS, or download the binary from [ngrok.com/download](https://ngrok.com/download).
2. Authenticate once: sign up for a free account, copy your authtoken from the dashboard, and run `ngrok config add-authtoken <token>`.
3. Start the tunnel:

```bash theme={null}
ngrok http 8000
```

ngrok prints a line like `Forwarding https://<random>.ngrok-free.app -> http://localhost:8000`. That `https://<random>.ngrok-free.app` host goes into the manifest and `.env` below. Leave the process running the whole time you're testing — closing it kills the tunnel and every request URL stops resolving.

<Tip>
  A free plan's random host changes on every restart, which means re-editing the Slack app's request URLs and `.env` each time. A free account includes one **reserved domain** that fixes this permanently: create it under **Domains** in the ngrok dashboard, then run `ngrok http 8000 --domain=your-name.ngrok-free.app`. Set the manifest and `SLACK_REDIRECT_URI` to that fixed host once and it never changes across restarts.
</Tip>

<Info>
  Free-tier ngrok shows a "Visit Site" interstitial page to **browsers** opening the tunnel URL directly. It does **not** apply to Slack's server-to-server requests (commands, events, interactivity) — those go straight through, so it never blocks the integration itself.
</Info>

## Setup

### 1. Create the Slack App from the Manifest

<Warning>
  Create a **separate** Slack app per environment (local dev, staging, production) — and per developer. Never point the production app's manifest at your laptop: reusing one app means whoever else is testing has their events routed to your tunnel instead of the real server.

  Also prefer a workspace where **only your app is installed**. Slack lets multiple apps register the same slash command and shows a disambiguation dropdown — so in a shared workspace with several Cognee apps, `/cognee-remember` may silently go to someone else's backend, and the reply looks like your server misbehaving.
</Warning>

1. Go to [api.slack.com/apps](https://api.slack.com/apps) → **Create New App** → **From an app manifest**.
2. Paste the manifest below, replacing every `<public-host>` with your backend's public host.
3. On the app's **Basic Information** page, copy **Client ID**, **Client Secret**, and **Signing Secret** — you'll need them for `.env` in step 2.
4. Install the app to your workspace when prompted.

```yaml theme={null}
display_information:
  name: Cognee
  description: Ask questions, save messages, and recall your team's shared memory — right from Slack.
  background_color: "#6510F4"

features:
  bot_user:
    display_name: cognee
    always_online: true
  app_home:
    home_tab_enabled: true
    messages_tab_enabled: true
  slash_commands:
    - command: /cognee-ask
      url: https://<public-host>/api/v1/slack/commands
      description: Ask your Cognee memory a question — reviewed privately before you share it
      usage_hint: what do we know about the Q3 launch?
    - command: /cognee-remember
      url: https://<public-host>/api/v1/slack/commands
      description: Save a decision or fact worth keeping — for things Slack never saw
      usage_hint: we chose Neon for v2, branching is cheaper
    - command: /cognee-link
      url: https://<public-host>/api/v1/slack/commands
      description: Get a private link to connect this Slack account to your own Cognee memory
  shortcuts:
    - name: Remember this
      type: message
      callback_id: remember_this
      description: Save this message to your own Cognee memory, tagged with who said it and where

oauth_config:
  redirect_urls:
    - https://<public-host>/api/v1/integrations/slack/callback
  scopes:
    bot:
      - commands
      - chat:write
      - im:write
      - channels:read

settings:
  event_subscriptions:
    request_url: https://<public-host>/api/v1/slack/events
    bot_events:
      - app_uninstalled
      - tokens_revoked
      - app_home_opened
  interactivity:
    is_enabled: true
    request_url: https://<public-host>/api/v1/slack/interactive
  org_deploy_enabled: false
  socket_mode_enabled: false
  token_rotation_enabled: false
```

<Warning>
  **Adding a slash command to an existing app is not enough on its own.** Slack does not grant a new command to an already-installed app — it refuses the command client-side and nothing ever reaches your server, which looks exactly like a broken backend. After editing the manifest to add a command, **reinstall the app** to the workspace, then reload the Slack client (`Cmd+R`) so autocomplete picks it up.
</Warning>

<Info>
  Deliberately no `channels:history` — bulk channel ingestion isn't part of this integration (see the [dlt integration](/integrations/dlt-integration) for pulling Slack history via dlt's `slack_source` instead). Slack's non-Marketplace rate limits on history reads make it impractical here anyway.
</Info>

### 2. Configure Cognee

Copy the app's credentials into your backend's `.env`:

| Variable                      | Value                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `SLACK_CLIENT_ID`             | From the app's **Basic Information** page.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `SLACK_CLIENT_SECRET`         | From the app's **Basic Information** page.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `SLACK_SIGNING_SECRET`        | From the app's **Basic Information** page — verifies every inbound request's `X-Slack-Signature` and signs the OAuth `state` and link codes.                                                                                                                                                                                                                                                                                                                       |
| `SLACK_REDIRECT_URI`          | `https://<public-host>/api/v1/integrations/slack/callback` — must **byte-match** the manifest's `redirect_urls` entry. Slack re-validates it during the token exchange, so a mismatch fails *after* the user has already approved the app, as a generic callback error.                                                                                                                                                                                            |
| `SLACK_FRONTEND_BASE_URL`     | Your frontend's origin, e.g. `http://localhost:3000` — used to build the `/cognee-link` confirmation URL.                                                                                                                                                                                                                                                                                                                                                          |
| `INTEGRATION_CREDENTIALS_KEY` | Not Slack-specific — the AES-256-GCM key (32 raw bytes, base64-encoded) the integrations framework encrypts every stored OAuth token under. If it's missing, the first credential write raises `RuntimeError`, so `/cognee-link` and the OAuth Connect step both hard-fail. Generate one with `openssl rand -base64 32`. `INTEGRATION_CREDENTIALS_KEYS` (a JSON keyring) is the preferred, rotation-capable form — the single-key variable is the legacy fallback. |

Then bring the stack up **from source** — it runs exactly the checkout you have, with no image layer in between to go stale:

```bash theme={null}
# backend, on :8000
cd cognee
uv sync                                  # re-run after every branch switch
uv run python cognee/api/client.py

# frontend, on :3000 (separate terminal)
cd cognee-frontend
npm install
npm run dev
```

<Info>
  `uv sync` matters more than it looks: branches move `pyproject.toml`/`uv.lock`, and a venv left over from another branch fails in ways that read as application bugs rather than a dependency mismatch. Restart the backend after any `.env` change.
</Info>

### 3. Install and Connect

1. Installing the app from the manifest (step 1) prompts the workspace install once.
2. In the Cognee frontend, go to **Integrations** → **Connect** under Slack. This runs the OAuth exchange and stores the workspace-level bot credential.
3. In Slack, run `/cognee-link` and open the link it replies with in a browser where you're already logged in to Cognee, then click **Confirm**. The link is a short-lived signed code (10-minute expiry), not an API key — nothing secret is ever typed into Slack. This is what points `/cognee-ask` and the save actions at **your** memory — and for anyone who didn't run Connect, what makes them work at all (see the per-person note above).
4. Try `/cognee-ask What does Cognee do?` — you should get a private reply with **Share** / **Discard** buttons.

<Warning>
  **Use the frontend's Connect button, not Slack's "Install to Workspace".** The OAuth `state` is what binds the install to a Cognee account. Slack's own install button sends no signed state, so the callback rejects it and you land on `/integrations?slack=error_invalid_state`.
</Warning>

## Using It

| Command / action                   | Behavior                                                                                                                                                                                                                                                          |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/cognee-ask <question>`           | Ephemeral ack (`🔎 Recalling: ...`) → searches memory → private reply with **Share** (posts to the channel) / **Discard** buttons.                                                                                                                                |
| `/cognee-remember <text>`          | Ephemeral ack (`💾 Remembering: ...`) → saves the text with provenance (`In Slack, @user noted: ...`) → the ack is replaced by a confirmation (`✅ Remembered — it'll be recallable shortly.`) or by a failure message (`Could not save that. Please try again.`). |
| **Remember this** (message ⋯ menu) | Saves the message text with provenance (`In #channel, @user said: ...`). Both save paths land in the same `slack` dataset and node set — one Slack-origin body of memory, not two the graph can't relate.                                                         |
| `/cognee-link`                     | Ephemeral, one-time per member. The link expires in 10 minutes if unused.                                                                                                                                                                                         |

<Note>
  **Ingest something before you ask.** `/cognee-ask` only searches — it never writes, so it cannot create the `slack` dataset. On a completely empty memory it fails with `CollectionNotFoundError: Collection 'DocumentChunk_text' not found`, surfaced as *"Search failed. Please try again."* — which reads like a broken integration but just means there is nothing to search. Run `/cognee-remember` (or ingest via the CLI) first.
</Note>

<Note>
  **@-mentioning the bot does nothing.** The SDK app subscribes to `app_home_opened`, `app_uninstalled`, and `tokens_revoked` only — there is no `app_mention` handler. Mentions are a cloud-integration feature. Use the slash commands.
</Note>

<Info>
  No `/invite @cognee` needed for any of the above. Every reply — including Share, which posts to the channel — is delivered by Slack on the app's behalf regardless of channel membership.
</Info>

### Restricting Which Channels Can Run Commands

An opt-in, per-workspace channel allowlist is available from the Integrations page, backed by two authenticated endpoints: `GET /api/v1/slack/channels` lists the workspace's public channels and flags which are currently allowed, `PUT /api/v1/slack/channels` sets the list. An empty list (the default) means unrestricted — a workspace that never touches this setting keeps working everywhere.

This requires the `channels:read` scope (already in the manifest above). If a workspace connected before that scope existed, the channel list call fails — the fix is to disconnect and reconnect the workspace, not to re-save the allowlist.

Once a non-empty allowlist exists, every command in every other channel returns *"Cognee isn't enabled in this channel."* — worth remembering when testing from a scratch channel.

### Removing the App from a Channel vs. Uninstalling

* **Removing/kicking the bot from a channel** only stops it from posting there — it does not revoke anything; the workspace connection and everyone's `/cognee-link`s stay intact.
* **Uninstalling the app** (or a token revoke) fires `app_uninstalled`/`tokens_revoked`, which revokes the stored workspace credential server-side — commands then fail with "not connected" until reconnected from Integrations.

## Multiple Environments

Slack apps are tied to one set of OAuth credentials and one redirect URL each. If you run more than one Cognee deployment (local dev, staging, production), create a **separate Slack app per environment** rather than editing one app's config back and forth — each environment gets its own `SLACK_CLIENT_ID`/`SLACK_CLIENT_SECRET`/`SLACK_SIGNING_SECRET`/`SLACK_REDIRECT_URI`. This avoids local testing ever breaking a shared staging or production connection.

<Info>
  This is separate from how many Slack **workspaces** one deployment can serve: any number of teams can each connect their own workspace to the same Cognee deployment through the same Connect flow — that's already multi-tenant by design and needs no extra setup per workspace.
</Info>

## Troubleshooting

1. **``Command `/cognee-remember` is not yet supported``**: most likely your backend is on a Cognee release older than `1.5.0`, which has the integration but not this command. Run `pip install -U cognee`, or run the `dev` checkout directly.
2. **Same message, correct version installed**: either the manifest you installed from predates the command and the app was never **reinstalled** (see the reinstall warning above — this is the most common cause), or you are running stale code — restart the backend process (or rebuild the container if containerized).
3. **Same message, but a *different app name* answers**: another Cognee app in the workspace owns the command. Slack shows all of them in autocomplete — pick yours explicitly, or test in a workspace where only your app is installed.
4. **Typing the command produces nothing at all, no request reaches your server**: the command is not registered on your app. Check **api.slack.com/apps → your app → Slash Commands**; if it's missing, the manifest save silently failed. Add it via **Create New Command**, then reinstall.
5. **"Something went wrong when authorizing Cognee"** during Connect: the `redirect_uri` your backend sent (from `SLACK_REDIRECT_URI`) isn't byte-identical to an entry under the app's redirect URLs, or `.env` still holds a different app's `SLACK_CLIENT_ID`/`SLACK_CLIENT_SECRET` than the workspace you're installing into. Re-sync `.env` to the exact app you're testing and restart.
6. **Callback redirects to `?slack=error_exchange_failed`**: the callback never 500s — it catches everything and redirects. The traceback is in the **backend log**. Usual causes: `SLACK_REDIRECT_URI` mismatch, or a missing/malformed `INTEGRATION_CREDENTIALS_KEY`.
7. **Signature verification fails on every request (401)**: `SLACK_SIGNING_SECRET` in `.env` doesn't match the app you actually installed — easy to hit when juggling more than one test app. Copy it again from **Basic Information** and restart the backend.
8. **Request URL mismatch after restarting ngrok**: free-tier ngrok mints a new random host every restart. Update every request URL and redirect URL in the app's Slack settings — or use a reserved/static domain so this never happens.
9. **Slack shows "dispatch\_failed" instead of a reply**: the slash command's request URL is missing or wrong — it must point at `/api/v1/slack/commands`, not `/api/v1/slack/events` or `/api/v1/slack/interactive`.
10. **"This Slack workspace is not connected to Cognee"**: the OAuth install (Connect in the Cognee UI) hasn't completed for this workspace yet, or the connection was later disconnected/revoked.
11. **"I don't know which Cognee account you are yet"**: the member running the command has no active `/cognee-link`, and isn't the member who completed the workspace's Connect — so the command is refused before it reads or writes anything, rather than falling back to the installer's memory. Run `/cognee-link` and confirm the link in a browser where you're logged in to Cognee. **No API key is involved**; if the reply instead tells you to run `` `/cognee-link <api_key>` ``, you're on code from before this was fixed — that argument never existed.
12. **Can't delete a dataset — deletion hangs or errors**: a running Cognee backend holds an **exclusive lock** on the graph database via a worker subprocess. Stop the server first, then delete.
13. **Asking returns an "I don't know"-phrased answer as if it were real**: known limitation — the ask handler substring-matches common refusal phrasings ("cannot answer", "no relevant information", "does not contain", …) before forwarding an answer, but new phrasings can still slip through.

## Related

<CardGroup cols={2}>
  <Card title="dlt Integration" icon="database" href="/integrations/dlt-integration">
    Pull Slack channel history in bulk via dlt, instead of the live bot.
  </Card>

  <Card title="Cloud Integrations UI" icon="puzzle" href="/cognee-cloud/ui/integrations">
    Where "Connect Slack" lives in the Cognee UI.
  </Card>
</CardGroup>
