One agent, one store, zero network.
The bedrock shape. An MCP client spawns ai-memory mcp over stdio, or you run a CLI verb; either way the process opens a SQLite file in-process and the same engine that powers every other tier does the work. Build with SQLCipher and the file is encrypted at rest. Nothing listens on a port unless you ask it to.
Two ways in, one file.
The MCP child and the CLI are separate processes that link the same engine; neither is a client of a daemon. An HTTPS daemon on loopback (TLS even there; this single-operator shape mints and renews a local CA certificate) and a same-host wake hub are optional extras, drawn dashed.
Sources. src/mcp/mod.rs (the stdio server takes a SQLite path), src/profile.rs (core and full profiles), src/cli/store.rs and src/cli/recall.rs (CLI verbs open the store in-process), src/cli/backup.rs, src/cli/doctor.rs; the sqlcipher feature is in Cargo.toml.
One write, one recall.
memory_store
The tool call carries a title, content, tier and namespace. The engine resolves the agent id (from AI_MEMORY_AGENT_ID or --agent-id), consults the namespace standard's governance policy, inserts the row with its tier's TTL (short expires after hours, mid after days, long never) and indexes it for keyword search and, at the semantic tier, an embedding.
memory_recall
The context runs through keyword search on SQLite and the in-process HNSW vector index, the scores are blended, and the scope filter in SQL drops anything the caller may not see. Embeddings come from a local MiniLM model or an OpenAI-compatible endpoint (src/embeddings.rs).
Laptop or single VM, no daemon.
# MCP client config (.mcp.json): spawn the stdio server; it opens SQLite in-process
{ "mcpServers": { "memory": {
"command": "ai-memory",
"args": ["--db", "/home/me/.local/share/ai-memory/ai-memory.db", "mcp", "--profile", "core"]
} } }
# The CLI opens the same file in-process (it is not an HTTP client)
ai-memory --db ~/.local/share/ai-memory/ai-memory.db store -T "build cache" -c "CI uses sccache" -n proj/build
ai-memory --db ~/.local/share/ai-memory/ai-memory.db recall "how do we cache builds" -n proj/build
# Encryption at rest: a SQLCipher build plus a passphrase file
cargo build --release --no-default-features --features sqlcipher
ai-memory --db ~/.local/share/ai-memory/ai-memory.db --db-passphrase-file ~/.config/ai-memory/db.pass mcp --profile core
# Signed snapshots (SQLite only), health
ai-memory --db ~/.local/share/ai-memory/ai-memory.db backup --to ~/ai-memory-backups --keep 48
ai-memory --db ~/.local/share/ai-memory/ai-memory.db restore --from ~/ai-memory-backups --latest
ai-memory --db ~/.local/share/ai-memory/ai-memory.db doctor
Every flag above is a clap argument in src/daemon_runtime.rs, src/cli/store.rs, src/cli/recall.rs or src/cli/backup.rs. Use --profile full when the agent needs the whole tool surface.
What still applies with one agent.
Namespace standards
A namespace standard can already require approval or ownership for writes, promotes and deletes, so a single agent can be fenced out of a namespace it should only read.
signed_events · audit log
The signed_events chain is verifiable with verify-signed-events-chain; the hash-chained audit log is opt-in and checked by audit verify (src/signed_events.rs, src/audit.rs).
Optional, same host
With one agent there is nobody to wake. Add a wake hub when a second agent or an operator tool starts sending messages.
When Tier 1 stops fitting.
| Dimension | Tier 1 behaviour | Move up when |
|---|---|---|
| Writers | One writer at a time on the SQLite file; WAL lets readers pass it. | Several agents write at once: Tier 2. |
| Vectors | HNSW index held in RAM and rebuilt at start-up. | The corpus makes start-up or memory painful: PostgreSQL tier. |
| Remote access | None unless you run serve; it listens with TLS only, loopback by default, and non-loopback binds require an API key. | Agents on other machines need the memory: Tier 3. |
| Durability | One disk. Snapshots with backup; no replication. | You need a second copy that is current: Tier 3. |
| Filesystem | Local disk only; network filesystems are unsafe for SQLite locking. | Always: keep the file on local storage. |
Reasoning for each: architectural limits.