Core Architecture of ai-memory: A Dual-Layer Memory System for AI Agents

The core architecture of ai-memory is a dual-layer system that uses a markdown wiki as the single source of truth and a SQLite-driven index for fast retrieval, organized into 8 independent Rust crates with strict single-responsibility boundaries.

The ai-memory project by akitaonrails implements a persistent memory layer for AI agents. Its architecture prioritizes durability, auditability, and retrieval performance through a clear separation between human-readable storage and machine-optimized indexing.

Dual-Layer Data Model

The foundation of ai-memory rests on two distinct storage layers that remain synchronized through controlled write paths.

Wiki Layer: The Source of Truth

All knowledge lives as markdown files in <data_dir>/wiki/. This design choice guarantees that your memory remains human-inspectable and version-controllable.

Key characteristics:

  • Atomic writes — every mutation uses a temporary file, rename, and fsync sequence
  • Git versioning — powered by git2 for complete audit history
  • Authoritative state — the wiki is the ground truth; the database is a derived view

SQLite Index: The Fast Mirror

The derived index at <data_dir>/db/memory.sqlite enables efficient search and metadata queries.

Critical implementation details:

  • WAL mode for concurrent reads during writes
  • Single-writer actor owns the write connection, eliminating race conditions
  • Mirrors sessions, observations, handoffs, embeddings, and link graphs

This pattern appears in crates/ai-memory-store/src/lib.rs, where the writer actor enforces sequential consistency without locks.

Crate Layout and Responsibility Boundaries

The codebase follows a strict vertical slice organization. Each crate has exactly one reason to change and communicates only through typed APIs.

Crate Responsibility I/O Status
ai-memory-core Domain types, IDs, errors No I/O
ai-memory-store SQLite writer actor, reader pool, decay math Database I/O
ai-memory-wiki Atomic markdown writes, file-watcher, Git handling Filesystem I/O
ai-memory-mcp RMCP transport, tool router, admin routes Network I/O
ai-memory-hooks Hook payload schemas, sanitiser, /hook endpoint Network I/O
ai-memory-llm Provider auth, LlmProvider / Embedder traits External API
ai-memory-consolidate Karpathy-style ingest, lint, auto-improve pipeline Pipeline I/O
ai-memory-workstream Read-only native transcript + launch adapters Filesystem I/O
ai-memory-cli ai-memory binary entry point All orchestrated

This structure prevents direct data structure coupling. A crate cannot bypass another's API to touch internal state.

Steady-State Data Flow

The core architecture of ai-memory processes agent lifecycle events through a deterministic pipeline.

1. Lifecycle Hook Reception

Agent CLIs post JSON events to POST /hook. This endpoint is fire-and-forget with a hard 200 ms timeout — the system never blocks agents.

2. Payload Sanitisation

The hook router in ai-memory-hooks performs the sole trust boundary transformation. Untrusted input is validated and normalized here exclusively.

3. Write Actor Enqueue

Sanitized observations become WriteCmd messages dispatched to the single-writer actor. The actor:

  • Persists to SQLite
  • Creates or updates wiki pages when session summaries are needed

4. Session Completion

On session-end events, the system:

  • Synthesizes sessions/<id>.md
  • Creates a handoff row for context continuity
  • Commits the wiki update atomically

5. Optional LLM Consolidation

When AI_MEMORY_LLM_PROVIDER is configured, memory_consolidate from ai-memory-consolidate rewrites summaries into richer structures:


concepts/
decisions/
procedures/

6. Auto-Improvement Background Jobs

The scheduler in ai-memory-consolidate reviews completed sessions, generates improvement proposals via LLM, and writes them through the standard wiki path — maintaining full auditability.

Example scheduler invocation:

// In a tokio task started by the server
ai_memory_auto_improve::scheduler::run(pool.clone()).await?;

Retrieval Pipeline: Multi-Stream RRF

The memory_query system implements Reciprocal Rank Fusion across multiple search streams.

Stream Search Target Implementation Location
FTS5 Page titles and bodies SQLite FTS5 virtual table
Entity match Front-matter entities list Indexed entity column
Link-neighbour Wikilink graph to_workspace / to_project columns
Vector (optional) Cosine similarity When embedder configured

Post-fusion, results are re-ranked using authority multipliers:

  • Tier (Working > Episodic > Semantic > Procedural)
  • Pinned status
  • Computed salience

Optional LLM reranker activates with AI_MEMORY_RERANKER=llm.

Query example via MCP tool:

{
  "tool": "memory_query",
  "arguments": {
    "q": "how to reset a project",
    "scopes": ["my-workspace/my-project"]
  }
}

Memory Tiers and Decay System

Pages are categorized into four lifetime tiers with distinct decay formulas:

  • Working — active session context, shortest decay
  • Episodic — event sequences, medium decay
  • Semantic — facts and concepts, slow decay
  • Procedural — how-to knowledge, very slow decay

Pinned pages are exempt from all decay.

The forget sweep periodic job:

  1. Evicts cold pages to archive
  2. Hard-deletes TTL-expired pages
  3. Prunes old raw observations

This logic resides in crates/ai-memory-store alongside the decay mathematics.

Cross-Project Linking

Wikilinks support workspace-spanning references using the syntax [[project:path.md]].

The parser extracts a structured LinkTarget:

LinkTarget {
    workspace: Option<String>,
    project: Option<String>,
    path: String,
}

Storage records include to_workspace and to_project columns, enabling global dependency graphs while maintaining scope isolation.

Security and Cross-Cutting Invariants

The architecture of ai-memory enforces safety through structural constraints:

  • Single-writer SQLite — prevents concurrent write corruption
  • Sanitiser-only inbound path — all untrusted data flows through one validator
  • Atomic wiki operations — crash-safe persistence guarantees
  • Typed 3-tuple identity — (workspace_id, project_id, path) enforced in every row
  • Zero-LLM default — fully functional without external AI providers

These invariants are documented in docs/ARCHITECTURE.md and codified in the type system.

Key Source Files

Path Purpose
docs/ARCHITECTURE.md Human-readable architectural overview
crates/ai-memory-core/src/lib.rs Domain types with zero I/O
crates/ai-memory-store/src/lib.rs Writer actor and reader pool
crates/ai-memory-wiki/src/lib.rs Atomic markdown and Git
crates/ai-memory-mcp/src/lib.rs RMCP transport layer
crates/ai-memory-llm/src/lib.rs Provider abstraction
crates/ai-memory-consolidate/src/lib.rs Auto-improvement pipeline
crates/ai-memory-cli/src/main.rs Binary entry point

Summary

  • Dual-layer design: Markdown wiki as source of truth, SQLite for speed
  • Single-responsibility crates: 8 specialized packages with typed APIs
  • Deterministic flow: Hooks → sanitise → writer actor → wiki + index
  • Multi-stream retrieval: FTS5, entities, links, and vectors with RRF fusion
  • Tiered decay: Automatic lifetime management with pin exemptions
  • Zero-LLM baseline: Works without external AI, enhanced when configured

Frequently Asked Questions

How does ai-memory prevent data corruption during crashes?

The wiki layer uses atomic file operations: write to temporary file, fsync, then rename into place. This guarantees that the filesystem always contains a complete, valid file — never a partially-written state. The SQLite layer uses WAL mode for similar durability guarantees.

Can ai-memory work entirely offline without any LLM provider?

Yes. The system defaults to zero-LLM operation. All core functionality — storage, retrieval, session tracking — works without external AI. LLM features like memory_consolidate and auto-improvement are strictly optional enhancements activated by setting AI_MEMORY_LLM_PROVIDER.

What prevents multiple agents from corrupting the SQLite database?

A single-writer actor pattern enforces sequential access. All write operations route through one asynchronous task that owns the write connection. Reader pools provide concurrent read access, but writes are strictly serialized without locks or conflicts.

How does the retrieval ranking combine different search signals?

The memory_query implementation uses Reciprocal Rank Fusion (RRF) to merge FTS5, entity, link, and vector streams. Each stream produces ranked results; RRF computes a fused score that democratically combines rankings without requiring score calibration. Final re-ranking applies authority multipliers for tier, pinning, and salience.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →