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
Summary
Add the
/memoryTelegram 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 filterssource="extracted"so the UI is stable regardless of removal timing.Modified files
src/kai/bot.py- add/memorycommand handler (~200-250 lines for all subcommands)tests/test_bot_memory_command.py- new test file for the command handlersrc/kai/memory.py- no new functions expected. Use the existingget_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
/memory/memory <tag>/memory <tag> <page>/memory search <query>/memory review/memory forget <id>/memory forget allTag 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
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
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
Two scores, clearly distinguished:
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 reviewreturns 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.Confirmation quotes
Facts tagged
confirmed_actioncarry aconfirmation_quotefield (required by the extraction schema). Display it inline in drill-down and search so the user can audit why Haiku stored the fact:For non-
confirmed_actionfacts, 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 bychat_id) so the user can/memory search X, see results, then/memory forget 3to delete the third result./memory forget allshows an inline-keyboard confirmation button before proceeding. Irreversible. Backed bydelete_all(user_id=...).Graceful degradation
If the memory system is disabled (
MEMORY_ENABLED=falseor init failure),/memoryresponds with a short message explaining that semantic memory is not active. No partial views or mystery errors.Tests
matchandconflabeled and correct/memory forget <id>deletes the correct fact from the last listing/memory forget allclears all user facts after confirmationconfirmed_actionfacts and is omitted otherwiseDependencies
source="extracted"in the interim so the UI is independent of removal timing.tagsas part of its extraction output, so the dashboard and drill-down work on Haiku's own taxonomy. Topic pre-classification: keyword-based tagger for memory retrieval #309 becomes an optional augmentation (a second source of topic tags if we ever want finer filter resolution), not a gating dependency.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(Telegramchat_id) via Mem0's built-in user isolation.Reference
src/kai/memory_extraction.py:140-183src/kai/memory.py(get_all,search,delete_all,delete_by_source,get_stats)home/docs/memory-system/mempalace-inspired-additions.md