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

The ai-memory system implements a dual-layer architecture where markdown files serve as the single source of truth while a SQLite index provides fast retrieval, organized into eight single-responsibility crates that communicate through strict typed APIs and invariants.

The ai-memory project by akitaonrails is a local-first memory system designed for AI agents and developer workflows. Understanding the core architecture of ai-memory reveals how it balances durability, searchability, and auditability without requiring external LLM providers by default.

Dual-Layer Storage Model

The foundation of ai-memory rests on a strict separation between authoritative storage and derived indices.

Markdown Wiki as Source of Truth

All knowledge persists as markdown files in <data_dir>/wiki/. This layer remains the authoritative representation of memory through several mechanisms:

  • Atomic writes: All file operations use a temporary file + rename + fsync pattern to guarantee crash safety
  • Git versioning: The ai-memory-wiki crate integrates git2 for automatic versioning of all changes
  • Human-readable: Files remain accessible via standard text editors and command-line tools

As documented in docs/ARCHITECTURE.md, writes to the wiki layer trigger corresponding updates to the derived index, never the reverse.

SQLite-Driven Derived Index

The <data_dir>/db/memory.sqlite database mirrors the wiki for high-performance access patterns:

  • WAL mode: SQLite operates in Write-Ahead Logging mode for concurrent read performance
  • Single-writer actor: The ai-memory-store crate implements an actor pattern where a single connection owns all writes, eliminating race conditions
  • Rich metadata: Stores embeddings, session observations, handoffs, and cross-project link graphs

The ReaderPool in crates/ai-memory-store/src/lib.rs manages a pool of read-only connections for query operations, while the writer actor序列所有 mutations.

Modular Crate Architecture

The codebase organizes into eight independent crates under crates/, each enforcing a single responsibility:

  • ai-memory-core/: Domain types, IDs, and error variants—zero I/O operations
  • ai-memory-store/: SQLite writer actor, reader pool connection management, and decay mathematics
  • ai-memory-wiki/: Atomic markdown writes, file-watcher implementation, and Git handling
  • ai-memory-mcp/: RMCP transport layer, tool routing, and admin HTTP endpoints
  • ai-memory-hooks/: Hook payload schemas, sanitization logic, and the /hook endpoint handler
  • ai-memory-llm/: Provider authentication, LlmProvider and Embedder trait definitions
  • ai-memory-consolidate/: Karpathy-style ingestion pipeline, linting, and auto-improvement scheduling
  • ai-memory-workstream/: Read-only native transcript adapters and launch integrations
  • ai-memory-cli/: The ai-memory binary entry point and subcommand dispatch in src/main.rs

Each crate exposes typed APIs; no crate accesses another's internal data structures directly. This enforces cross-cutting invariants like "typed 3-tuple identity" (workspace_id, project_id, path) and single configuration paths.

Steady-State Data Flow

The system processes agent observations through a six-stage pipeline:

  1. Lifecycle hook: External agent CLIs POST JSON events to /hook with a strict ≤200ms timeout (fire-and-forget)
  2. Sanitization: The ai-memory-hooks sanitiser acts as the only trust boundary between untrusted input and storage
  3. WriteCmd enqueue: Sanitized observations route to the writer actor, which persists to SQLite and creates wiki pages when necessary
  4. Session termination: On session-end events, the server synthesizes sessions/<id>.md, creates handoff rows, and commits wiki updates atomically
  5. LLM consolidation: If AI_MEMORY_LLM_PROVIDER is configured, memory_consolidate rewrites summaries into richer conceptual pages (concepts/, decisions/)
  6. Auto-improvement: Background jobs in ai-memory-consolidate review completed sessions and generate proposals through the standard wiki mutation path

This flow ensures all edits remain auditable through Git history while supporting real-time agent integrations.

Multi-Stream Retrieval Pipeline

The memory_query function implements Reciprocal Rank Fusion (RRF) across four parallel search streams:

Stream Index Type Search Target
FTS5 Full-text Page titles and bodies
Entity Front-matter entities list in YAML headers
Link-neighbour Graph Wikilink relationships
Vector Cosine similarity Embedding space (when Embedder configured)

Results merge with authority multipliersbased on tier (Working, Episodic, Semantic, Procedural), pinned status, and calculated salience. When AI_MEMORY_RERANKER=llm is set, a final LLM-based reranking pass reorders the result set.

Memory Tiers and Decay System

Pages categorize into four lifecycle tiers, each with distinct retention policies:

  • Working: Active session data with short TTL
  • Episodic: Past session summaries
  • Semantic: Conceptual knowledge and decisions
  • Procedural: How-to guides and instructions

A periodic forget sweep (implemented in ai-memory-store) applies tier-specific decay formulas, evicts cold pages, hard-deletes TTL-expired entries, and prunes raw observations while pinned pages remain exempt from all decay.

Security and Cross-Cutting Invariants

The architecture enforces strict invariants at the type system level:

  • Single-writer SQLite: Prevents concurrent write transactions entirely
  • Sanitiser isolation: Only path from untrusted hook data to storage
  • Atomic wiki operations: Guarantees filesystem consistency via fsync
  • Typed IDs: Every row enforces workspace_id, project_id, and path as a composite key
  • Zero-LLM default: Core functionality works without any AI_MEMORY_LLM_PROVIDER configured

These invariants are enumerated in docs/ARCHITECTURE.md under Cross-cutting invariants.

Summary

  • ai-memory uses a dual-layer design with markdown as the source of truth and SQLite for fast access
  • Eight single-responsibility crates in crates/ enforce strict API boundaries and typed IDs
  • The single-writer actor pattern in ai-memory-store eliminates SQLite concurrency issues
  • RRF retrieval combines FTS5, entity matching, link graphs, and optional vector similarity
  • Memory tiers with decay formulas and pinned exemptions manage storage lifecycle
  • All mutations flow through the wiki layer, ensuring Git-auditable history without LLM dependencies

Frequently Asked Questions

How does ai-memory ensure consistency between the markdown wiki and SQLite index?

All writes originate in the wiki layer through atomic file operations (tmp + rename + fsync) in ai-memory-wiki, then propagate to the SQLite index via the single-writer actor in ai-memory-store. The wiki remains the authoritative source; the database is purely a derived view. If the database corrupts, it can rebuild entirely from the markdown files.

What is the single-writer actor pattern used in ai-memory-store?

The ai-memory-store crate implements an actor pattern where one dedicated connection handles all write operations through a message queue. This design eliminates SQLite's "database is locked" errors without complex retry logic, while a separate ReaderPool manages multiple read-only connections for concurrent queries.

Can ai-memory function without connecting to an LLM provider?

Yes. The system operates in zero-LLM default mode. All core features—wiki storage, SQLite indexing, session tracking, and decay management—work without any AI_MEMORY_LLM_PROVIDER configuration. LLM integration only enables optional features like semantic search embeddings, consolidation rewriting, and LLM-based result reranking.

How does cross-project linking work in the wiki architecture?

Wikilinks support the syntax [[project:path.md]] to reference pages across workspaces. The wiki parser extracts a LinkTarget { workspace, project, path } struct, and the store records these with to_workspace and to_project columns. This enables a global dependency graph while maintaining scope isolation, allowing agents to trace relationships across project boundaries without namespace collisions.

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 →