Mnemosyne Documentation

repository·main·Indexed 23 days ago

https://github.com/mnemosyne-oss/mnemosyne

A zero-cloud, SQLite-backed universal memory layer for AI agents. It provides a memory system (BEAM) supporting working memory, episodic long-term storage, and temporal knowledge graphs with sub-millisecond retrieval. Mnemosyne features a Python API, a CLI, and integrations for MCP clients (Cursor, Claude Code, Windsurf), OpenWebUI, and the Hermes Agent. It includes Mnemosyne Sync for bidirectional, encrypted synchronization across devices.

Tokens
106.3K
Snippets
195
Records
498
Agent score
80%

What's inside Mnemosyne

  1. Explore Mnemosyne API and CLI references

    main

    Mnemosyne provides two primary interfaces for interaction:

    • Python API: Use the remember, recall, sleep, triples, and stats functions to manage and query memory programmatically.
    • CLI: A command-line interface for managing the memory system. Use the CLI reference for a complete list of commands, including those not shown by the --help flag.

    Detailed documentation for both can be found in the API Reference and CLI Reference respectively.

  2. Understand BEAM Benchmark output files

    main

    The BEAM benchmark (produced by _benchmarks/evaluate_beam_end_to_end.py) generates three primary files in the results/ directory for analyzing end-to-end performance:

    1. beam_e2e_results.json: Contains per-question results, full metadata, and diagnostic information. This file is overwritten every run.
    2. beam_e2e_summary.json: A small, aggregate scoreboard showing average ability scores per scale (e.g., 100K, 500K). This file is also overwritten every run.
    3. paired_outcomes.jsonl: An append-only file containing one JSON object per question per run. This is the primary file for performing A/B testing or paired comparisons across different configurations by filtering for specific config_id values.
  3. Implement a ContentResolver for media access

    main

    To prevent Mnemosyne from being tied to a local filesystem, media access is abstracted through the ContentResolver protocol. This allows different providers (like an Obsidian vault or a cloud store) to resolve URIs.

    Key Components

    • ContentResolver: A protocol and registry used to map URI schemes to specific resolvers.
    • BlobResolver: A specific implementation designed to close the 'unreachable blob' gap by providing a reader for the content-addressed byte store used by content_sanitizer.py.
    • URI Scheme: Uses the blob://sha256/<hash> format to reference content-addressed bytes.

    When a resolver is not found for a scheme, the system's understanding_status remains 'unavailable', meaning text-based memories are still accessible, but media previews are not.

  4. Understand the relationship between scope, tags, and session_id

    main

    Mnemosyne distinguishes between identity, visibility, and dimensions:

    • session_id: Represents the current conversation or workspace identity (the isolation boundary).
    • scope: Represents visibility or ranking metadata (e.g., session vs global). It is a reserved subset of tags.
    • tags: User-defined dimensions used for cross-cutting query filters (e.g., area:auth, project:x).

    This allows you to maintain session isolation while still performing complex, multi-dimensional queries across different axes of memory.

  5. How Mnemosyne memory works: Capture, Recall, and Consolidate

    main

    Mnemosyne operates through a three-stage lifecycle to provide structured, local-first memory for agents:

    1. Capture

    After a Hermes turn completes, the provider automatically stores the interaction (user message, assistant response, tool calls, and execution context) in a local SQLite database. Memories are tagged with:

    • Importance (0.0-1.0)
    • Scope (session or global)
    • Veracity (stated, inferred, tool, or imported)
    • Metadata (optional, including expiration dates and named entities)

    2. Recall

    Recall is intentional rather than automatic. When an agent invokes mnemosyne_recall, the system performs a hybrid search combining:

    • Vector similarity (semantic matches)
    • FTS5 full-text search (keyword matches)
    • Importance scoring (boosting significant memories)

    Weights for these three components are tunable per-query to bias toward recency, relevance, or both.

    3. Consolidate

    To prevent the working memory from becoming overwhelming, the mnemosyne_sleep tool compresses old working memories into episodic summaries. This keeps the active context window small and ensures recall remains sharp during long-running sessions.

  6. Understand the Layered Agent Memory Model

    main

    Mnemosyne's memory architecture is evolving into a layered system designed to extend the existing BEAM (working and episodic memory) engine. This model organizes information from raw events to high-level procedures, ensuring every synthesized memory maintains a link to its original evidence.

    Memory Layers

    LayerNamePurposeSQLite Representation
    L0Raw TracesFull-fidelity events (user/assistant messages, tool calls, file edits, environment events).Append-only trace tables with session, bank, source, timestamp, hash, and payload metadata.
    L1AtomsSmall, source-linked facts, decisions, preferences, constraints, and entities.Atomic memory rows with evidence links to L0 trace spans.
    L2Scenes/EpisodesCoherent task narratives, milestones, failures, and outcomes.Episode records derived from trace ranges and atom clusters.
    L3Persona/ProfileUser, project, repo, and agent profiles.Versioned profile facts with confidence, validity window, and source links.
    L4Skills/SOPsReusable procedures, workflows, recipes, and agent habits.Procedure records with preconditions, steps, examples, and source episodes.

    Key Concepts

    • Provenance: Every synthesized memory (L1-L4) must retain links to the raw supporting evidence (L0).
    • Progressive Disclosure Recall: A recall strategy that returns the smallest useful information pack first (starting with L3/L4) and expands to L0 only when more evidence is required. This helps manage token budgets.
  7. Understand the Mnemosyne MCP Tool availability

    main
    Mnemosyne provides a total of 36 tools. When using the Model Context Protocol (MCP) via stdio or SSE, only 28 tools are available. The remaining 8 tools are implemented exclusively in the Hermes provider and cannot be called through the MCP server. Attempting to call a plugin-only tool over MCP will result in an Unknown tool error.
  8. Generate a codebase surface map for documentation verification

    main

    When the codebase version changes, generate a fresh codebase map to ensure documentation accurately reflects the current implementation. This involves cataloging all public interfaces to verify against documentation pages.

    Key areas to catalog:

    • Classes and Methods: e.g., BeamMemory in mnemosyne/core/beam.py, Mnemosyne in mnemosyne/core/memory.py.
    • Tool Definitions: MCP tool definitions in mnemosyne/mcp_tools.py and Hermes plugin tools in plugin.yaml.
    • Configuration: Environment variables (via os.getenv) and config.yaml keys.
    • Hooks and Plugins: Hook registration in hermes_plugin/__init__.py and new import providers in mnemosyne/core/importers/.
    • Dependencies: Entry points and dependencies in pyproject.toml.

    Output the results to a structured JSON file (e.g., mnemosyne_codebase_surface.json) to facilitate comparison with documentation.

  9. Understand Mnemosyne session shutdown and consolidation timeouts

    main

    When a session ends, Mnemosyne's on_session_end() hook triggers consolidation (sleep) in a daemon thread. This thread has a 15-second join timeout.

    If the LLM call (especially a slow host LLM) takes longer than 15 seconds, the join returns and the host process proceeds with shutdown to prevent getting stuck. The consolidation daemon continues to run in the background and is reaped when the process exits.

    If a timeout occurs, you will see the following warning: WARNING Mnemosyne session-end sleep timed out after 15s — consolidation deferred

  10. Understand the three time axes in Mnemosyne

    main

    Mnemosyne distinguishes between three distinct time scales to prevent temporal corruption during recall. Do not conflate these:

    1. media_assets.captured_at: The wall-clock time of the original recording. This is the absolute time.
    2. working_memory.timestamp: The time when Mnemosyne ingested the data.
    3. media_moments.t_start_ms: An offset relative to the start of the specific media asset (e.g., "90s into the video"). This is not comparable across different assets.

    Temporal Bridging: You can bridge these to create an event_date (e.g., "what did I see on the afternoon of the 12th") using the formula captured_at + t_start_ms. This is only valid when captured_at_precision == 'exact' and is controlled by the MNEMOSYNE_MEDIA_TIME_BRIDGE setting (default is off).

  11. Understand the Mnemosyne Memory Architecture

    main

    Mnemosyne uses a three-layer architecture to manage memory intake, storage, and retrieval, specifically designed to handle noise remediation through filtering and hygiene processes.

    Layer 1: Pre-storage Filter (filters.py)

    Before data is written to storage, it passes through a filter gate. This layer uses provider filters, core classifiers (regex + heuristics), and content sanitizers (binary extraction) to produce a WriteDecision. If the decision is reject, the content is dropped and logged; if allow, it proceeds to BEAM storage.

    Layer 2: BEAM Storage (beam.py)

    Data is stored in BEAM, which manages different memory types:

    • working_mem: Hot memory with a 7-day TTL and 10K max capacity.
    • episodic_mem: Summarized memories.
    • memory_embeddings: The vector index.

    BEAM also manages a Sleep cycle that triggers consolidate_to_episodic() to move data from working memory to episodic memory.

    Layer 3: Post-storage Hygiene (hygiene.py)

    This layer performs periodic audits of stored data. It uses audit_noise (scoring 0-1) and clean_noise (to delete, archive, or flag) to maintain database quality. A hygiene_audit_log maintains a full audit trail, and restore_archived() allows for reversibility.

    Layer 4: Retrieval (polyphonic_recall.py + beam.py)

    Retrieval is handled via Linear recall (FTS5 + working memory) and Polyphonic recall (hybrid vector + keyword). Ranking is determined by a combination of importance × veracity × Weibull recency × embedding sim.

  12. How media assets and moments are architected

    main

    Mnemosyne uses a sidecar table approach to handle media. Instead of creating a new specialized storage engine, media 'moments' (the text extracted from media) are stored as standard working_memory rows with a memory_type='artifact'. This allows moments to automatically inherit all existing features like vector search, full-text search (FTS), decay, and consolidation.

    The Data Flow:

    1. User Action: An explicit action is taken via mnemosyne media add, mnemosyne_media_register, or remember_media().
    2. media_assets table: Stores the identity of the media (deterministic asset_id, modality, understanding_status, and archive_locator). Note: This table does not store raw bytes; it only holds references.
    3. media_moments table: Stores the relationship between an asset and a specific point in time or space. It uses a span_kind (e.g., whole, time, page, char, box) and coordinates (t_start_ms, t_end_ms, etc.).
    4. working_memory table: The actual text content of the moment is stored here as a standard memory row.
    5. Recall: The system enriches results with media metadata (Phase 2), allows filtering by modality (Phase 3), and applies media-specific ranking weights (Phase 4).
       EXPLICIT USER ACTION ONLY  (no watcher, no polling, no directory scan)
       mnemosyne media add | mnemosyne_media_register | remember_media()
                              │
                              v
       ┌──────────────────────────────────────────────────────────────────┐
       │ media_assets            [NEW, core/media.py]                     │
       │ asset_id (deterministic) · ref_kind/ref_value · modality         │
       │ captured_at + precision · understanding_status · archive_locator │
       │ *** NO BLOB COLUMN. Bytes are never stored here. ***             │
       └──────────┬───────────────────────────────────────────────────────┘
                  │ call_modality_describe()   [RFC 0002]
                  │   -> DescribeResult{ moments: MomentDraft[] }  ... TEXT
                  v
       ┌──────────────────────────────────────────────────────────────────┐
       │ media_moments           [NEW, core/media.py]                     │
       │ span_kind: whole | time | page | char | box                      │
       │ t_start_ms/t_end_ms · page_* · char_* · bbox · speaker           │
       │ UNIQUE(asset_id, kind, span_key) + INSERT OR IGNORE => idempotent│
       │ memory_id ──────────────┐  (soft ref, no FK per #503)            │
       └─────────────────────────┼────────────────────────────────────────┘
                                 v
       ┌──────────────────────────────────────────────────────────────────┐
       │ working_memory          [EXISTING, unchanged schema]             │
       │ memory_type='artifact' · content = the moment's TEXT             │
       │ inherits: vec_working · fts_working · decay · sleep ·           │
       │           veracity · memory_events(sync) · mnemosyne reindex     │
       └─────────────────────────┬────────────────────────────────────────┘
                                 v
       │ recall                                                            │
       │   phase 2: enrichment  -> result["media"] = {ref, span, locator} │
       │   phase 3: filter      -> EXISTS(...) correlated sub-select       │
       │   phase 4: _media_voice -> RRF k=60 (polyphonic_recall.py:734)   │