Skip to content

/memory Telegram command: browse, search, and manage memories #310

@dcellison

Description

@dcellison

Summary

Add the /memory Telegram command, giving users a first-class interface to browse, search, and manage what Kai remembers about them. This is the trust and transparency feature: users can see exactly what is stored, how confident Haiku was when it stored it, verify accuracy, and delete anything they want removed. Also a tuning instrument: low-confidence extractions are visible, so prompt regressions become fixable instead of invisible.

No other AI assistant offers browsable, user-controlled semantic memory. ChatGPT shows a flat list with no structure or search. Claude shows "project knowledge" with no visibility into what it actually uses. Kai lets the user run the same semantic search the system uses internally and see the results with relevance scores alongside extraction confidence.

Parent issue: #306

Scope

What this operates on

Haiku-extracted facts only (Track 2, source="extracted"). Track 1 (raw turn embeddings) is being removed under a sibling issue; once that lands, Qdrant contains extracted facts exclusively and no source filter is needed. Until it lands, the handler filters source="extracted" so the UI is stable regardless of removal timing.

Modified files

  • src/kai/bot.py - add /memory command handler (~200-250 lines for all subcommands)
  • tests/test_bot_memory_command.py - new test file for the command handler
  • src/kai/memory.py - no new functions expected. Use the existing get_all, search, delete_all, delete_by_source. If aggregation in Python becomes slow at scale, add a Qdrant-side helper then, not now.

Design

Subcommands

Command Behavior
/memory Dashboard: total fact count and breakdown by tag
/memory <tag> Paginated listing of facts in that tag, sorted by recency
/memory <tag> <page> Navigate to a specific page
/memory search <query> Semantic search with relevance scores shown
/memory review Lowest-confidence facts, ascending, for tuning
/memory forget <id> Delete a fact by position in the most recent listing
/memory forget all Delete all facts for this user (inline-keyboard confirmation)

Tag enum (from src/kai/memory_extraction.py:149-163)

Haiku emits 1 to 4 tags per fact from this closed set of nine: preference, decision, fact, constraint, confirmed_action, project, location, schedule, relationship. The dashboard aggregates on these; no keyword re-tagging is required.

Dashboard example

Memory: 134 facts across 7 tags

  preference        42
  fact              31
  project           18
  decision          14
  confirmed_action  12
  constraint         9
  schedule           5
  location           2
  relationship       1

Built by iterating get_all(user_id) and counting tag occurrences in Python. Aggregation happens server-side (no LLM call, no vector search), so the response is instant at expected row counts.

Topic drill-down example

preference (42 facts, showing 1-10 of 42)

1. [Apr 17, conf 0.95] Uses metric except for small measurements,
   where the unit-to-mental-picture mapping matters.
2. [Apr 15, conf 0.90] Never hard-wraps paragraphs; each is one line.
3. [Apr 14, conf 0.88] Prefers concise, chat-friendly responses.
...

Page 1/5  |  /memory preference 2  for next page

Each line shows creation date and the confidence Haiku assigned at extraction time. Low-confidence facts stand out visually, which is the first step in the tuning workflow.

Search example

Search: "memory system architecture" (4 results)

1. [match 0.91, conf 0.90] Track 1 dropped Apr 17 2026: only Haiku-
   extracted facts write to Qdrant.
2. [match 0.84, conf 0.95] Spec 320 merged via PR #333 after 8
   review rounds.
3. [match 0.81, conf 0.85] Mem0 v2.0.0 requires explicit
   embedding_model_dims.
4. [match 0.72, conf 0.80] Memory foundation (#307) landed with
   Qdrant + sentence-transformers.

Two scores, clearly distinguished:

  • match (0.0 to 1.0): semantic similarity between the query and the stored fact, computed at query time.
  • conf (0.5 to 1.0): Haiku's self-assessed confidence at extraction time, stored with the fact.

The first tells the user how relevant the result is to this query; the second tells them how reliable the fact itself is. Different questions, different numbers, visibly distinct labels.

Review (tuning) view

/memory review returns the 20 lowest-confidence facts for the user, sorted ascending by confidence. Purpose: make tuning a one-command workflow. Look at what Haiku was least sure about, delete noise, adjust the extraction prompt if a pattern emerges.

Review: lowest-confidence facts (20 shown)

1. [conf 0.52, Apr 12, fact] The Mac mini has 16GB of RAM.
2. [conf 0.55, Apr 9, preference] Likes cooler rooms.
3. [conf 0.58, Apr 3, project] Phi uses Haskell for its parser.
...

/memory forget <id>  to delete any row above

Confirmation quotes

Facts tagged confirmed_action carry a confirmation_quote field (required by the extraction schema). Display it inline in drill-down and search so the user can audit why Haiku stored the fact:

1. [Apr 17, conf 0.95, confirmed_action] User merged PR #333.
   quote: "I see PR #333 is merged, thanks for landing it"

For non-confirmed_action facts, the quote field is absent and nothing extra is rendered.

Deletion

/memory forget <id> deletes by position in the most recent listing (1-indexed). Pagination state is ephemeral (dict keyed by chat_id) so the user can /memory search X, see results, then /memory forget 3 to delete the third result.

/memory forget all shows an inline-keyboard confirmation button before proceeding. Irreversible. Backed by delete_all(user_id=...).

Graceful degradation

If the memory system is disabled (MEMORY_ENABLED=false or init failure), /memory responds with a short message explaining that semantic memory is not active. No partial views or mystery errors.

Tests

  • Dashboard returns correct tag counts across mixed-tag facts
  • Topic drill-down paginates correctly at various page sizes
  • Search returns results with both match and conf labeled and correct
  • Review returns the 20 lowest-confidence facts in ascending order
  • /memory forget <id> deletes the correct fact from the last listing
  • /memory forget all clears all user facts after confirmation
  • Empty states: zero memories, unknown tag, zero search results, zero low-confidence facts
  • Graceful degradation when the memory system is disabled
  • Multi-user isolation: one user cannot browse or delete another user's facts
  • Confirmation quote renders for confirmed_action facts and is omitted otherwise

Dependencies

Risk

Low. Read-only commands (dashboard, drill-down, search, review) carry no risk. Deletion by position uses an explicit per-chat listing state, so there is no way to accidentally delete "any memory shaped like X". Bulk delete requires a confirmation keyboard press. All operations scope by user_id (Telegram chat_id) via Mem0's built-in user isolation.

Reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions