Chat Memory
Chat Memory persists AI agent working context across sessions. When enabled, every tool call is automatically logged — no manual tool call needed. AI restarts sessions with full context from previous work, without re-searching from scratch.
🧠 New in v0.12.0
Hybrid storage: SQLite (full text) + Qdrant (vector embeddings). Auto-track via existing tools, semantic search via chat_context tool, and auto-load via knowledge://context/{project} resource.
Architecture
SAVE:
entry → SQLite (sync, always works)
└→ Ollama embed() → Qdrant (background, fire-and-forget)
LOAD (chronological):
SQLite → all recent entries by time
LOAD (semantic):
query → Ollama embed() → Qdrant search(top-K) → SQLite fetch by ID
→ only returns relevant entries, saves tokens| Storage | Role | Speed |
|---|---|---|
| SQLite | Source of truth — full text, chronological queries | ⚡ Instant |
| Qdrant | Acceleration — vector embeddings, semantic search | 🐢 Network round-trip (background) |
Auto-Track
When CHAT_MEMORY_ENABLED=true, these tools automatically logto chat memory. The AI agent doesn't need to call any additional tool.
| Tool | What Gets Logged |
|---|---|
search | Query + mode + top 5 result files + scores |
smart_context | Task/question + gathered file paths |
code_session | Task + core files + test files + session ID |
💡 Zero friction: Auto-track means the AI agent just does its job — searches, reads context, writes code — and the memory builds up automatically. No manual tool calls, no context rot.
chat_context Tool
The chat_context tool provides manual control over chat memory with 5 actions: save, load, ingest, clear, resource.
Save — Store a single message
chat_context(
action: "save",
project_name: "my-app",
role: "assistant",
content: "Decision: use JWT with refresh tokens for auth flow"
)Ingest — Dump full conversation
Call once at session end to persist the entire conversation.
chat_context(
action: "ingest",
project_name: "my-app",
title: "Fix login bug — June 2026",
messages: [
{ role: "user", content: "fix login bug in auth.ts" },
{ role: "assistant", content: "Found the bug in token validation..." },
{ role: "user", content: "ok, push it" }
]
)Load — Retrieve context
Chronological load — "what were we working on?"
chat_context(
action: "load",
project_name: "my-app",
limit: 20, // max entries (default 20)
max_age_hours: 168 // only within 7 days (default 168)
)Semantic load — "anything about auth rate limiting?"
chat_context(
action: "load",
project_name: "my-app",
semantic_query: "auth rate limiting middleware",
limit: 10
)
// Flow: embed query → Qdrant search → SQLite fetch by ID
// Only returns entries semantically similar to the query.
// Falls back to chronological if Ollama/Qdrant are unavailable.Clear — Delete old entries
chat_context(
action: "clear",
project_name: "my-app",
max_age_hours: 720, // delete entries older than 30 days
thread_id: "ct_abc123" // optional — delete only from this thread
)Resource: knowledge://context/{project}
AI clients automatically read this MCP resource on session startup. No tool call needed — previous context is immediately available.
// AI reads: knowledge://context/my-app
// Returns formatted summary:
## Chat Context for "my-app"
### Fix login bug (4 msgs, 1200 chars, updated 2026-06-16)
👤 User: fix login bug in auth.ts
🛠 system [tool: search]: [keyword] "auth module" → 5 results
🤖 AI [tool: smart_context]: task="fix bug" → 3 files
👤 User: ok, push itSession Lifecycle
Recommended pattern for AI agents using Chat Memory:
SESSION START
→ Resource knowledge://context/my-app auto-loads
→ (Optional) chat_context(action:"load", limit: 10) for more detail
DURING SESSION
→ search / smart_context / code_session → auto-tracked (no action needed)
→ (Optional) chat_context(action:"save", ...) for important notes
SESSION END
→ chat_context(action:"ingest", messages=[entire conversation])
→ (Optional) chat_context(action:"clear", max_age_hours: 720) for cleanup
Configuration
Env Vars
| Var | Default | Purpose |
|---|---|---|
CHAT_MEMORY_ENABLED | false | Master switch — must be true |
CHAT_MEMORY_VECTOR_ENABLED | true | Qdrant vector storage for semantic search |
CHAT_MEMORY_LOAD_LIMIT | 20 | Max entries per load |
CHAT_MEMORY_MAX_AGE_HOURS | 168 | Only load entries within 7 days |
CHAT_MEMORY_THREAD_TTL_MS | 3600000 | Reuse latest thread if within 1 hour |
Minimal Setup
# Enable chat memory (SQLite-only — no Qdrant/Ollama needed for memory)
CHAT_MEMORY_ENABLED=true
CHAT_MEMORY_VECTOR_ENABLED=falseFull Setup (recommended)
# Enable with semantic search (requires Ollama + Qdrant)
CHAT_MEMORY_ENABLED=true
CHAT_MEMORY_VECTOR_ENABLED=trueBest Practices
- Ingest at session end — dump entire conversation once, not after every message.
- Use semantic search for specific topics — when looking for past discussions on a topic, use
semantic_queryto get only relevant entries. - Use chronological load for resuming — when resuming a session, use chronological load to see everything in order.
- Clear periodically — clean up entries older than 7-30 days to keep the database lean.
- Adjust thread TTL — set
CHAT_MEMORY_THREAD_TTL_MSto match your work patterns (short sessions = lower TTL). - Let auto-track work — don't call
chat_contextduring normal work; auto-track handles search and context calls automatically.
Storage Details
| Detail | Value |
|---|---|
| SQLite tables | chat_threads + chat_context in knowledge.db |
| Qdrant collection | mcp_cc_{project_name} |
| Vector model | Same as code embeddings — OLLAMA_MODEL |
| Embedding timing | Fire-and-forget (background, doesn't block response) |
| Fallback | Semantic load falls back to chronological if Ollama/Qdrant are down |