Mnemo
by oyekamal
README.md
# ποΈ Mnemo β the agent that never forgets
> A standalone AI assistant with a **persistent, temporal memory brain**. Tell it something in one session; ask about it in a completely new session and it recalls it β with who, what, *and when* β citing its sources.
Mnemo pairs a **temporal knowledge graph** ([Graphiti](https://github.com/getzep/graphiti) on [FalkorDB](https://www.falkordb.com/)) with a **Claude-session harness** (MCP tools + hooks + skills), so any Claude Code session can `remember` and `recall` across time. Its persona is *the archivist*: precise, unhurried, and it never states a fact without saying where and when it was true.
```
you (session 1): "Remember: Marco leads Solaris; it launches Q4 2027; it depends on Helios."
you (session 2): "Who leads Solaris, when does it launch, what does it depend on?"
Mnemo: Lead: Marco Β· Launch: Q4 2027 Β· Depends on: Helios API (as of 2026-07-17)
```
---
## How it works
Mnemo has two layers, exactly like a well-run agent: a **git-versioned identity** (markdown) and a **memory brain** (a graph database). A thin connection layer (MCP + hooks) plugs that brain into any Claude session.
```mermaid
flowchart TB
subgraph SESSION["π§ Claude session (this repo, any repo, or Claude Desktop)"]
Q["You ask a question<br/>or state a fact"]
end
subgraph CONNECT["π Connection layer"]
direction LR
MCPR["recall tool"]
MCPM["remember tool"]
SS["SessionStart hook<br/>Β· ensure DB up<br/>Β· surface tools"]
STP["Stop hook<br/>Β· auto-learn:<br/>summarize + ingest"]
end
subgraph BRAIN["πΎ Memory brain"]
direction LR
GR["Graphiti<br/>extract entities + typed edges<br/>bi-temporal validity"]
FDB[("FalkorDB<br/>property graph")]
EMB["fastembed<br/>local embeddings"]
end
Q -->|"tell"| MCPM --> GR
Q -->|"ask"| MCPR --> GR
GR <--> FDB
GR <--- EMB
SS -.injects context.-> SESSION
STP --> GR
```
**Ingest and recall** β remembering turns text into a graph; recalling runs a hybrid search over it and answers in persona:
```mermaid
flowchart LR
T["raw text<br/>(who / what / when)"] --> RM["remember()"]
RM --> EX["Graphiti extraction<br/>Β· entities as typed nodes<br/>Β· relationships as typed edges<br/>Β· dates/status as node attributes"]
EX --> KG[("FalkorDB<br/>temporal property graph")]
QQ["a question"] --> RC["recall()"]
KG --> HS["hybrid search_()<br/>vector + BM25 + graph traversal"]
RC --> HS
HS --> CTX["facts + entity attributes + source excerpts"]
CTX --> ANS["Claude answers in the<br/>archivist persona, with citations"]
```
**Why memory survives across sessions** β nothing is shared between sessions except the graph on disk:
```mermaid
sequenceDiagram
participant S1 as Session 1 (Mon)
participant M as Mnemo
participant DB as FalkorDB (volume)
participant S2 as Session 2 (Fri Β· fresh process)
S1->>M: remember("Marco leads Solaris, launches Q4 2027")
M->>DB: extract β nodes + typed edges + valid-time
Note over S1,DB: session ends β Stop hook summarizes & ingests it too
S2->>M: recall("who leads Solaris? when?")
M->>DB: hybrid search (edges + nodes + episodes)
DB-->>S2: Marco Β· Q4 2027 (cited, as-of dated)
```
### The pieces
| Piece | File | Role |
|---|---|---|
| Identity | `personality.md`, `CLAUDE.md` | The archivist persona + operating rules (git-versioned) |
| Graph types | `mnemo/types.py` | Custom entities (`Project, Feature, Person, Meeting, Company`) + typed edges (`BelongsTo, WorksOn, Said, DependsOn, Attended`); dates/status/roles captured as **node attributes** |
| Memory wrapper | `mnemo/memory.py` | `ingest()` and `recall()` β recall uses Graphiti's `search_()` (edges **+** nodes **+** episodes), not the edge-only default |
| MCP server | `mnemo/mcp_server.py`, `.mcp.json` | Exposes `recall` / `remember` as MCP tools to any Claude session |
| Hooks | `.claude/hooks/` | SessionStart (ensure DB up, surface tools) Β· Stop (detached auto-learn worker) |
| Auto-learn worker | `mnemo/ingest_session.py` | Summarizes a finished session and ingests it (kill-switch: create `.mnemo-nolearn`) |
| Skills | `.claude/skills/{recall,remember}` | Ergonomic in-session use |
| Agent | `mnemo/agent.py` | Recalls, then answers in persona with citations |
Embeddings run **locally** (`fastembed`, 384-dim) so no embeddings key is needed; the LLM (extraction + answers) is **Claude**, and the client accepts both a standard `sk-ant-api03` key **and** a Claude Code `sk-ant-oat` OAuth token.
---
## How Mnemo compares
Most "AI memory" is either a flat vector store (good at *similar text*, blind to *relationships* and *time*) or an opaque per-user blob you can't inspect. Mnemo is a **temporal knowledge graph** with a Claude-native connection layer.
| Capability | **Mnemo** | Vanilla RAG (vector DB) | Mem0 | Raw Graphiti / Zep | Letta (MemGPT) | ChatGPT-style memory |
|---|:--:|:--:|:--:|:--:|:--:|:--:|
| Storage model | temporal property graph | flat chunks + vectors | vectors (+opt. graph) | temporal graph | tiered memory blocks | opaque per-user store |
| Typed relationships (whoβwhat) | β
| β | partial | β
| β | β |
| Temporal "as-of" / fact invalidation | β
bi-temporal | β | limited | β
| β | β |
| Hybrid retrieval (vector + BM25 + graph) | β
| vector only | vector | β
| n/a | n/a |
| Cross-session persistence | β
| β
(if wired) | β
| β
| β
| β
(per user) |
| Auto-learns from each session | β
(Stop hook) | β | manual | β (library) | β
| β
|
| Claude Code / MCP native (drop-in tools + hooks) | β
| β | β | β | β | β |
| Runs fully local (offline embeddings) | β
fastembed | depends | depends | depends | depends | β cloud |
| Works with a Claude Code OAuth token | β
| n/a | n/a | n/a | n/a | n/a |
| Inspectable + cites source & time | β
| β | β | partial | partial | β |
**Where Mnemo sits:** it is *not* a competitor to Graphiti β it is **built on Graphiti**. Think of it as **Graphiti (the brain) + a Claude-session body**: the MCP tools, the SessionStart/Stop hooks, the archivist persona, and the operational glue (OAuth-token auth, local embeddings, portable `${CLAUDE_PROJECT_DIR}` config, comprehensive `search_()` recall) that turn a memory *library* into a memory *agent* you can talk to.
**vs. a Notion/RAG-backed assistant** (e.g. an agent whose "memory" is a Notion database): those retrieve documents by similarity. Mnemo retrieves *facts and their relationships over time* β it can answer "who **used to** own this, and who owns it **now**", which flat retrieval cannot.
### What Mnemo is **not** (yet)
Honest scope β it's an experiment, not a product:
- No multi-user / auth on the graph β single local user.
- No managed hosting or horizontal scale (FalkorDB is a local Docker container).
- Extraction is LLM-driven and ~good, not perfect β occasionally a detail is missed (it will say "not found" rather than hallucinate).
- Auto-learned summaries vary in quality; recall-heavy sessions produce thin summaries.
- No daemon; the brain is up while `docker compose` is running.
---
## Quickstart
```bash
git clone <this repo> && cd mnemo-agent
cp .env.example .env # set ANTHROPIC_API_KEY (sk-ant-api03 key OR sk-ant-oat token)
docker compose up -d # start FalkorDB (defaults to port 6380)
python -m venv .venv && . .venv/bin/activate && pip install -r requirements.txt
python scripts/seed.py # load the fictional sample data (Atlas project)
pytest -v # prove it: ingest + recall + temporal, all live
```
Then talk to it from any Claude Code session in this repo β the SessionStart hook wires the `recall`/`remember` tools automatically. To use Mnemo from *any* repo or Claude Desktop, add the `.mcp.json` server to your global config.
## Verified behaviour
Proven live (see the test suite + `docs/`):
- **Cross-session:** store in one `claude` process, recall in a separate one β including dates and dependencies.
- **Temporal:** after a reassignment, "who **currently** owns X" returns the new owner, not the stale one (edge invalidation).
- **Durable:** survives a `docker compose restart` (data in the FalkorDB volume).
- **MCP transport:** tools list and call over the real MCP stdio protocol.
- **Auto-learn:** finished sessions are summarized and ingested by the Stop hook.
## Design & internals
- `docs/2026-07-16-mnemo-agent-design.md` β the design spec.
- `docs/agent-memory-plan.md` β the graph-first memory model this is built on (why a graph, not a flat table; the 3-tier idea; engine selection).
## Tech stack
Python 3.12 Β· [Graphiti](https://github.com/getzep/graphiti) `graphiti-core` Β· [FalkorDB](https://www.falkordb.com/) (Docker) Β· [Anthropic Claude](https://www.anthropic.com/) (extraction + answers) Β· [fastembed](https://github.com/qdrant/fastembed) (local embeddings) Β· [MCP](https://modelcontextprotocol.io/) (FastMCP) Β· pytest.
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues