Skip to main content

Overview

NullClaw’s memory system is a custom-built hybrid search engine with:
  • Zero external dependencies (SQLite FTS5 + custom vector math)
  • Multiple backends: SQLite, Markdown, Redis, PostgreSQL, LanceDB, API, in-memory LRU
  • Hybrid search: Weighted merge of keyword (FTS5/BM25) + vector (cosine similarity)
  • Lifecycle management: Automatic hygiene (archive/purge stale memories), snapshot export/import
  • Embedding providers: OpenAI, Gemini, Voyage, Ollama, custom

Memory Interface

Memory Backends

Hybrid Search Architecture

Layer A: Primary Store

Persists structured knowledge:
Categories:
  • core — Long-term facts (“Alice prefers vim”)
  • daily — Today’s context (“Meeting at 3pm”)
  • conversation — Session-specific (“User asked about X”)
  • Custom — Project-specific (e.g., "project_alpha")

Layer B: Retrieval Engine

Merges multiple search sources: Sources:
  • Primary adapter: Keyword (FTS5) + vector (cosine similarity)
  • QMD adapter: Grep-based search on workspace .md files (IDENTITY.md, TOOLS.md, etc.)
Merge strategy: Reciprocal Rank Fusion (RRF) + temporal decay

Layer C: Vector Plane

Optional vector search subsystem: Components:
  • Embedding provider: OpenAI, Gemini, Voyage, Ollama
  • Vector store: SQLite (shared or sidecar), Qdrant, pgvector
  • Circuit breaker: Auto-disable on repeated failures
  • Outbox: Durable async sync queue (SQLite-backed)

Layer D: Lifecycle

Hygiene (automatic cleanup):
  • Archive stale memories after N days (moved to archive.db)
  • Purge ancient memories after M days (deleted)
  • Conversation retention (session-specific entries expire)
Configuration:
Snapshot (export/import):
Response cache (LLM deduplication):
Cache key: sha256(system_prompt + messages + model + temperature)

Configuration

SQLite Backend (Default)

Store modes:
  • auto — sqlite_shared if primary is SQLite, else sqlite_sidecar
  • sqlite_shared — Reuses primary backend’s SQLite db (single file)
  • sqlite_sidecar — Separate vectors.db file
  • qdrant — Qdrant vector database (requires qdrant_url)
  • pgvector — PostgreSQL pgvector extension (requires postgres.url)

Embedding Providers

Supported providers:
  • OpenAI: text-embedding-3-small, text-embedding-3-large, text-embedding-ada-002
  • Gemini: text-embedding-004
  • Voyage: voyage-3, voyage-3-lite
  • Ollama: Local models (e.g., nomic-embed-text)
API key resolution: OPENAI_API_KEY, GEMINI_API_KEY, VOYAGE_API_KEY, or config.

QMD (Query Markdown Documents)

Search workspace markdown files:
Searches: IDENTITY.md, TOOLS.md, AGENTS.md, SOUL.md, custom paths.

Reliability

Rollout modes:
  • on — Hybrid search always
  • off — Keyword-only search always
  • canary — Hybrid for N% of queries (config: canary_percent)
  • shadow — Hybrid runs in background, serves keyword results (comparison)
Fallback policies:
  • degrade — Fall back to keyword-only on vector failures
  • fail_fast — Abort runtime init if vector plane fails

Hybrid Search Flow

Search Pipeline Stages

  1. Query expansion (optional): Generate synonyms/variations
  2. Adaptive analysis (optional): Classify query intent (factual vs. semantic)
  3. Retrieval: Fetch candidates from all sources
  4. RRF merge: Combine results with reciprocal rank fusion
  5. Temporal decay: Boost recent memories
  6. LLM rerank (optional): Use LLM to reorder results
  7. MMR diversification (optional): Maximal marginal relevance
Configuration:

Memory Tools Integration

Agent tools interact with memory runtime:

memory_store

Flow:
  1. memory.store(key, content, category, session_id)
  2. Async vector sync (if enabled):
    • Embed content via embedding provider
    • Upsert to vector store
    • Errors logged, never block

memory_recall

Flow:
  1. memory_runtime.search(query, limit, session_id)
  2. Rollout decision (keyword-only vs. hybrid)
  3. Retrieval engine merges sources
  4. Returns scored candidates

Vector Sync Modes

Best-Effort (Default)

Immediate, non-blocking:
  • Embeds content
  • Upserts to vector store
  • Errors logged, never propagated
  • Circuit breaker disables on repeated failures

Durable Outbox

Queued, retryable:
Flow:
  1. store() enqueues to SQLite outbox table
  2. drainOutbox() called periodically (after each agent turn)
  3. Retries on failure (exponential backoff)
  4. Deletes from outbox on success

Migration & Interop

Import from OpenClaw

Migrates:
  • Memory entries from ~/.openclaw/brain.db (SQLite)
  • Config from ~/.openclaw/config.json
  • Identity files from ~/.openclaw/workspace/

Export Snapshot

Snapshot includes:
  • All memory entries (full content)
  • Metadata (category, timestamp, session_id)
  • Excludes: autosave entries, bootstrap prompts

Reindex Vectors

Rebuild vector index after embedding model change:
Reindexing can take minutes/hours for large memory sets and costs API credits (embedding API calls).

Performance

SQLite backend is fast enough for most use cases (<100K memories). Use Qdrant/pgvector for multi-agent deployments or massive datasets.

Next Steps

Configuration

Full memory configuration reference

Tools

Learn about memory tools