Files
Nikola Živković 3f69682b1c feat(slack): Add /cognee-remember and align command replies with cloud (#4479)
## What

Adds `/cognee-remember` to the SDK's Slack app and brings the two
commands' replies in line with the cloud integration.

`/cognee-remember` fell through to *"Command `/cognee-remember` is not
yet supported."* — remembering was reachable only through the **Remember
this** message shortcut. That shortcut covers what Slack already has on
screen; it cannot cover what Slack never saw, which is most of what's
worth keeping: a decision from a call, a conclusion someone records
after the fact.

## Changes

**New `/cognee-remember <text>`** (`handle_cognee_remember.py`)
- Writes to the same dataset and `node_set` as the shortcut, so both
land as one Slack-origin body of memory rather than two the graph can't
relate.
- Acks inside Slack's 3-second window and saves detached, confirming via
`response_url`. `cognee.remember` resolves — and on a first save,
creates — the dataset before returning even with
`run_in_background=True`, so it can't run inline.
- Refuses an unconnected workspace and an unlinked member *before*
writing: a note landing in the installer's memory because the author
never linked is worse than one refused with a reason.
- Every reply is ephemeral, matching `/cognee-ask` — what someone
commits to memory isn't the app's to announce.

**Fixed the not-linked reply**
`handle_cognee_ask.py` and `handle_slack_interactive.py` both told
people to run `` `/cognee-link <api_key>` `` and create a key from their
API Keys settings. That argument has never existed and the SDK flow uses
no key — leftover from before linking became a magic link. The wording
now lives in `handle_slack_link.py` beside the command it names, so the
three call sites can't drift again.

**Empty-input replies now carry an example** instead of `Usage: ...`,
and acks match cloud's `🔎 Recalling:` / `💾 Remembering:`.

**Manifest** gains the command, plus a note that adding a slash command
to an existing app requires reinstalling it — Slack doesn't grant new
commands to an existing install.

## Unrelated fix, folded in because it blocks verifying any of the above

`GET /datasets/{id}/data` raises `TypeError: dict() got multiple values
for keyword argument 'dataset_id'`. `Data` carries its own `dataset_id`
column now, so `dict(**jsonable_encoder(data), dataset_id=…)` collides
with the encoded row on every call. **Every dataset detail view 500s —
on `dev`, not just here.** A dict literal resolves the duplicate instead
of raising; the requested id still wins, which matters because the
column is nullable. Happy to split this out if you'd rather it land on
its own.

## Testing

205 unit tests pass (was 197). New coverage for `/cognee-remember`:
unconnected workspace, unlinked member, empty text, the
ack/detached-save split, save failure reporting back rather than
raising, and ack truncation not touching the stored note.

Manually verified end to end against a real Slack workspace over ngrok.

## Note

No `/cognee-forget`. cognee can delete a dataset, one item, or
everything — not by description. A command taking a description of a
fact couldn't honour it, and someone believing otherwise is the worst
outcome available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---

## Follow-up commit: the manifest that actually gets installed

`scripts/slack-app-manifest.sdk.yml` — the manifest people install from
when testing the SDK locally — still listed only `/cognee-ask` and
`/cognee-link`. Adding the command to the tracked
`slack-app-manifest.yml` was not enough: an app created from the SDK
manifest can't invoke `/cognee-remember` at all, because Slack refuses
an unregistered command client-side and nothing ever reaches the
backend. It looks exactly like a broken server.

This cost a full debugging session to find, which is the argument
against keeping two manifests for one app. Worth deciding as part of
this PR:

1. **Delete `scripts/slack-app-manifest.sdk.yml`** and drive local
testing off the tracked manifest with a host substitution — one source
of truth, drift impossible.
2. **Keep both** and add a test asserting the two files declare
identical `slash_commands`, so CI catches the next divergence.

I've committed the fix plus a note about the reinstall requirement, but
haven't picked between those — happy to do either.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 13:10:07 +02:00
..