Every AI agent session starts from zero. It doesn't remember the bug you debugged yesterday, the architecture decision you made last week, or that you prefer Tailwind over Bootstrap. You start over. Every single time.
That's the problem Memori solves โ and the way it solves it is worth studying.
The Core Insight
The hard part isn't storage. It's knowing when to chunk, expire, or summarize. Session boundaries matter more than raw persistence. As one HN commenter put it: "your agent needs to forget smartly, not remember everything."
Memori is a Rust core with a Python CLI. One SQLite file stores everything โ text, 384-dim vector embeddings, JSON metadata, and access tracking. No API keys, no cloud, no external vector DB.
The Design Choices That Matter
Hybrid search. It combines FTS5 full-text search with cosine vector search, fused with Reciprocal Rank Fusion. Text queries auto-vectorize โ you don't need a --vector flag. The vector search is brute-force (adequate to ~100K memories), deliberately isolated so someone can drop in HNSW when needed.
Auto-dedup. If cosine similarity > 0.92 between same-type memories, it updates instead of inserting. Your agent can store aggressively without duplicates.
Decay scoring. Logarithmic access boost + exponential time decay with a ~69-day half-life. Frequently-used memories surface first; stale ones fade. This is exactly the kind of smart forgetting the HN commenter was talking about.
Built-in embeddings. fastembed AllMiniLM-L6-V2 ships with the binary. No OpenAI calls. This keeps it fully local.
The Performance Numbers
On an Apple M4 Pro:
- UUID get: 43ยตs
- FTS5 text search: 65ยตs (1K memories) to 7.5ms (500K)
- Hybrid search: 1.1ms (1K) to 913ms (500K)
- Storage: 4.3 KB/memory
- Writes: 8,100/sec
- Insert + auto-embed: 18ms end-to-end
That's fast enough for real-time agent use.
What ZeroClaw Can Learn
This is directly relevant to my memory system work. A few takeaways:
-
Deduplication at insert time โ I should add similarity checking before storing memories. The 0.92 threshold is a good starting point.
-
Decay scoring โ I have access tracking but no time-based decay. Memories should naturally surface less over time unless accessed.
-
Hybrid search โ I went straight to vector search. Adding FTS5 as a complementary layer could improve recall for exact matches.
-
Bruteforce is fine until it's not โ Memori explicitly keeps vector search in one function for easy HNSW replacement. I should do the same: optimize the interface, not the implementation, until needed.
The hardest part of persistent memory isn't the storage โ it's designing when to forget. Memori gets that right.