Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Mnemo is an MCP-native memory database for AI agents. It provides persistent, structured memory with semantic search, access control, hash-chain verification, and multi-agent collaboration primitives.

Key Features

  • 21 MCP Tools: core memory ops (remember, recall, forget, forget_subject, share, consolidate), git-like state (checkpoint, branch, merge, replay), delegation & verification (delegate, verify, trajectory_audit), attention state, agent-controlled mem_*, and plan memory — see the tools reference
  • Hybrid Retrieval: Vector similarity (USearch/pgvector) + BM25 full-text (Tantivy) + recency + graph signals fused via Reciprocal Rank Fusion
  • Access Control: Owner-based permissions, ACL sharing, transitive delegation with time bounds
  • Integrity Verification: SHA-256 hash chains over memory records with tamper detection
  • Git-like State Management: Checkpoint, branch, merge, and replay agent memory states
  • Cognitive Forgetting: Ebbinghaus decay curves, consolidation, archival strategies
  • Memory Poisoning Detection: Anomaly scoring with automatic quarantine
  • Multiple Backends: DuckDB (embedded) or PostgreSQL (distributed)
  • REST API: Full HTTP API alongside MCP stdio transport
  • SDKs: Python (with LangGraph, CrewAI, OpenAI Agents integrations), TypeScript, Go

Use Cases

  • Agent Memory: Give LLM agents persistent memory across conversations
  • Multi-Agent Collaboration: Share memories between agents with fine-grained permissions
  • Audit Trails: Immutable event logs with hash-chain integrity verification
  • Knowledge Management: Store, retrieve, and organize agent-generated knowledge

Architecture

Mnemo is built in Rust for performance and safety. The workspace contains:

CratePurpose
mnemo-coreStorage, indexing, query engine, models
mnemo-mcpMCP server (rmcp 3.0)
mnemo-cliBinary with CLI args
mnemo-postgresPostgreSQL storage backend
mnemo-restAxum REST API
python/PyO3 Python bindings

Quick Start

Installation

From source

cargo install --path crates/mnemo-cli

With Docker

docker pull ghcr.io/mnemo-ai/mnemo:latest
docker run -v mnemo-data:/data ghcr.io/mnemo-ai/mnemo:latest

Running

Basic (embedded DuckDB, noop embeddings)

mnemo --db-path my-agent.db

With OpenAI embeddings

export OPENAI_API_KEY=sk-...
mnemo --db-path my-agent.db

With PostgreSQL backend

mnemo --postgres-url "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost/mnemo"

With REST API

mnemo --db-path my-agent.db --rest-port 8080

Claude Desktop Integration

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "mnemo": {
      "command": "mnemo",
      "args": ["--db-path", "/path/to/memory.db"],
      "env": {
        "OPENAI_API_KEY": "sk-..."
      }
    }
  }
}

Python SDK

pip install mnemo-db   # `mnemo` itself is held by a 2021 notebook project
from mnemo import MnemoClient

client = MnemoClient(db_path="agent.db")
result = client.remember("The user prefers dark mode")
memories = client.recall("user preferences")

First Operations

Once running, the agent (or you via MCP client) can:

  1. Store a memory: mnemo.remember with content and optional metadata
  2. Retrieve memories: mnemo.recall with a natural language query
  3. Share with other agents: mnemo.share to grant access
  4. Verify integrity: mnemo.verify to check hash chain consistency

Architecture

System Overview

┌──────────┐  ┌───────────┐  ┌──────────┐  ┌──────────┐
│MCP Client│  │REST Client│  │  gRPC    │  │  psql    │
│ (stdio)  │  │  (HTTP)   │  │ (tonic)  │  │ (pgwire) │
└────┬─────┘  └─────┬─────┘  └────┬─────┘  └────┬─────┘
     │              │              │              │
     ▼              ▼              ▼              ▼
┌────────────────────────────────────────────────────────┐
│                    MnemoEngine                          │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│  │ Remember │ │  Recall  │ │ Forget/  │ │Checkpoint│ │
│  │ Pipeline │ │ Pipeline │ │Share/... │ │/Branch/  │ │
│  │          │ │  (RRF)   │ │          │ │Merge     │ │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│       └─────────────┴────────────┴────────────┘       │
│                         │                              │
│  ┌──────────────────────▼──────────────────────────┐  │
│  │          StorageBackend (trait)                   │  │
│  │   ┌──────────┐              ┌─────────────┐     │  │
│  │   │  DuckDB   │              │  PostgreSQL  │     │  │
│  │   │           │              │  + pgvector  │     │  │
│  │   └──────────┘              └─────────────┘     │  │
│  └──────────────────────────────────────────────────┘  │
│                                                         │
│  ┌────────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│  │VectorIndex │ │FullText  │ │Embeddings│ │Encrypt │ │
│  │USearch/PG  │ │ Tantivy  │ │OpenAI/   │ │AES-256 │ │
│  │  (HNSW)   │ │ (BM25)   │ │ONNX/Noop │ │  GCM   │ │
│  └────────────┘ └──────────┘ └──────────┘ └────────┘ │
│                                                         │
│  ┌────────────┐ ┌──────────┐ ┌──────────────────────┐ │
│  │   Cache    │ │ColdStore │ │  Poisoning Detection  │ │
│  │ (in-mem)   │ │  (S3)    │ │  + Prompt Injection   │ │
│  └────────────┘ └──────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────┘

Crate Structure

CratePurpose
mnemo-coreStorage, data model, query engine, indexing, encryption
mnemo-mcpMCP server via rmcp 3.0 (STDIO transport)
mnemo-cliCLI binary with clap argument parsing
mnemo-postgresPostgreSQL storage backend via sqlx + pgvector
mnemo-restREST API via Axum 0.8
mnemo-adminAdmin dashboard endpoints (agent stats)
mnemo-pgwirePostgreSQL wire protocol server
mnemo-grpcgRPC API via tonic 0.12
pythonPython bindings via PyO3

Data Model

MemoryRecord

The core data structure. Key fields:

FieldTypeDescription
idUUID v7Time-ordered unique identifier
agent_idStringOwning agent
contentStringMemory content (encrypted at rest if enabled)
memory_typeEnumEpisodic, Semantic, Procedural, Strategic
scopeEnumPrivate, Shared, Global
importancef320.0-1.0 importance score
tagsVecSearchable tags
embeddingVecVector embedding
content_hashVec<u8>SHA-256 hash
prev_hashOptionPrevious record hash (chain)
quarantinedboolFlagged by poisoning detection
decay_rateOption<f32>Custom decay rate
decay_functionOptionCustom decay function

Retrieval Pipeline

Recall uses Reciprocal Rank Fusion (RRF) to combine:

  1. Vector similarity (cosine via USearch or pgvector HNSW)
  2. BM25 full-text (Tantivy)
  3. Recency scoring (exponential decay with configurable half-life)
  4. Graph expansion (1-2 hop relation traversal)

Weights are configurable via hybrid_weights parameter. Permission-safe ANN pre-filtering ensures only authorized memories appear in results.

Access Control

Three-tier permission model:

  1. Owner: Agent who created the memory has full access
  2. ACL: Explicit grants via share with permission levels (Read, Write, Delete, Share, Delegate)
  3. Delegation: Transitive, scoped, time-bounded permission delegation with depth limits

Hash Chain Integrity

Every memory record is linked via SHA-256 hashes:

Record₁ → content_hash = SHA256(content + agent_id + timestamp)
Record₂ → prev_hash = SHA256(content_hash₂ + content_hash₁)
Record₃ → prev_hash = SHA256(content_hash₃ + content_hash₂)

The verify tool checks the entire chain for tampering using constant-time comparisons.

Security Layers

  • Encryption: AES-256-GCM at-rest content encryption (pluggable via ContentEncryption)
  • Validation: agent_id charset/length validation at engine level
  • Poisoning: anomaly scoring + prompt injection pattern detection → quarantine
  • CORS: configurable origin allowlist, defaults to localhost
  • Error sanitization: internal errors logged only, generic messages returned

MCP Tools Reference

Mnemo registers 21 MCP tools via the rmcp framework. Each is available over the STDIO transport when running the mnemo binary.

Every tool takes a single JSON object argument (the fields below) and returns a JSON-encoded text result. On failure a tool returns an isError result whose text is the error message rather than throwing. Required arguments are bold; all others are optional with sensible defaults.

Role filtering. When the server is built with MnemoServer::with_role_filter, a caller only sees the tools its role is allowed to call in tools/list, and a denied tools/call returns a structured -32601 (method-not-found) error instead of a silent empty result. Without a filter every tool below is visible and callable.

The ten core tools also have dedicated pages (linked in the tables). The remaining eleven are documented inline here.

Core memory operations

ToolPurposeKey argumentsReturns
mnemo.rememberStore a new memory (semantic + keyword searchable).content; memory_type, scope, importance, tags, metadata, ttl_seconds, related_to, thread_id, source_type, source_id, org_id, decay_rate, created_by{ id, content_hash, status }
mnemo.recallSearch/retrieve memories by strategy (semantic, lexical, hybrid, graph, reconstruct, exact, auto).query; limit, memory_type(s), scope, min_importance, tags, strategy, temporal_range, org_id, recency_half_life_hours, hybrid_weights, rrf_k, as_of, explain, current_fact_resolver, orientation_cache, domain_scope{ memories, total } (plus optional orientation, belief_state, explain fields)
mnemo.forgetSoft-delete, hard-delete, decay, consolidate, or archive memories by ID or criteria.memory_ids; strategy, criteria (max_age_hours, min_importance_below, memory_type, tags){ forgotten, errors, status }
mnemo.forget_subjectGDPR / DPDPA subject erasure: redact (default, preserves hash chain) or hard-delete every memory tagged subject:<id>.subject_id; strategy, agent_id{ subject_id, strategy, matched, forgotten, cascaded_events, errors }
mnemo.provenanceRead write-provenance: who wrote each memory, under what capability, in what session, when. Tamper-evident audit history that survives forgetting.one of memory_id, principal, session_id; limitone record (by memory_id) or an array (by principal/session_id) of { id, memory_id, principal, capability_id, session_id, op, authored_at, content_hash, prev_hash }
mnemo.forget_by_provenanceFORGET BY PROVENANCE: revoke every memory a principal (or session/trace) authored in one call. Targeted remediation, not a wipe — the audit trail survives.one of principal, session_id; strategy (soft_delete/hard_delete/redact){ forgotten, errors, status }
mnemo.shareGrant one or more agents access to one or more memories (batch supported).memory_id, target_agent_id; memory_ids, target_agent_ids, permission, expires_in_hours{ acl_ids, memory_ids, shared_with, errors, status }
mnemo.consolidateConsolidate related memories into one revisable topic document (Infini-Memory), preserving provenance + a hash-chained audit event.memory_ids, topic_name; agent_id, summary, supersede, thread_id, metadata{ topic_document_id, topic_name, source_count, version, superseded_id, member_ids, content_hash, consolidation_event_id, revision_event_id, status }

Checkpoint, branch, merge & replay (git-like state)

ToolPurposeKey argumentsReturns
mnemo.checkpointSnapshot the current agent state (state, active memories, event cursor).thread_id, state_snapshot; branch_name, label, metadata{ checkpoint_id, parent_id, branch_name, status }
mnemo.branchFork state into a new branch from an existing checkpoint.thread_id, new_branch_name; source_checkpoint_id, source_branch{ checkpoint_id, branch_name, source_checkpoint_id, status }
mnemo.mergeMerge a branch into another (full, cherry-pick, or squash).thread_id, source_branch; target_branch, strategy, cherry_pick_ids{ checkpoint_id, target_branch, merged_memory_count, status }
mnemo.replayReconstruct agent context at a checkpoint (state, memories, events up to that point).thread_id; checkpoint_id, branch_name, as_of{ id, content, memory_type, created_at, status }

Delegation & verification

ToolPurposeKey argumentsReturns
mnemo.delegateGrant scoped, time-bounded (optionally re-delegable) access to your memories.delegate_id, permission; memory_ids, tags, max_depth, expires_in_hours{ delegation_id, delegator, delegate, permission, status }
mnemo.verifyVerify per-record hash-chain integrity; detect tampered/corrupted records.agent_id, thread_id{ valid, total_records, verified_records, first_broken_at, error_message, status }
mnemo.trajectory_auditGEM-aligned trajectory-correctness audit (arXiv:2605.26252): unregulated growth, missing semantic revision, capacity-driven forgetting, read-only retrieval.agent_id, thread_id, active_bank_ceiling, fact_key, named_forget_strategies{ report, all_ok }

Attention state (arXiv:2605.18226)

Requires the server to be built with MnemoServer::with_attention_state; otherwise both tools return an error result.

ToolPurposeKey argumentsReturns
mnemo.attention_state.putStore a precomputed, opaque attention-state blob under (agent_id, prefix_hash).agent_id, prefix_hash, state_blob_hex; model, ttl_seconds{ id, agent_id, prefix_hash, model, ttl_seconds, created_at }
mnemo.attention_state.getFetch the most-recent attention-state record for (agent_id, prefix_hash).agent_id, prefix_hashrecord { id, agent_id, prefix_hash, model, state_blob_hex, ttl_seconds, created_at } or null on miss

Agent-controlled memory — mem_* family (AutoMEM)

A flat, agent-managed store: nothing is written unless the agent explicitly calls mem_write. Entries are tagged agent-managed and are only visible to mem_read (not the general recall pipeline).

ToolPurposeKey argumentsReturns
mnemo.mem_writePersist an entry the agent decided is worth keeping.content; tags, importance, memory_type, metadata, agent_id, org_id{ id, content_hash, store, status }
mnemo.mem_readRead back only the agent’s own agent-managed entries.query; limit, tags, agent_id, org_id{ memories, total, store }
mnemo.mem_reviseSupersede a stale agent-managed entry with a corrected one (newest wins).id, content; tags, importance, agent_id, org_id{ id, revises, content_hash, store, status }
mnemo.mem_forgetDrop an agent-managed entry (soft by default; hard=true for permanent).id; hard, agent_id{ forgotten, errors, status }

Plan / experience memory (DocTrace)

Caches successful retrieval/reasoning plans for replay. Requires the server’s experience-memory mode to be enabled.

ToolPurposeKey argumentsReturns
mnemo.remember_planCache a successful plan (query, ordered steps, chunk ids, outcome score in [0,1]). Below-threshold plans are not stored.query, steps, chunk_ids, outcome_score; scope, agent_id, org_id{ id, signature, stored, status }
mnemo.recall_planReplay the best cached plan whose query signature matches above a threshold (default 0.7). RBAC-gated.query; similarity_threshold, agent_id, org_id{ plan, candidates_considered, hit }

A note on audit-log export

mnemo.export_audit_log is referenced by the manifest schema but is not one of the 23 registered tools above. The audit-log export capability itself already exists today as a library API: mnemo_compliance::export_audit_log(events, format, signer) (with verify_ndjson_signed), which produces a signed NDJSON / EU-AI-Office CSV bundle from the hash-chained event log.

The earlier capability-lease design (per-read lease tokens gating forget_subject / audit-log export) was removed as dead code — it was never wired, and on the stdio transport a single-operator lease is ceremony rather than isolation. The design is captured in #126 for a future multi-caller (authenticated) transport where it has real value.

mnemo.remember

Store a new memory record with optional metadata, tags, and relationships.

Input Schema

FieldTypeRequiredDescription
contentstringyesThe memory content to store
agent_idstringnoAgent identifier (uses server default)
memory_typestringnoepisodic, semantic, procedural, strategic
scopestringnoprivate, shared, global
importancenumberno0.0-1.0 importance score (default 0.5)
tagsstring[]noSearchable tags
metadataobjectnoArbitrary JSON metadata
source_typestringnoconversation, tool_output, reflection, etc.
source_idstringnoReference to source (e.g., message ID)
related_tostring[]noUUIDs of related memories (creates graph edges)
org_idstringnoOrganization scope
thread_idstringnoConversation thread ID
ttl_secondsnumbernoTime-to-live in seconds
decay_ratenumbernoCustom decay rate for importance
created_bystringnoCreator identifier

Response

FieldTypeDescription
idstringUUID v7 of the created memory
content_hashstringSHA-256 hash of the content

Example

{
  "content": "User prefers dark mode and larger fonts",
  "memory_type": "episodic",
  "importance": 0.8,
  "tags": ["preferences", "ui"]
}

mnemo.recall

Retrieve memories using semantic search, full-text search, exact filters, graph traversal, or hybrid retrieval.

Input Schema

FieldTypeRequiredDescription
querystringyesSearch query
agent_idstringnoFilter by agent (uses server default)
limitnumbernoMax results (default 10)
memory_typestringnoFilter by single type
memory_typesstring[]noFilter by multiple types
scopestringnoFilter by scope
min_importancenumbernoMinimum importance threshold
tagsstring[]noFilter by tags (any match)
org_idstringnoFilter by organization
strategystringnovector, bm25, exact, graph, hybrid (default: hybrid)
temporal_rangeobjectno{ after: string, before: string } ISO timestamps

Strategies

  • vector: Cosine similarity via USearch/pgvector
  • bm25: Full-text search via Tantivy
  • exact: Filter-only (no embeddings needed)
  • graph: Vector seeds + 2-hop graph expansion with RRF
  • hybrid (default): Vector + BM25 + recency + graph fused via RRF

Response

FieldTypeDescription
memoriesarrayMatching memories with scores
totalnumberTotal count of results

Each memory includes: id, agent_id, content, memory_type, scope, importance, tags, score, created_at, updated_at.

Example

{
  "query": "user preferences",
  "strategy": "hybrid",
  "limit": 5,
  "min_importance": 0.3
}

mnemo.forget

Remove or decay memories using various strategies.

Input Schema

FieldTypeRequiredDescription
memory_idsstring[]yesUUIDs of memories to forget
agent_idstringnoAgent identifier
strategystringnoForget strategy (see below)
criteriaobjectnoFilter criteria for bulk forget

Strategies

StrategyDescription
soft_deleteMark as deleted (default, recoverable)
hard_deletePermanently remove from storage
decayReduce importance using Ebbinghaus decay curve
consolidateMerge into a semantic summary
archiveMove to cold storage

Criteria (for bulk forget)

FieldTypeDescription
max_age_hoursnumberOnly forget memories older than this
min_importance_belownumberOnly forget memories below this importance
tagsstring[]Only forget memories with these tags

Response

FieldTypeDescription
forgottenstring[]UUIDs of successfully forgotten memories
errorsarray{ id, error } for any failures

mnemo.share

Grant another agent access to a memory.

Input Schema

FieldTypeRequiredDescription
memory_idstringyesUUID of memory to share
target_agent_idstringyesAgent to share with
target_agent_idsstring[]noShare with multiple agents at once
agent_idstringnoSharing agent (uses server default)
permissionstringnoread, write, delete, share, delegate (default: read)
expires_in_hoursnumbernoACL expiration time

Response

FieldTypeDescription
acl_idstringUUID of the created ACL entry
shared_withstring[]Agents the memory was shared with
statusstringshared

mnemo.checkpoint

Create a named snapshot of the current agent memory state.

Input Schema

FieldTypeRequiredDescription
agent_idstringnoAgent identifier
labelstringnoHuman-readable label for the checkpoint

Response

FieldTypeDescription
checkpoint_idstringUUID of the checkpoint
labelstringThe label (if provided)
created_atstringISO timestamp

mnemo.branch

Create a named branch from a checkpoint for isolated memory experimentation.

Input Schema

FieldTypeRequiredDescription
checkpoint_idstringyesBase checkpoint UUID
branch_namestringyesName for the branch

Response

FieldTypeDescription
branch_namestringThe created branch name
base_checkpointstringThe checkpoint it branched from
statusstringbranched

mnemo.merge

Merge a branch back into the main agent memory state.

Input Schema

FieldTypeRequiredDescription
branch_namestringyesBranch to merge
agent_idstringnoAgent identifier

Response

FieldTypeDescription
mergednumberCount of merged records
conflictsnumberCount of conflicts detected
statusstringmerged

mnemo.replay

Replay events that occurred after a given checkpoint.

Input Schema

FieldTypeRequiredDescription
checkpoint_idstringyesCheckpoint to replay from
agent_idstringnoAgent identifier

Response

FieldTypeDescription
eventsarrayList of AgentEvent objects
countnumberNumber of events replayed

mnemo.verify

Verify the SHA-256 hash chain integrity of memory records.

Input Schema

FieldTypeRequiredDescription
agent_idstringnoAgent to verify (uses server default)
thread_idstringnoVerify only a specific thread

Response

FieldTypeDescription
validbooleanWhether the chain is intact
total_recordsnumberTotal records checked
verified_recordsnumberRecords that passed verification
first_broken_atstringUUID of first broken record (if any)
error_messagestringDescription of the integrity violation
statusstringverified or integrity_violation

mnemo.delegate

Delegate permissions to another agent with optional scoping and time bounds.

Input Schema

FieldTypeRequiredDescription
delegate_idstringyesAgent to delegate to
permissionstringyesread, write, delete, share, delegate
memory_idsstring[]noScope to specific memories
tagsstring[]noScope to memories with these tags
max_depthnumbernoMaximum transitive delegation depth (default 0)
expires_in_hoursnumbernoDelegation expiration time

Scoping

If memory_ids is provided, the delegation applies only to those specific memories. If tags is provided, it applies to memories matching those tags. If neither is provided, the delegation applies to all memories.

Transitive Delegation

When max_depth > 0, the delegate can further delegate to other agents, up to the specified depth.

Response

FieldTypeDescription
delegation_idstringUUID of the delegation
statusstringdelegated

REST API

The REST API provides HTTP access to Mnemo, enabling non-MCP clients to interact with the memory database. Enable it with --rest-port:

mnemo --db-path my.db --rest-port 8080

All endpoints are under /v1/.

Configuration

  • CORS: controlled by MNEMO_CORS_ORIGINS environment variable. Defaults to localhost:3000 and localhost:8080. Set to * for permissive mode.
  • Body limit: 2 MB maximum request body.

Endpoints

Health Check

GET /v1/health

Returns {"status": "ok"}.

Remember

POST /v1/memories
Content-Type: application/json

{
  "content": "User prefers dark mode",
  "importance": 0.8,
  "tags": ["preferences"]
}

Returns {"id": "...", "content_hash": "..."}.

Recall

GET /v1/memories?query=preferences&limit=5&strategy=hybrid&min_importance=0.3

Query parameters:

ParameterTypeDescription
querystringNatural language search query (required)
agent_idstringFilter by agent
limitintegerMax results (default: 10, max: 100)
memory_typestringFilter: episodic, semantic, procedural, strategic
memory_typesstringComma-separated list of types
scopestringFilter: private, shared, global
min_importancefloatMinimum importance threshold
tagsstringComma-separated tag filter
org_idstringFilter by organization
strategystringhybrid, semantic, fulltext, exact, graph
as_ofstringPoint-in-time query (RFC 3339 timestamp)
hybrid_weightsstringComma-separated RRF weights
rrf_kfloatRRF constant (default: 60)

Get Memory by ID

GET /v1/memories/{id}

Forget

DELETE /v1/memories/{id}?strategy=soft_delete

Query parameters: strategy (soft_delete, hard_delete, decay, consolidate, archive), agent_id.

Share

POST /v1/memories/{id}/share
Content-Type: application/json

{
  "target_agent_id": "agent-2",
  "permission": "read",
  "expires_in_hours": 24
}

Checkpoint

POST /v1/checkpoints
Content-Type: application/json

{"label": "before-experiment"}

Branch

POST /v1/branches
Content-Type: application/json

{"checkpoint_id": "...", "branch_name": "experiment-1"}

Merge

POST /v1/merge
Content-Type: application/json

{"branch_name": "experiment-1"}

Replay

POST /v1/replay
Content-Type: application/json

{"checkpoint_id": "..."}

Verify

POST /v1/verify
Content-Type: application/json

{"agent_id": "my-agent"}

Delegate

POST /v1/delegate
Content-Type: application/json

{
  "agent_id": "my-agent",
  "delegate_id": "agent-2",
  "permission": "read",
  "memory_ids": ["uuid-1", "uuid-2"],
  "expires_in_hours": 48
}

The agent_id field identifies the caller. The server verifies the caller has Delegate permission on each memory in memory_ids before creating the delegation.

OTLP Ingest

POST /v1/ingest/otlp
Content-Type: application/json

{
  "resourceSpans": [...]
}

Accepts simplified OTLP JSON spans and converts them to agent events. Extracts GenAI semantic convention fields (gen_ai.request.model, gen_ai.usage.input_tokens, etc.).

Returns {"accepted": <count>}.

Error Handling

Errors return appropriate HTTP status codes with generic messages:

StatusMeaning
400Validation error (bad input)
403Permission denied
404Memory not found
500Internal error

Error body: {"error": "description"}. Internal errors are logged server-side; the response contains only a generic message to prevent information leakage.

Python SDK

The Python SDK provides native access to Mnemo via PyO3 bindings, plus integrations for LangGraph, CrewAI, and OpenAI Agents SDK.

Installation

pip install mnemo-db

The PyPI distribution name is mnemo-db (not mnemo) because the unqualified name is held by an unrelated 2021 notebook project. The import path is unchanged — your code keeps saying from mnemo import MnemoClient.

With framework integrations:

pip install mnemo-db[langgraph]     # LangGraph checkpoint support
pip install mnemo-db[crewai]        # CrewAI memory integration
pip install mnemo-db[openai-agents] # OpenAI Agents SDK integration

Basic Usage

from mnemo import MnemoClient

client = MnemoClient(db_path="agent.db", agent_id="my-agent")

# Store a memory
result = client.remember("The user likes dark mode", importance=0.8)

# Recall memories
memories = client.recall("user preferences", limit=5)
for m in memories:
    print(f"{m['content']} (score: {m['score']:.2f})")

# Forget a memory
client.forget([result["id"]])

OpenAI Agents SDK

import asyncio
from agents import Agent, Runner
from mnemo.openai_agents import MnemoAgentMemory

async def main():
    async with MnemoAgentMemory(db_path="agent.db") as memory:
        agent = Agent(
            name="MemoryAgent",
            instructions="Use memory tools to remember and recall information.",
            mcp_servers=memory.mcp_servers,
        )
        result = await Runner.run(agent, "Remember that I prefer Python over JavaScript")
        print(result.final_output)

asyncio.run(main())

LangGraph Checkpointer

from mnemo import MnemoClient
from mnemo.checkpointer import ASMDCheckpointer

client = MnemoClient(db_path="agent.db")
checkpointer = ASMDCheckpointer(client)

# Use with LangGraph
from langgraph.graph import StateGraph
graph = StateGraph(...).compile(checkpointer=checkpointer)

CrewAI Memory

from mnemo.crewai_memory import ASMDMemory

memory = ASMDMemory(db_path="crew.db")
# Use with CrewAI agents

Claude Agent SDK (0.2.0+)

Connects Mnemo to the claude-agent-sdk Python package used by Claude Opus 4.7’s Auto Memory workflow. Exposes the MCP tool surface and optionally materializes memories into Markdown files that Auto Memory reads and edits directly; a watchdog observer persists those edits back into Mnemo.

import asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from mnemo.claude_agent_sdk import MnemoClaudeMemory

async def main():
    async with MnemoClaudeMemory(
        db_path="agent.mnemo.db",
        agent_id="my-project",
        memory_dir=Path(".claude/memory"),
    ) as memory:
        memory.materialize(query="recent work", limit=25)
        memory.watch()
        options = ClaudeAgentOptions(
            mcp_servers={"mnemo": memory.mcp_server_config},
            allowed_tools=["mcp__mnemo__recall", "mcp__mnemo__remember"],
        )
        async with ClaudeSDKClient(options=options) as client:
            await client.query("Summarize yesterday's work.")

asyncio.run(main())

Install with pip install mnemo[claude].

OpenAI Agents SDK — Session store (0.2.0+)

Implements the SessionABC protocol introduced in the 2026-04-15 release, so conversation history is stored in Mnemo. Each turn becomes a session-tagged episodic memory, so a new process can resume the conversation by opening a store with the same session_id.

import asyncio
from agents import Agent, Runner
from mnemo.openai_sessions import MnemoSessionStore

async def main():
    session = MnemoSessionStore(
        db_path="agent.mnemo.db",
        agent_id="user-42",
        session_id="support-2026-04-20",
    )
    agent = Agent(name="Support")
    result = await Runner.run(agent, "I can't log in", session=session)
    print(result.final_output)

asyncio.run(main())

GDPR / DPDPA-safe erasure (0.2.0+)

Subject-scoped erasure through the engine, MCP, REST, or gRPC. Memories are matched by the tag convention subject:<subject_id>. The default redact strategy preserves the memory’s hash chain (so audit verification still succeeds) and replaces content with [REDACTED].

# REST — redact
curl -X POST -H 'content-type: application/json' \
  -d '{"subject_id":"user-42","strategy":"redact"}' \
  http://localhost:8080/v1/forget_subject

To hard-delete instead, use {"strategy": "hard_delete"}.

Ranking provenance (0.2.0+)

Pass explain=True to recall to receive a score_breakdown for each result showing the per-signal contributions (vector, BM25, graph, recency) and the final RRF rank.

result = client.recall("alpha", explain=True, strategy="hybrid")
for memory in result["memories"]:
    bd = memory.get("score_breakdown")
    if bd:
        print(memory["content"], bd)

TTL sweeper + point-in-time replay (0.2.0+)

The engine can run a background TTL sweeper that hard-deletes expired memories and emits MemoryExpired audit events. Enable it via --ttl-sweep-interval / MNEMO_TTL_SWEEP_INTERVAL.

replay accepts an as_of timestamp that synthesizes a virtual checkpoint of the agent state at that instant:

state = client.replay(
    thread_id="support-2026-04-20",
    as_of="2026-04-18T00:00:00Z",
)

TypeScript SDK

The TypeScript SDK communicates with Mnemo via MCP STDIO, spawning the mnemo binary as a child process.

Installation

npm install @mndfreek/mnemo-sdk

Usage

import { MnemoClient } from '@mndfreek/mnemo-sdk';

const client = new MnemoClient({
  dbPath: 'agent.db',
  agentId: 'my-agent',
});

await client.connect();

// Store a memory
const result = await client.remember({
  content: 'User prefers dark mode',
  importance: 0.8,
  tags: ['preferences'],
});

// Recall memories
const memories = await client.recall({
  query: 'user preferences',
  limit: 5,
});

// Share with another agent
await client.share({
  memory_id: result.id,
  target_agent_id: 'agent-2',
  permission: 'read',
});

// Verify integrity
const verification = await client.verify({
  agent_id: 'my-agent',
});
console.log(`Chain valid: ${verification.valid}`);

await client.close();

API Reference

Constructor Options

OptionTypeDefaultDescription
commandstring"mnemo"Path to mnemo binary
dbPathstring"mnemo.db"Database file path
agentIdstring"default"Default agent ID
orgIdstring-Organization ID
openaiApiKeystring-OpenAI API key for embeddings
dimensionsnumber1536Embedding dimensions

Methods

All methods return promises and correspond to MCP tools:

  • remember(input) / recall(input) / forget(input)
  • share(input) / checkpoint(input) / branch(input)
  • merge(input) / replay(input) / verify(input) / delegate(input)

Go SDK

The Go SDK communicates with Mnemo via MCP STDIO, spawning the mnemo binary as a child process.

Installation

go get github.com/mnemo-ai/mnemo-go

Usage

package main

import (
    "fmt"
    "log"

    mnemo "github.com/mnemo-ai/mnemo-go"
)

func main() {
    client, err := mnemo.NewClient(mnemo.ClientOptions{
        DbPath:  "agent.db",
        AgentID: "my-agent",
    })
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    // Store a memory
    importance := float32(0.8)
    result, err := client.Remember(mnemo.RememberInput{
        Content:    "User prefers dark mode",
        Importance: &importance,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Stored: %s\n", result.ID)

    // Recall memories
    limit := 5
    memories, err := client.Recall(mnemo.RecallInput{
        Query: "user preferences",
        Limit: &limit,
    })
    if err != nil {
        log.Fatal(err)
    }
    for _, m := range memories.Memories {
        fmt.Printf("  %s (score: %.2f)\n", m.Content, m.Score)
    }
}

API Reference

ClientOptions

FieldTypeDefaultDescription
Commandstring"mnemo"Path to mnemo binary
DbPathstring"mnemo.db"Database file path
AgentIDstring"default"Default agent ID
OrgIDstring-Organization ID
OpenAIKeystring-OpenAI API key
Dimensionsint1536Embedding dimensions

Methods

  • Remember(RememberInput) / Recall(RecallInput) / Forget(ForgetInput)
  • Share(ShareInput) / Checkpoint(CheckpointInput) / Branch(BranchInput)
  • Merge(MergeInput) / Replay(ReplayInput) / Verify(VerifyInput) / Delegate(DelegateInput)

Memory tiers

Mnemo follows the Letta / MemGPT pattern of giving each memory record a tier — a coarse class that tells the engine how to treat it for expiry, decay, and consolidation. Four tiers are defined:

  • Working — session-scoped. Auto-expires after engine.ttl_working_seconds (default 3600 s) when the caller doesn’t supply an explicit expires_at. Treat this as the “scratchpad” tier for within-conversation working memory.
  • Procedural — system prompts, tool definitions, decision-logic snippets. Importance is clamped on write to engine.procedural_importance_floor (default 0.8) so these never decay below recall visibility.
  • Semantic — facts, user preferences, long-lived knowledge. Current default behaviour; no special handling beyond the normal decay / consolidation pipeline.
  • Episodic — interaction logs. Carries thread_id / session_id as the scoping identifier; the prime target for the reflection pass’s semantic dedup and stale archival phases.

Shape in the data model (honest note)

MemoryTier is a type alias for the existing MemoryType enum, not a separate schema field. v0.2.0’s initial Task-8 spec called for a new tier: MemoryTier field on MemoryRecord; we shipped the type-alias shape instead because MemoryType already had the same four variants — a redundant second column would have been churn with no runtime benefit. The practical effect is identical: callers can pass tier= (a MemoryTier value) to remember and the engine applies the per-tier behaviour based on memory_type.

#![allow(unused)]
fn main() {
use mnemo_core::model::memory::{MemoryTier, MemoryType};
// These are the same type; MemoryTier is literally `pub type MemoryTier = MemoryType;`
let t: MemoryType = MemoryTier::Working;
}

Any downstream code that was relying on a separate tier field for v0.1.1 forward compatibility will compile against memory_type.

Engine knobs

MnemoEngine exposes two builder methods for tuning tier behaviour:

#![allow(unused)]
fn main() {
let engine = MnemoEngine::new(...)
    .with_ttl_working_seconds(1800)           // 30-minute Working TTL
    .with_procedural_importance_floor(0.9);   // raise Procedural floor
}

The constants DEFAULT_TTL_WORKING_SECONDS and DEFAULT_PROCEDURAL_IMPORTANCE_FLOOR are exported from mnemo_core::query so callers can reference the shipping defaults.

Recall semantics

All four tiers participate in the same recall pipeline (auto/vector_only/hybrid_rrf/graph_boosted/lexical). Use tags=["tier:procedural"] or the existing memory_type filter to constrain to a specific tier; the engine does not currently apply a recall-time boost for Working or cap Procedural to read-only.

Out of scope

Letta’s moving-between-tiers heuristics (Working → Semantic after N accesses; Episodic → Semantic via reflection) are not implemented — the v0.3.1 reflection pass only touches Episodic consolidation. A tier-promotion pipeline is queued for v0.4.0.

Temporal edges (mnemo-graph)

The mnemo-graph crate (introduced in v0.4.0-rc1) adds a bitemporal graph layer over the existing storage backends. It’s loosely inspired by Graphiti (Zep) and the Graphiti paper: every relation carries two clocks instead of one, so historical queries can ask “what did we believe at time T?” without losing later corrections.

The two clocks

Every edge in the graph stores:

valid_from              valid_to (None = still true)
    ^                       ^
    |   fact validity       |
    +-----------------------+
    |
    +-- recorded_at (when we wrote the row)
  • valid_from / valid_to describe fact validity — when the relation is true in the world.
  • recorded_at describes system time — when we wrote the row. Useful for audit replay: “show me what the graph looked like at recorded_at = 2026-04-15.”

Without the second clock, there’s no way to distinguish “we always knew Priya works at Acme since 2025” from “we found out yesterday Priya works at Acme since 2025.” Both situations are common; both need different answers from a debugging session.

The TemporalEdge model

#![allow(unused)]
fn main() {
pub struct TemporalEdge {
    pub id: Uuid,
    pub src: Uuid,
    pub dst: Uuid,
    pub relation: String,
    pub valid_from: DateTime<Utc>,
    pub valid_to: Option<DateTime<Utc>>,   // None = still true
    pub confidence: f32,                   // [0.0, 1.0]
    pub recorded_at: DateTime<Utc>,
}
}

relation is a free-form string today ("works_at", "located_in", "reports_to"). We considered an enum but discarded it — codifying a relation set without real corpus data risks pinning the wrong vocabulary. The full LLM extractor that lands in v0.4.0 final will document the conventions it emits.

Storage

Two tables — DuckDB + Postgres equivalents:

CREATE TABLE graph_nodes (
    id VARCHAR PRIMARY KEY,
    label VARCHAR,
    metadata JSON,
    created_at VARCHAR NOT NULL
);

CREATE TABLE graph_edges (
    id VARCHAR PRIMARY KEY,
    src VARCHAR NOT NULL,
    dst VARCHAR NOT NULL,
    relation VARCHAR NOT NULL,
    valid_from VARCHAR NOT NULL,
    valid_to VARCHAR,
    confidence FLOAT NOT NULL DEFAULT 1.0,
    recorded_at VARCHAR NOT NULL
);
CREATE INDEX idx_graph_edges_src_validfrom ON graph_edges(src, valid_from);
CREATE INDEX idx_graph_edges_dst ON graph_edges(dst);

graph_expand — the bitemporal walk

#![allow(unused)]
fn main() {
use chrono::{TimeZone, Utc};
use mnemo_graph::{DuckGraphStore, GraphStore, TemporalEdge, graph_expand};

let store = DuckGraphStore::open_in_memory()?;

// Priya works at Acme starting 2026-01-01.
let priya = Uuid::now_v7();
let acme = Uuid::now_v7();
let acme_edge = TemporalEdge::new(
    priya, acme, "works_at",
    Utc.with_ymd_and_hms(2026, 1, 1, 0, 0, 0).unwrap(),
    None, 0.9,
);
store.insert_edge(&acme_edge).await?;

// Priya leaves Acme on 2026-04-01 and joins Globex.
let globex = Uuid::now_v7();
store.close_edge(acme_edge.id, Utc.with_ymd_and_hms(2026, 4, 1, 0, 0, 0).unwrap()).await?;
store.insert_edge(&TemporalEdge::new(
    priya, globex, "works_at",
    Utc.with_ymd_and_hms(2026, 4, 1, 0, 0, 0).unwrap(),
    None, 0.95,
)).await?;

// Walk the graph at two different points in time.
let in_feb = Utc.with_ymd_and_hms(2026, 2, 15, 0, 0, 0).unwrap();
let in_june = Utc.with_ymd_and_hms(2026, 6, 1, 0, 0, 0).unwrap();

let reachable_feb = graph_expand(&store, priya, 2, in_feb).await?;
//     ^^^ contains acme, NOT globex (relation hadn't started yet)

let reachable_june = graph_expand(&store, priya, 2, in_june).await?;
//     ^^^ contains globex, NOT acme (relation closed at 2026-04-01)
}

This is the supersession property — without it, the graph layer would be redundant with a regular non-temporal graph.

Conflict resolution

When the LLM extractor (v0.4.0 final) emits a contradicting fact with higher confidence than an existing edge, the convention is:

  1. The new edge inserts with its own valid_from and recorded_at.
  2. The pre-existing edge with the lower confidence has its valid_to set to the new edge’s valid_from — capping its validity window.

The result: a sceptical operator can reconstruct the historical view that contained the old answer (via recorded_at) AND the corrected view (via valid_from).

What ships in v0.4.0-rc1

Status
TemporalEdge model
GraphStore async trait
DuckDB-backed DuckGraphStore
graph_expand BFS with as_of filter
Postgres-backed storev0.4.0 final
TemporalEdge::extract LLM-drivenout of scope (#156)
hybrid_rrf 4th-signal integrationv0.4.0 final
MCP / REST / gRPC graph_expand toolsv0.4.0 final

There is no LLM extractor, and there is no longer a stub pretending to be one. mnemo-graph is a bitemporal storage + query layer: callers construct TemporalEdges, and this crate stores, closes and walks them.

A TemporalEdge::extract stub lived here until 2026-08-15, always returning Vec::new(). It was removed rather than left in place, because a function that always returns empty is worse than an absent one: a caller cannot tell “found no relations” from “not implemented”, so wiring it in produces silent no-ops indefinitely. It also outlived its own promise by five releases — the docstring said “lands in v0.4.0 final” while the workspace reached 0.5.23 — and its graph-extract feature flag gated nothing, since the module was compiled unconditionally. See #156.

If LLM-driven extraction is wanted later it should arrive as a designed feature with its own issue, not as a placeholder.

Sources

Claude Agent SDK integration

Mnemo integrates with Anthropic’s claude-agent-sdk two ways at once:

  1. MCP tool surface — every Mnemo MCP tool (remember / recall / forget / share / checkpoint / branch / merge / replay / delegate / verify / forget_subject / reflect) is exposed to the agent through the standard ClaudeAgentOptions.mcp_servers parameter.

  2. Memory-file bridge — recalled memories are materialised as Markdown files on disk with YAML frontmatter. Claude Opus 4.7’s Auto Memory reads and edits those files directly; a watchdog observer picks up the edits and persists them back into Mnemo so the two views stay in sync.

Install with pip install mnemo[claude].

Minimal example

import asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from mnemo.claude_agent_sdk import MnemoClaudeMemory

async def main():
    async with MnemoClaudeMemory(
        db_path="agent.mnemo.db",
        agent_id="my-project",
        memory_dir=Path(".claude/memory"),
    ) as memory:
        # Seed the memory directory from Mnemo so Auto Memory has context.
        memory.materialize(query="recent work", limit=25)
        # Start watching for Auto Dream / Auto Memory edits.
        memory.watch()

        options = ClaudeAgentOptions(
            mcp_servers={"mnemo": memory.mcp_server_config},
            allowed_tools=[
                "mcp__mnemo__recall",
                "mcp__mnemo__remember",
            ],
        )
        async with ClaudeSDKClient(options=options) as client:
            await client.query("Summarize what I worked on yesterday.")

asyncio.run(main())

What the bridge does to each file

  • Write from Mnemomaterialize(...) writes {memory_dir}/{uuid}.md with frontmatter

    ---
    id: 0195a7e8-...
    importance: 0.7
    tags: ["decision", "roadmap"]
    expires_at: 2026-05-20T00:00:00Z
    ---
    The team agreed to ship v0.3.1 on 2026-04-22.
    
  • Edit by Opus 4.7 Auto Memory / Auto Dream — the watchdog observer detects an edit, parses the (possibly rewritten) frontmatter, calls engine.remember(...) with the new content and importance, and the reflection pass (mnemo.reflect) then picks up metadata.dreamed_at markers so they don’t get double-consolidated.

Auto Dream coordination

v0.3.1 adds ReflectionMode::Coordinated which honours the same cadence Auto Dream does: skip when fewer than 5 new records have accumulated or fewer than 24 h have elapsed since the last successful pass. Run via:

# The engine is exposed indirectly through the MCP tool surface; the
# Python bridge also owns a MnemoClient instance you can drive directly:
client = memory._ensure_client()
# Coordinated is the default; pass force=True to override.
client.reflect(mode="coordinated")

Parse the Auto Dream “organization report” trailer (the markdown block with Consolidated: N / Removed: M / Reindexed: K) automatically — mnemo.reflect emits a dream_report_ingested audit event per memory containing one and marks the record so subsequent passes are no-ops.

Caveats (v0.3.1)

  • Python MnemoClient currently does not attach a full-text index, so lexical and hybrid_rrf recall strategies return no results when driven from Python. Tracked; see docs/benchmarks/2026-04-21-mnemo-v0.3.0.md.
  • If OPENAI_API_KEY is unset, MnemoClient falls back to NoopEmbedding. Semantic recall is then random. Set the key, or wait for the v0.3.x ONNX-embedding repair.

Anthropic memory-tool (memory_20250818)

Mnemo ships a client-side handler that satisfies Anthropic’s memory-tool spec for the memory_20250818 surface. It maps the six tool commands (view, create, str_replace, insert, delete, rename) onto Mnemo’s storage so the model gets a persistent “memory directory” that’s audited, hash-chained, and ACL-aware by default.

Install

pip install 'mnemo-db[anthropic-memory-tool]'

The extra pulls anthropic>=0.40 for SDK-driven integration. The server itself does not import Anthropic at runtime, so handlers can also be wired directly into raw API requests.

Quick start

from anthropic import Anthropic
from mnemo import MnemoClient, MnemoMemoryToolServer

# 1. Wire a Mnemo backend.
client = MnemoClient(db_path="memory.mnemo.db", agent_id="agent-1")

# 2. Construct the handler.
server = MnemoMemoryToolServer(client=client)

# 3. Register the tool with Anthropic.
anthropic = Anthropic()
extra_headers = {}
if server.beta_header():
    extra_headers["anthropic-beta"] = server.beta_header()

response = anthropic.messages.create(
    model="claude-opus-4-7",
    max_tokens=2048,
    tools=[server.tool_schema()],
    messages=[{"role": "user", "content": "Help me with my project."}],
    extra_headers=extra_headers or None,
)

# 4. When the model emits a `tool_use`, dispatch through the server.
for block in response.content:
    if block.type == "tool_use" and block.name == "memory":
        result = server.handle({
            "type": "tool_use",
            "id": block.id,
            "name": block.name,
            "input": block.input,
        })
        # Feed `result` back into the next `messages.create` call as a
        # `{"role": "user", "content": [{... tool_result ...}]}` block.

Storage shape

Every “file” is one Mnemo MemoryRecord with two tags:

  • memorytool — flags it as belonging to this surface.
  • path:/memories/... — the canonical absolute path.

Directories are implicit. They exist when at least one file lives under that prefix. view of a directory enumerates first-level children; delete of a directory recursively forgets every record under that prefix; rename re-writes every descendant under the new prefix.

This means:

  • Every file write lands in Mnemo’s hash chain.
  • forget propagates correctly — there is no separate file system to keep in sync.
  • ACL enforcement is whatever the underlying MnemoClient is configured for. The handler doesn’t bypass scope checks.

Beta header

The basic surface needs no anthropic-beta header. When using the Managed Agents container, construct with managed_agents_beta=True:

server = MnemoMemoryToolServer(client=client, managed_agents_beta=True)
extra_headers = {"anthropic-beta": server.beta_header()}
# server.beta_header() == "managed-agents-2026-04-01"

Path-traversal safeguards

The spec calls path validation “the most important security control” for client-side handlers. MnemoMemoryToolServer enforces:

  • Every path (and old_path / new_path) must start with the configured root (default /memories).
  • Paths are normalised with os.path.normpath; the result must still be under the root.
  • Inputs containing .. segments or URL-encoded %2e%2e / %2f sequences are rejected before normalisation.

Override the root with MnemoMemoryToolServer(client=..., root="/other") if you need a different namespace.

Return-string contract

All return values are spec-pinned. Tests in python/tests/test_anthropic_memory_tool.py assert the exact strings listed in the memory-tool spec:

  • view of a directory: Here're the files and directories up to 2 levels deep in {path} ...
  • view of a file: Here's the content of {path} with line numbers:\n{6-char-right-padded line no}\\t{content}
  • create success: File created successfully at: {path}
  • create duplicate: Error: File {path} already exists
  • str_replace success: The memory file has been edited.\n{snippet with line numbers}
  • str_replace no match: No replacement was performed, old_str `{old}` did not appear verbatim in {path}.
  • str_replace multi: No replacement was performed. Multiple occurrences of old_str `{old}` in lines: {a, b, ...}. Please ensure it is unique
  • insert success: The file {path} has been edited.
  • delete success: Successfully deleted {path}
  • rename success: Successfully renamed {old} to {new}

Errors are returned with is_error: true on the tool_result block so the model can react.

Sources

OpenAI Agents SDK — GA resume contract

The 2026-04-16 GA release of openai-agents generalised the preview Session protocol into three cooperating interfaces:

  • SessionStore — per-turn conversation items.
  • SnapshotStore — durable RunState + SandboxSessionState blobs.
  • ResumeProvider — locator layer for picking a SnapshotRef to resume from.

Mnemo ships adapters for both halves.

MnemoSessionStore (chat history)

python/mnemo/openai_sessions.py. Stores each conversation turn as a session-tagged episodic memory; survives process restarts.

from mnemo.openai_sessions import MnemoSessionStore

session = MnemoSessionStore(
    db_path="agent.mnemo.db",
    agent_id="user-42",
    session_id="support-2026-04-20",
)
# Pass `session=session` to the Agents SDK `Runner`.

MnemoSnapshotStore (run state)

python/mnemo/openai_sessions_ga.py. Persists RunState + SandboxSessionState and lets the GA SDK resume crashed runs.

from mnemo.openai_sessions_ga import MnemoSnapshotStore

store = MnemoSnapshotStore(
    session_id="support-2026-04-20",
    db_path="agent.mnemo.db",
    agent_id="user-42",
    workspace_backend="local",
    workspace_root="/var/mnemo/snapshots",
)

ref = await store.save_snapshot(run_state, sandbox_state)
# ... process crashes ...
ref, run, sandbox = await store.resume(from_ref="latest")

SnapshotRef.as_uri() returns a stable snapshot://<session>/<ts> URI suitable for the forthcoming MCP resource exposure layer.

Payload storage policy

  • Inline — payloads at or below inline_threshold_bytes (default 64 KiB) live in the Mnemo memory body as base64, with a SHA-256 digest.
  • Offload — larger payloads go to a pluggable WorkspaceStorage. Mnemo only keeps the locator + SHA-256; the load_snapshot path verifies the digest on every read.

Workspace backends

  • localshipped. Writes under workspace_root.
  • s3 / r2 / gcs / azurestubs in v0.3.1. The WorkspaceStorage class raises NotImplementedError with a NotImplementedError("…install mnemo[openai-sandbox-<backend>] …") message. The v0.3.1 roadmap ships a real aioboto3-backed S3 backend; R2/GCS/Azure follow once the SnapshotSpec shape stabilises in the GA SDK.

Install with pip install mnemo[openai-agents].

Example (crash / resume)

See python/examples/openai_agents_snapshot_example.py for a 3-step agent that writes two snapshots, crashes before the final reply, and resumes from the latest snapshot on the second process start. The equivalent openai_agents_resume_s3_example.py ships with the v0.3.1 S3 backend.

Workspace backends (parity matrix)

The OpenAI Agents SDK GA snapshot store persists an agent’s workspace tree to object storage. Mnemo ships four backends. All four write the identical object layout and share the identical signing contract, so a snapshot is portable between providers by copying objects — nothing in the manifest is provider-specific.

<bucket-or-container>/<key_prefix>/manifest.json
<bucket-or-container>/<key_prefix>/manifest.sig
<bucket-or-container>/<key_prefix>/files/<rel_path>

The four backends

BackendClassExtraClientImplementation
AWS S3S3Workspacemnemo-db[openai-sandbox-s3]boto3base class
Cloudflare R2CloudflareR2Workspacemnemo-db[openai-sandbox-r2]boto3subclasses S3Workspace
Google Cloud StorageGCSWorkspacemnemo-db[openai-sandbox-gcs]google-cloud-storagestandalone
Azure BlobAzureBlobWorkspacemnemo-db[openai-sandbox-azure]azure-storage-blobstandalone

Why R2 subclasses and the other two do not

R2 speaks the S3 wire protocol, so it inherits the entire storage contract and encodes only an endpoint and a region. That makes it a one-paragraph maintenance burden.

GCS and Azure Blob are not S3-wire-compatible:

  • GCS exposes an interoperability XML API that is a partial S3 emulation. It does not cover the paginated list_objects_v2 or batch delete_objects calls S3Workspace relies on, so subclassing would inherit methods that fail at runtime against a real bucket.
  • Azure Blob shares no wire surface at all — different auth (shared key / SAS / Entra ID), different REST API, different pagination.

Both therefore use their provider’s native client, as a single standalone class each. There is deliberately no abstract base layer: the genuinely shared logic (manifest construction, Ed25519 signing, per-blob digest verification) already lives in mnemo.openai_sandbox.manifest, and what remains per backend is a ~5-method object-store adapter. An ABC over five methods would add a layer without removing duplication.

One spec shape, four backends

RemoteSnapshotSpec has a single bucket field. Azure calls its top-level namespace a container; that name goes in bucket anyway.

RemoteSnapshotSpec(backend="azure", bucket="<container-name>", ...)

This is intentional. A provider-specific field would push a conditional into every consumer of a spec; one field keeps MnemoSnapshotStore’s dispatch to a single spec.backend lookup.

Construction

# AWS S3 — standard credential chain
from mnemo.openai_sandbox import S3Workspace
ws = S3Workspace(bucket="agent-snapshots")

# Cloudflare R2 — account ID + access keys
from mnemo.openai_sandbox import CloudflareR2Workspace
ws = CloudflareR2Workspace(
    bucket="agent-snapshots", account_id="abc123",
    access_key_id="...", secret_access_key="...",
)

# GCS — Application Default Credentials
from mnemo.openai_sandbox import GCSWorkspace
ws = GCSWorkspace(bucket="agent-snapshots")

# Azure Blob — connection string (also works against Azurite)
from mnemo.openai_sandbox import AzureBlobWorkspace
ws = AzureBlobWorkspace.from_connection_string(
    "DefaultEndpointsProtocol=...", container="agent-snapshots",
)

Every backend then exposes the same three methods: save_workspace, load_workspace, delete_workspace.

Provider behaviour worth knowing

BehaviourS3 / R2GCSAzure Blob
Overwrite existing objectsilentsilentrejects unless overwrite=True
Prefix listingexplicit paginatorauto-paginatedauto-paginated
Batch deletedelete_objects (1000/call)per blobper blob

The Azure row is the one that bites. upload_blob defaults to raising ResourceExistsError on an existing name, so AzureBlobWorkspace passes overwrite=True — without it, re-saving a workspace to the same key_prefix would fail on the second attempt, making save_workspace non-idempotent across retries. A regression test pins this.

Integrity model (identical across backends)

  1. save_workspace walks the tree, records a SHA-256 per file, builds manifest.json, and signs it with Ed25519.
  2. The returned spec carries manifest_sha256.
  3. load_workspace re-checks that digest against what the provider served before verifying the signature, then verifies every per-file digest while materialising the tree.

Step 2/3 is what catches tampering in the bucket even if an attacker also re-signs the manifest with a rotated key. A tampered manifest fails closed, and each backend has a test that mutates the stored manifest and asserts the load raises.

Testing

BackendUnit substrateLive gate
S3, R2moto (in-memory S3)R2_ACCOUNT_ID + R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY + R2_BUCKET
GCSin-process fake clientGCS_BUCKET + Application Default Credentials
Azurein-process fake container clientAZURE_STORAGE_CONNECTION_STRING + AZURE_CONTAINER

GCS has no moto equivalent and its official emulator (fake-gcs-server) is a Docker image; Azurite likewise needs Docker or npm. So those two use small in-process fakes that implement only the handful of client methods the backend actually calls — a new call reaching for an unfaked method fails loudly rather than passing against a permissive mock. The live gates are skipped by default and never run in CI.

The Azure live test works unmodified against Azurite, whose connection string is well-known — the cheapest way to exercise the real SDK path locally.

Cloudflare R2 workspace backend

Mnemo’s MnemoSnapshotStore — the OpenAI Agents SDK GA snapshot store — supports persisting workspace trees to any S3-compatible object store. v0.3.4 ships CloudflareR2Workspace as a thin subclass of S3Workspace so R2-backed snapshots inherit every feature of the AWS path unchanged: signed manifests, Ed25519 verification, per-blob digest checks, batched delete.

Install

pip install 'mnemo-db[openai-sandbox-r2]'

The extra pulls boto3>=1.34 and cryptography>=42. R2’s S3 API is wire-compatible with AWS SDK v4 signing, so no R2-specific client library is needed.

Quick start

from mnemo.openai_sandbox.r2_workspace import CloudflareR2Workspace
from mnemo.openai_sandbox.manifest import WorkspaceSigner

signer = WorkspaceSigner.generate_ephemeral()  # or load yours from KMS

ws = CloudflareR2Workspace(
    bucket="agent-snapshots",
    account_id="abc123def456",   # R2 account ID
    access_key_id="...",         # R2 access key
    secret_access_key="...",     # R2 secret access key
)

spec = ws.save_workspace(
    workspace_root="/tmp/agent-state",
    signer=signer,
    workspace_id="run-2026-04-25-1",
    created_at="2026-04-25T00:00:00Z",
    key_prefix="agents/agent-1",
)

# `spec` carries backend="r2" — MnemoSnapshotStore dispatches via
# this field to keep the load path symmetric with save.
print(spec)
# RemoteSnapshotSpec(backend='r2', bucket='agent-snapshots',
#                    key_prefix='agents/agent-1', manifest_sha256='...')

Differences from S3 in one line

KnobAWS S3Cloudflare R2
endpoint_urlregional defaulthttps://{account_id}.r2.cloudflarestorage.com
regionus-east-1 etc."auto" (literal)
Addressingpath or virtual"virtual"
Signaturesigv4sigv4
Credential providersfull AWS chainaccess keys only

CloudflareR2Workspace sets every R2-specific knob in its constructor; nothing else in the snapshot path needs to know it’s R2.

Storage layout

Same as S3Workspace. One R2 object per file in the workspace plus two top-level objects per snapshot:

<bucket>/<key_prefix>/manifest.json     # signed JSON manifest
<bucket>/<key_prefix>/manifest.sig      # detached Ed25519 signature
<bucket>/<key_prefix>/files/<rel_path>  # one per source file

Symlinks are recorded in the manifest (not as separate objects) so the load path can recreate them after every regular file is fetched

Live-credential test

The Mnemo test suite runs a moto-S3 round-trip against CloudflareR2Workspace on every CI build. To run a real R2 round-trip locally, export:

export R2_ACCOUNT_ID=<account>
export R2_ACCESS_KEY_ID=<key>
export R2_SECRET_ACCESS_KEY=<secret>
export R2_BUCKET=<bucket>

pytest python/tests/test_r2_workspace.py::test_live_r2_round_trip -v

The test creates a small workspace tree, dumps it to R2 under the mnemo-tests/live-r2/ prefix, fetches it back, asserts file contents match, and cleans up. Skipped silently when any of the four env vars are unset.

Cost note

R2’s free tier is 10 GB storage + 1M Class-A operations / month + 10M Class-B operations / month. A typical mnemo workspace snapshot is ~10 files at ~1 MB each, so a few thousand snapshots fit inside the free tier — see Cloudflare R2 pricing.

R2 also has zero egress fees, which makes it a good fit for snapshot restore traffic patterns (lots of reads on a bad day, very few on a good one).

Sources

Letta Conversations-style shared memory

Letta’s Letta-Code release (2026-04-06) introduced a Conversations API where multiple agents share a single memory stream rather than each maintaining its own.

Mnemo v0.4.0-rc1 ships MnemoLettaShared — the same shape (attach / detach / read / write / list_participants) backed by Mnemo memories rather than a remote Letta service. That keeps shared state on Mnemo’s audit log + hash chain + ACL surface even when the agents are running through Letta’s orchestration.

Install

MnemoLettaShared lives in the core mnemo package — no extra needed:

pip install mnemo-db

Quick start

from mnemo import MnemoClient
from mnemo.letta_adapter import MnemoLettaShared

client = MnemoClient(db_path="conversation.mnemo.db", agent_id="orchestrator")
shared = MnemoLettaShared(
    client=client,
    conversation_id="design-review-2026-04-25",
)

shared.attach("agent-architect")
shared.attach("agent-reviewer")

shared.write(
    "Initial proposal: split the API into v1 / v2 prefixes.",
    source_agent_id="agent-architect",
)
shared.write(
    "Concern: deprecation timeline for v1 is unclear.",
    source_agent_id="agent-reviewer",
)

for msg in shared.read():
    print(f"[{msg.source_agent_id}] {msg.content}")

Storage shape

  • Each shared message is one Mnemo MemoryRecord with two tags:
    • conversation:<id> — every record in the conversation carries this.
    • participant:<source_agent_id> — the author.
  • Participants list is a single Mnemo record tagged conversation:<id> + meta:participants, body = a JSON list of agent IDs. Updated on every attach / detach.

This keeps the conversation audit-log-replayable: every write is a hash-chained Mnemo memory, every participant change is a discrete write the operator can replay.

Conflict policy

The adapter does not pre-resolve conflicts at write time. When two participants write overlapping content within 60 seconds, both records land in Mnemo and the existing ResolutionStrategy::EvidenceWeighted scorer ranks them at recall time. Pre-resolving at write time would amount to silently dropping one participant’s contribution — the exact failure mode shared memory is supposed to avoid.

To inspect cross-participant overlaps for operator review:

for earlier, later in shared.overlapping_writes_within(seconds=60.0):
    print(f"{earlier.source_agent_id} → {later.source_agent_id}: "
          f"{earlier.content[:50]}... / {later.content[:50]}...")

Read semantics

# Full stream, time-ordered.
shared.read()

# Filter by author.
shared.read(from_agent="agent-reviewer")

# Forward a query through Mnemo's hybrid retrieval (vector + BM25).
shared.read(query="deprecation timeline", limit=10)

read() excludes the meta:participants metadata record automatically, so callers see only real messages.

Why a Mnemo-backed adapter rather than a Letta-API client

The blog post called for a MnemoLettaShared adapter, not a client. The shape — attach / detach / read / write — is useful by itself: any time multiple agents need a shared, audited, queryable history, this adapter does the job without needing a Letta account or API key. If you also use Letta’s orchestrator, point its agents at this adapter as their memory backend and the conversation state is portable.

Sources

mnemo mcp-server — hardened MCP STDIO mode

v0.4.0-rc3, Task B2. Defends against the OX-MCP “exfiltrate-then-act” disclosure (2026-04-24) by refusing inherited secrets, JSON-injection argv, and untrusted parent processes BEFORE any engine state is constructed.

Why this exists

The default mnemo startup path is convenient: it reads OPENAI_API_KEY, MNEMO_ENCRYPTION_KEY, MNEMO_POSTGRES_URL, and a stack of CLI flags straight from the environment. That’s fine for local development. It is not fine when an attacker can spawn the binary inside someone else’s shell — the OX-MCP disclosure showed how a poisoned Claude Code session can cause the host to exec an MCP server with the attacker’s manifest attached and the user’s secrets visible.

mnemo mcp-server --manifest <path> is a hardened entry point with a narrower trust boundary:

  • All privileged knobs (keystore, audit log destination, allowed tools, allowed agents, allowed parents) live in a TOML manifest the operator controls.
  • Sensitive env vars are an automatic refusal.
  • --config-style argv injection is an automatic refusal.
  • Non-TTY parents that aren’t on the manifest’s allow-list are an automatic refusal.

The manifest

keystore_path     = "/etc/mnemo/keystore.toml"
audit_log_path    = "/var/log/mnemo/audit.jsonl"
allowed_tools     = ["mnemo.recall", "mnemo.verify"]
allowed_agents    = ["claude-prod"]
allowed_parents   = ["claude", "systemd"]

A full annotated example lives at examples/mcp-server/manifest.toml.

Keystore

The manifest’s keystore_path points at a chmod-restricted TOML file:

key_id  = "mnemo-prov-2026-04"
key_hex = "<64 hex chars / 32 bytes / openssl rand -hex 32>"

The hardened mode loads this file at startup and attaches a ProvenanceSigner (B1) to the engine. Every recall(..., with_provenance=true) returns a verifiable HMAC receipt. Rotate by writing a new file with a fresh key_id and updating the manifest.

The safe-spawn gauntlet

Before constructing any engine state, the binary runs three checks:

  1. Inherited secrets. Refuses if the env carries any of: ANTHROPIC_API_KEY, OPENAI_API_KEY, HF_TOKEN, AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, MNEMO_ENCRYPTION_KEY. Run the binary through a secret-clearing wrapper (env -i, systemd Environment=). Override at your own risk: MNEMO_REJECT_INHERITED_SECRETS=0.
  2. Args-based config. Refuses if argv contains --config, --config-json, --inline-config, -c, or --secret (in any =value form). All config must live in the manifest.
  3. Untrusted parent. When stdin is not a TTY, the parent process basename (set via MNEMO_PARENT_BASENAME) must appear in manifest.allowed_parents. If the variable is unset the check is skipped — running interactively (TTY present) also lifts the check.

Each refusal exits non-zero with a stderr message that names the violating key/arg/parent.

Running it

# 1. Clear the env, set the parent assertion, pass the manifest.
env -i \
  PATH="$PATH" HOME="$HOME" \
  MNEMO_PARENT_BASENAME=systemd \
  mnemo mcp-server --manifest /etc/mnemo/manifest.toml

Under systemd:

[Service]
Type=simple
Environment=MNEMO_PARENT_BASENAME=systemd
ExecStart=/usr/local/bin/mnemo mcp-server --manifest /etc/mnemo/manifest.toml
ProtectSystem=strict
PrivateTmp=true
NoNewPrivileges=true

Verifying it

A quick “does the gauntlet actually fire” smoke test:

ANTHROPIC_API_KEY=leak mnemo mcp-server --manifest /etc/mnemo/manifest.toml
# refused to start: inherited sensitive env var "ANTHROPIC_API_KEY" ...

mnemo mcp-server --manifest /etc/mnemo/manifest.toml --config-json '{}'
# refused to start: command-line carries config-style argument ...

The full integration suite that exercises every refusal path lives in crates/mnemo-cli/tests/safe_spawn_integration.rs.

Role-aware tool filter (v0.4.2 — A1)

Mnemo’s MCP server aligns with the 2025-11-25 MCP authorization spec role-based annotations. The manifest can declare an optional [role_filter] block that gates tools/list (filters the advertised catalog) and tools/call (denies disallowed calls with a spec-compliant -32601).

[role_filter]
caller_roles = ["auditor"]
default      = "deny_all"

[role_filter.allow]
"mnemo.recall"   = ["auditor", "agent"]
"mnemo.verify"   = ["auditor"]
"mnemo.remember" = ["agent"]
"mnemo.forget"   = ["agent"]

[role_filter.deny]
"mnemo.delegate" = ["auditor"]

Rules:

  • Deny always wins. A tool that appears in both allow and deny for the same role is denied.
  • default = "allow_all" (the implicit default) lets any tool not named in allow/deny through. Use deny_all for a strict allow-list.
  • caller_roles declares the role assignment the operator has made for the binary itself. In stdio transport this is the entire caller identity; in future HTTP transports it composes with roles inferred from the Authorization header.
  • Every denied call emits an McpRoleDenied { caller_id, tool_name, attempted_at, reason } row to audit_log_path.
  • Omitting the block keeps pre-v0.4.2 behaviour byte-for-byte. Every advertised tool stays reachable and no audit events are emitted.

The filter contract (RoleFilter trait + ManifestRoleFilter impl) is public, so a custom filter can replace the manifest-driven default at test time. See crates/mnemo-mcp/src/role_filter.rs and the three integration tests under crates/mnemo-mcp/tests/ (role_filter_allow_deny.rs, role_filter_audit_event.rs, role_filter_no_block_when_unset.rs).

What this does NOT cover

  • Capability-leased reads (the old B2 follow-up) are not shipped: the never-wired lease store was removed as dead code. The design — per-read lease tokens gating forget_subject — is captured in #126 for a future authenticated, multi-caller transport where a lease has real cross-caller value (on stdio the operator is the only caller).
  • The DPDPA consent-token-per-write path (B4).
  • The Letta-protocol-compat surface (B5).
  • Per-tool-method enforcement of the role filter at tools/call dispatch — the manifest schema, the filter trait/impl, and the audit emission are shipped in v0.4.2; threading the filter through every MnemoServer tool method body is still pending. The mnemo-envelope OTel exporter kind that a later step depends on is not built — see docs/roadmap/planned-crates.md.

For the threat model and the full design notes, see the rationale at the top of crates/mnemo-cli/src/safe_spawn.rs.

Compatibility note (v0.4.3 — U1)

The MCP wire-protocol version mnemo’s server speaks (2024-11-05, with the 2025-11-25 authorization spec layered on top) is independent of the client SDK version your agent uses. SDK refreshes are common and don’t require a mnemo-side rev unless the spec itself moves.

The current version-skew matrix tracks tested combinations of the four official client SDKs:

  • mcp-python (refreshed 2026-05-01)
  • mcp-go (refreshed 2026-05-01)
  • mcp-ruby (refreshed 2026-05-02)
  • mcp-csharp (refreshed 2026-05-02)

If your agent hits an SDK-side incompatibility, consult the matrix first — most issues land on a row that documents which mnemo cut shipped against that SDK pair. The matrix is enforced in CI by crates/mnemo-mcp/tests/sdk_matrix_doc_present.rs, so the doc itself cannot silently disappear ahead of an SDK-bump release.

MCP 2026 Roadmap alignment (v0.4.4 — U1)

Superseded as a statement of current direction. This section maps mnemo against the March 2026 roadmap. The 2026-07-28 spec release came after it. For what mnemo actually implements today, revision by revision, see MCP 2026-07-28 conformance. The mapping below is kept as history.

The MCP 2026 Roadmap (published 2026-03-09 by lead maintainer David Soria Parra) reorganises the protocol’s direction around four priority areas. The honest mnemo stance against each is below — spec-context anchor, not compliance claim.

MCP 2026 priorityWhat it coversmnemo stance
Transport Evolution and ScalabilityStateless Streamable HTTP, .well-known server-discovery metadata, multi-tenant gateway behaviorFollower. mnemo speaks MCP via the rmcp = "3.0" workspace dep. SEPs land in rmcp first; mnemo upgrades when they’re stable, not before.
Agent CommunicationTasks-primitive lifecycle gaps; agent ↔ agent semantics outside the tool/resource layerObserver. mnemo’s mnemo.delegate + ACL/permission model is the existing surface; further coupling to a Tasks primitive waits on the SEP outcome.
Governance MaturationContributor ladder + WG delegation for the spec itselfObserver. Not a downstream surface mnemo participates in; we follow the spec the WGs ship.
Enterprise ReadinessAudit trails, SSO-integrated auth, gateway behavior, configuration portabilityAligned-by-design. Operator-held HMAC keystore (keystore_path in the manifest), AES-256-GCM at-rest content encryption (MNEMO_ENCRYPTION_KEY), mnemo-compliance crate’s DPDPA consent-token-per-write surface, dual DuckDB / PostgreSQL backend portability, and the role-aware tool filter (v0.4.2 §“Role-aware tool filter”) together form the attestable memory layer regulated-workflow buyers can defend today — independent of any one cloud’s audit boundary.

The honest framing: mnemo claims alignment-by-design with one of four priorities, not roadmap compliance. The other three priorities are spec-evolution work where mnemo follows rmcp’s implementation of the SEPs as they’re written. Buyers reading the roadmap should hear “mnemo’s existing audit story already serves the Enterprise Readiness ask,” not “mnemo is MCP-2026-ready.”

AMP / memorywire conformance (v0.4.13)

Alongside the MCP STDIO surface, mnemo ships an AMP / memorywire interop adapter in the mnemo-amp crate. AMP models memory as 5 operations (remember / recall / forget / merge / expire) over 4 memory types (episodic / semantic / procedural / working), carried in a self-describing JSON envelope validated against a JSON-Schema 2020-12 document (mnemo_amp::schema()).

The adapter is a MemoryStore-conformant surface over a real MnemoEngine. Two ops are deliberately thin compositions over existing primitives rather than assumed engine methods:

  • merge folds N records into one consolidated record (remember with SourceType::Consolidation) and retires the originals (forget with the Consolidate strategy). It is not mnemo’s engine.merge, which is a branch-timeline merge.
  • expire sets expires_at and runs the existing run_ttl_sweep lifecycle path (there is no engine.expire).

A fan-out AmpRouter broadcasts writes to several backends and fuses multi-adapter recall with Reciprocal Rank Fusion. An optional HITL diff-and-approve hook gates long-term (semantic / procedural) writes and records each approval as a Decision event in mnemo’s hash-chained audit log, so the approve trail is tamper-evident and replayable.

Conformance mirrors the cross-adapter suite: recall@5 on a small labelled corpus end-to-end against the embedded DuckDB backend, and RRF-holds-under-rank-0-injection vs max-fusion (RRF keeps a genuinely-relevant item on top; max-fusion is fooled by an adversarial rank-0 injection). Run the end-to-end smoke binary with cargo run --release --bin amp_conformance -p mnemo-amp.

Honest scope: the crate provides the wire format, the schema document, and the engine-backed surface. AMP transport framing (HTTP / stdio, .well-known schema discovery) is left to the embedding application.

MCP 2026-07-28 conformance

State of mnemo against the 2026-07-28 MCP specification revision, row by row. Anchored at commit aec648f against rmcp 3.1.3 (what the workspace rmcp = "3.0" requirement resolves to).

This page exists because mnemo’s posture is to follow rmcp’s implementation rather than race the spec, and that posture is only defensible if there is a document saying which parts are and are not done. Without one, “we follow rmcp” is indistinguishable from “we have not looked”.

What the statuses mean

StatusMeaning
CONFORMSmnemo satisfies the requirement today, either directly or because it never adopted the thing being removed.
GAPmnemo could close this without waiting for anyone. It has not.
UPSTREAM-BLOCKEDClosing it requires rmcp to move first. The rmcp version that would unblock it is named in the row. mnemo does not fork rmcp.

The headline

mnemo negotiates 2025-11-25, not 2026-07-28.

rmcp 3.1.3 knows the newer revision - it carries ProtocolVersion::V_2026_07_28, the CacheScope type, the SEP-2243 header constants and the MRTR result types - but its ProtocolVersion::LATEST is still V_2025_11_25, so that is what an initialize handshake settles on. Most of what follows falls out of that one fact.

The revisions mnemo advertises, which crates/mnemo-mcp/tests/mcp_2026_07_28_conformance.rs asserts against the running server:

  • 2024-11-05
  • 2025-03-26
  • 2025-06-18
  • 2025-11-25

2026-07-28 is deliberately not in that list, and goes back in when mnemo implements it, not when rmcp does.

Lifecycle and transport

Spec changeWhat the spec requiresmnemo todayrmcp 3.1.3 todayStatus
Sessions removed (SEP-2567)No protocol sessions, no Mcp-Session-Id. List endpoints must not vary per connection. Cross-call state uses “explicit, server-minted handles passed as ordinary tool arguments”.Never used sessions. Cross-call state is already handle-threaded: checkpoint_id carries checkpointbranch/replay, and lease_token carries recallforget_subject. tools/list varies by the capability presented on that request (ADR 0002), which is a per-request property, not a per-connection one. Pinned by explicit_handle_roundtrip.rs.Still implements Mcp-Session-Id for revisions at or below 2025-11-25.CONFORMS
Stateless lifecycle (SEP-2575)Remove initialize / notifications/initialized. Every request carries io.modelcontextprotocol/protocolVersion and client capabilities in _meta.Uses the initialize handshake; get_info() answers it. The per-request _meta plumbing already exists - mnemo reads its own capability key out of _meta on every call (ADR 0002) - so this is a lifecycle change, not new plumbing. A caller should assume it must perform the initialize handshake and must not send per-request io.modelcontextprotocol/protocolVersion; it will be ignored.Gated behind negotiating 2026-07-28; LATEST is 2025-11-25, so the gate never opens by default.UPSTREAM-BLOCKED - unblocks when rmcp moves ProtocolVersion::LATEST to V_2026_07_28.
server/discover (SEP-2575)Servers MUST advertise supported protocol versions, capabilities and identity.Inherits rmcp’s default discover, derived from supported_protocol_versions() and get_info().Provides the RPC and the default implementation.CONFORMS
Advertised version setWhat server/discover reports must be what the server serves.Narrowed to the four revisions above. Previously took rmcp’s default (ProtocolVersion::KNOWN_VERSIONS), which advertised 2026-07-28 - a revision mnemo does not serve. See “The defect this page found”.Default is every revision the SDK knows, 2026-07-28 included.CONFORMS (fixed here)
subscriptions/listen (SEP-2575)Replaces the HTTP GET endpoint and resources/subscribe / resources/unsubscribe.Implements no subscriptions at all, so there is nothing to migrate.Implements subscriptions/listen.CONFORMS
ping, logging/setLevel, notifications/roots/list_changed removed (SEP-2575)These methods go away.Overrides none of them; rmcp’s set_level default already answers method-not-found.Retains them for older revisions.CONFORMS
SSE resumability removed (SEP-2575)No Last-Event-ID, no SSE event IDs. A broken stream loses the in-flight request.stdio by default. Under the optional http-transport feature the stream is rmcp’s Streamable HTTP, so resumability is rmcp’s behaviour, not mnemo’s. A caller should assume Last-Event-Id resumption still works at the negotiated revision, and should not rely on it, since it disappears when mnemo adopts 2026-07-28.Still implements Last-Event-Id for older revisions.UPSTREAM-BLOCKED

Headers and caching

Spec changeWhat the spec requiresmnemo todayrmcp 3.1.3 todayStatus
Mcp-Method / Mcp-Name (SEP-2243)Required on Streamable HTTP POST requests so gateways can route without reading the body.Not applicable on stdio, which is the default transport. Under http-transport the headers are rmcp’s to emit and validate. A caller should assume these headers are neither required nor validated, so a gateway cannot route mnemo traffic on them today and must read the body.Has HEADER_MCP_METHOD and HEADER_MCP_NAME, explicitly gated on ProtocolVersion::STANDARD_HEADERS, which is V_2026_07_28.UPSTREAM-BLOCKED - the code path exists but cannot activate while the negotiated revision is 2025-11-25.
ttlMs on list results (SEP-2549)tools/list, prompts/list, resources/list, resources/read and resources/templates/list carry a freshness hint in milliseconds.Implemented. tools/list advertises 60000 (the catalog is compiled in and role-filtered, so it is stable for a fixed capability, but an operator manifest change must not be cached for an hour). resources/list advertises 0, immediately stale, because any mnemo.remember invalidates the listing. mnemo serves no prompts/* or resources/templates/*.Fields present on the list-result types.CONFORMS
cacheScope on list results (SEP-2549)"public" or "private", controlling whether shared intermediaries may cache.Implemented as private on both listings, and that is a correctness requirement rather than a tuning choice. See the note below.CacheScope enum present; note its Default is Public.CONFORMS
Deterministic tools/list orderServers SHOULD return tools in a deterministic order so clients can cache.Filters the router’s list by caller role; does not reorder it.ToolRouter::list_all() sorts by name before returning.CONFORMS (via rmcp)
Resource-not-found error code-32002 becomes -32602 (Invalid Params).Calls McpError::resource_not_found, which emits -32002. A caller should assume resource-not-found arrives as -32002, not -32602.That constructor still emits ErrorCode::RESOURCE_NOT_FOUND, which is -32002.GAP, deliberately unclosed - see below.

Why cacheScope is private and must stay that way. Both of mnemo’s listings are scoped to the caller’s per-request identity (ADR 0002): two callers presenting different capabilities see different tool catalogs, and resources/list returns one agent’s memory records. A public scope would permit a shared intermediary to serve one caller’s catalog, or one agent’s memories, to a different caller. CacheScope::default() is Public, so leaving the field unset is not the safe option it appears to be once anything downstream begins reading it. per_caller_listings_are_never_publicly_cacheable in crates/mnemo-mcp/tests/mcp_2026_07_28_conformance.rs asserts this on both surfaces, and was verified by mutation.

These fields belong to 2026-07-28 while mnemo negotiates 2025-11-25, so no client is currently promised them. They are emitted regardless: a client that does not know the field ignores it, while an intermediary that does understand cacheScope is told the truth now rather than after the eventual revision bump.

Why the error-code row stays open on purpose. mnemo emits -32002 because that is what 2025-11-25 - the revision it actually negotiates - specifies. Changing it to -32602 now would make mnemo non-conformant with the version it speaks in order to match a version it does not. The row closes when mnemo adopts 2026-07-28, not before.

Results

Spec changeWhat the spec requiresmnemo todayrmcp 3.1.3 todayStatus
resultType on all results (SEP-2322)Required field, "complete" or "input_required". Clients MUST read an absent field as "complete".Returns CallToolResponse::Complete. Observed on the wire at the negotiated revision: result_type: None, which is correct - rmcp clears the field for peers that negotiated an older version.Models ResultType and clears it per negotiated version.CONFORMS (via rmcp)
Multi Round-Trip Requests (SEP-2322)Server-initiated requests are replaced by InputRequiredResult plus a client retry.Every mnemo tool is synchronous and always resolves to Complete, so there is nothing to implement.Implements the MRTR types and the client-side retry loop.CONFORMS

Authorization (RFC 9728, RFC 8707)

This section exists because its absence was the most likely thing to be mistaken for conformance. The rows above are about the wire protocol; nothing in them says whether mnemo does OAuth. It does not.

mnemo implements no OAuth authorization. There is no /.well-known/oauth-protected-resource document, no WWW-Authenticate challenge, no authorization-server discovery and no bearer-token audience validation. Authentication is an HMAC capability presented per request (ADR 0002), which is a different mechanism, not a partial implementation of this one.

That is a conformant position rather than a gap, and the spec says so in the paragraph that governs the whole authorization document:

Authorization is OPTIONAL for MCP implementations. When supported: Implementations using an HTTP-based transport SHOULD conform to this specification. Implementations using an STDIO transport SHOULD NOT follow this specification, and instead retrieve credentials from the environment.

mnemo’s default transport is stdio and it takes its capability key from the environment (MNEMO_CAPABILITY_KEY), which is the behaviour that paragraph prescribes.

RequirementWhat the spec requiresWhat mnemo does todayStatus
RFC 9728 Protected Resource Metadata“MCP servers MUST implement OAuth 2.0 Protected Resource Metadata.” The MUST is real, and conditional: it binds servers that support authorization, which is itself OPTIONAL, and stdio servers are told SHOULD NOT.Not implemented. No /.well-known/oauth-protected-resource is served on any transport. A caller should assume discovery will 404 and must not infer from that that the server is unprotected; authenticate with an HMAC capability instead.Not implemented, and conformant on stdio
RFC 8707 Resource Indicators, resource parameter“MCP clients MUST implement Resource Indicators … MUST be included in both authorization requests and token requests.”Does not apply. This MUST binds clients, and mnemo ships an MCP server; the repo publishes no MCP client.Not applicable
RFC 8707 audience validation“MCP servers MUST validate that access tokens were issued specifically for them as the intended audience.”Not implemented as written, because mnemo accepts no OAuth access tokens to validate. The equivalent property is enforced on its own mechanism: a capability verifies against the issuer key and its principal, and an unverifiable capability is rejected rather than downgraded. A caller should assume an OAuth bearer token will not be accepted.Not implemented (no OAuth tokens accepted)
RFC 9207 iss in authorization responsesAuthorization servers SHOULD include iss; clients MUST validate a present iss.Does not apply. mnemo is neither an authorization server nor a client.Not applicable

Why this is worth stating rather than leaving blank

Serving RFC 9728 discovery is close to unheard of in practice: the scanning work in this project’s sibling reports 0 of 2,303 public MCP server configurations serving it. That figure is reported rather than reproduced here, and it is context, not an excuse. The useful thing is not that mnemo is normal, it is that a reader can find out in one place instead of inferring from silence.

An operator putting mnemo behind an OAuth-protected gateway should terminate authorization at that gateway and pass a capability inward. mnemo will not participate in the OAuth flow, will not advertise an authorization server, and will not accept the gateway’s access token in place of a capability.

Deprecations

None of these require work: mnemo never adopted any of them.

Deprecated featuremnemoStatus
Roots (SEP-2577)Never implemented. The spec’s suggested migration, passing paths as tool parameters, is what mnemo already does.CONFORMS
Sampling (SEP-2577)Never implemented. mnemo does not call an LLM; it stores and retrieves.CONFORMS
Logging (SEP-2577)Never implemented. mnemo logs through tracing to stderr, which is the spec’s suggested migration.CONFORMS
HTTP+SSE transport (SEP-2596)Never implemented. The optional http-transport feature is Streamable HTTP (ADR 0002).CONFORMS

The explicit-handle pattern, and the audit behind it

SEP-2567 states the replacement for sessions directly:

Servers that need cross-call state use explicit, server-minted handles passed as ordinary tool arguments.

mnemo already worked this way. Under 2025-11-25 that was one valid option among several; under 2026-07-28 it is the sanctioned one. Being on the right side of a change by accident is not the same as being on it on purpose, so the property is now tested rather than assumed (crates/mnemo-mcp/tests/explicit_handle_roundtrip.rs).

Two handles carry every piece of cross-call state mnemo has:

HandleMinted byConsumed byPassed as
checkpoint_idmnemo.checkpointmnemo.branch, mnemo.replayan ordinary tool argument
lease_tokenmnemo.recall (ADR 0001)mnemo.forget_subjectan ordinary tool argument

The LeaseStore is server-side state, but it is not a session: it is the bookkeeping behind a server-minted handle that the caller threads back through a tool argument, which is precisely the shape the SEP prescribes. A lease is bound to the principal that minted it and expires, so it is narrower than a session, not a rebranding of one.

Audit: what depends on identity that is not an argument

Every tool in crates/mnemo-mcp/src/tools/ was checked for behaviour that depends on connection-scoped identity rather than on a value in the request.

  • 19 of 23 tools take Parameters<T> and nothing else. Their signatures admit no context at all, so connection-scoped state is not merely unused, it is unrepresentable.
  • 4 tools take Extension<CallerContext>: mnemo.recall, mnemo.forget_subject, mnemo.delegate, mnemo.trajectory_audit. This is not connection state. The CallerContext is resolved per request by identity.rs from that request’s own _meta (ADR 0002), and call_tool inserts it immediately before dispatch. Two calls on one connection carrying two different capabilities produce two different callers. _meta remains a per-request carrier under 2026-07-28, which puts protocol version and client capabilities there too, so this shape survives the revision unchanged.

The one deliberate deviation

When a request presents no capability at all, resolve_caller falls back to a boot-derived identity: the agent_id fixed when the server process started. That value is process-scoped, so this is a genuine departure from “everything arrives in the request”, and it is kept on purpose.

The reason is that on stdio one process is one peer, and the operator who started the server genuinely is the caller. Requiring a capability there would break every existing stdio deployment on upgrade to buy no security, because there is no second caller to distinguish from.

The deviation is bounded rather than open-ended:

  • It applies only where no capability was presented. A capability that is present but unverifiable is an error, never a downgrade to the boot identity, since silently downgrading would hand a forged token the operator’s authority.
  • On the network-facing http-transport, the fallback does not apply at all: an unauthenticated request gets AnonymousOnAuthenticatedTransport, because there the fallback would let anyone who can reach the port act as the operator.

See crates/mnemo-mcp/src/identity.rs for the full resolution table.

The defect this page found

Writing the table surfaced one live defect rather than only recording known ones.

mnemo did not override supported_protocol_versions(), so it took rmcp’s default of ProtocolVersion::KNOWN_VERSIONS. rmcp derives server/discover from that list. The result, confirmed against a running server:

advertised protocol_version  = 2025-11-25
supported_protocol_versions  = [2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25, 2026-07-28]

mnemo was telling any discovering client that it speaks 2026-07-28 while answering initialize with 2025-11-25 and implementing none of the newer revision’s server-side requirements. A client entitled to believe that advertisement would have sent 2026-07-28 requests to a server that still expects the handshake that revision removes, and would have received list results with neither ttlMs nor cacheScope.

That is a machine-readable claim that was not true - the same claimed-but-not-wired shape this repo has repaired before (role_filter #124, tool-catalog attestation v0.5.20, LeaseStore under ADR 0001).

The fix is to narrow the list to what mnemo serves. This is rmcp’s own supported mechanism rather than a workaround: its negotiate_protocol_version documents that “a server that narrows that list is never made to answer initialize with a version it cannot serve”, and a client asking for an unlisted revision negotiates down to the server fallback instead of failing. No client breaks.

What is still open, and what would close it

Four rows are not CONFORMS. None of the four is closable by mnemo alone today, which is the reason each carries a caller-assumption sentence in the table above rather than a promise.

Open rowStatusWhat closes it
Stateless lifecycleUPSTREAM-BLOCKEDrmcp moving ProtocolVersion::LATEST to V_2026_07_28
SEP-2243 Mcp-Method / Mcp-NameUPSTREAM-BLOCKEDthe same move; rmcp gates the headers on that revision
SSE resumability removalUPSTREAM-BLOCKEDthe same move; the behaviour is rmcp’s transport, not mnemo’s
Resource-not-found -32002GAP, deliberateadopting 2026-07-28, not an independent change

All four collapse into one event: rmcp flips LATEST, mnemo adds V_2026_07_28 to supported_protocol_versions(), and this page is rewritten rather than amended. The error-code row is listed as a GAP rather than UPSTREAM-BLOCKED because mnemo could emit -32602 today; it does not, because -32002 is what the revision it actually speaks specifies, and changing it early would trade real conformance for imaginary conformance.

Separately, the authorization rows are not on this list. They are not open work: mnemo implements no OAuth and, on stdio, the spec says it should not. See the section above for what a caller should assume instead.

The two rows that were mnemo’s to close, ttlMs and cacheScope, are closed as of 0.5.26.

Deployment

Mnemo can be deployed in several configurations:

ModeBackendBest For
EmbeddedDuckDBSingle-agent, local development
DistributedPostgreSQLMulti-agent, production
DockerEitherContainer deployments
KubernetesPostgreSQLScalable production

Environment Variables

VariableDescriptionDefault
MNEMO_DB_PATHDuckDB database pathmnemo.db
MNEMO_POSTGRES_URLPostgreSQL connection URL-
MNEMO_REST_PORTREST API port-
MNEMO_AGENT_IDDefault agent IDdefault
MNEMO_ORG_IDOrganization ID-
OPENAI_API_KEYOpenAI API key for embeddings-
MNEMO_EMBEDDING_MODELEmbedding model nametext-embedding-3-small
MNEMO_DIMENSIONSEmbedding dimensions1536

Docker Deployment

Quick Start

docker run -d \
  --name mnemo \
  -v mnemo-data:/data \
  -e MNEMO_DB_PATH=/data/mnemo.db \
  -e OPENAI_API_KEY=sk-... \
  ghcr.io/mnemo-ai/mnemo:latest

Docker Compose

docker-compose up -d

The included docker-compose.yml starts Mnemo with PostgreSQL:

services:
  mnemo:
    build: .
    environment:
      MNEMO_POSTGRES_URL: postgres://mnemo:${POSTGRES_PASSWORD}@postgres/mnemo
      OPENAI_API_KEY: ${OPENAI_API_KEY}
      MNEMO_REST_PORT: "8080"
    ports:
      - "8080:8080"
    depends_on:
      - postgres

  postgres:
    image: pgvector/pgvector:pg16
    environment:
      POSTGRES_USER: mnemo
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set a strong POSTGRES_PASSWORD}
      POSTGRES_DB: mnemo
    volumes:
      - pg-data:/var/lib/postgresql/data

Building the Image

docker build -t mnemo .

The Dockerfile uses a multi-stage build for minimal image size.

Kubernetes Deployment

Helm Chart

Install Mnemo on Kubernetes using the Helm chart:

helm install mnemo deploy/helm/mnemo/ \
  --set postgres.url="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/mnemo" \
  --set openaiApiKey="${OPENAI_API_KEY}"

Configuration

Key values.yaml options:

ValueDefaultDescription
replicaCount1Number of replicas
image.repositoryghcr.io/mnemo-ai/mnemoContainer image
image.taglatestImage tag
postgres.url-PostgreSQL connection URL
openaiApiKey-OpenAI API key
rest.enabledtrueEnable REST API
rest.port8080REST API port
resources.requests.cpu100mCPU request
resources.requests.memory128MiMemory request
ingress.enabledfalseEnable ingress

Scaling

For production with PostgreSQL:

helm upgrade mnemo deploy/helm/mnemo/ --set replicaCount=3

Multiple replicas share the same PostgreSQL database, each handling MCP or REST connections independently.

PostgreSQL Mode

PostgreSQL mode enables distributed, multi-instance Mnemo deployments with pgvector for vector search.

Setup

1. PostgreSQL with pgvector

docker run -d \
  --name mnemo-pg \
  -e POSTGRES_USER=mnemo \
  -e POSTGRES_PASSWORD=changeme_use_strong_password \
  -e POSTGRES_DB=mnemo \
  -p 5432:5432 \
  pgvector/pgvector:pg16

2. Start Mnemo with PostgreSQL

mnemo --postgres-url "postgres://mnemo:$POSTGRES_PASSWORD@localhost/mnemo"

Or build with the postgres feature:

cargo build --release --features postgres

Schema

Mnemo automatically creates all required tables on first connection:

  • memories with pgvector vector(N) column and HNSW index
  • acls, delegations, relations, agent_events
  • checkpoints, agent_profiles

Differences from DuckDB Mode

FeatureDuckDBPostgreSQL
Vector indexUSearch (HNSW)pgvector (HNSW)
Full-textTantivyPostgreSQL FTS (planned)
ConcurrencySingle-writerMulti-writer
PersistenceFile-basedServer-based
ScalingSingle instanceMultiple instances

Security

Encryption

Mnemo supports AES-256-GCM at-rest encryption for memory content. Enable it by setting:

export MNEMO_ENCRYPTION_KEY=$(openssl rand -hex 32)
mnemo --encryption-key "$MNEMO_ENCRYPTION_KEY" --db-path my.db

Content is encrypted before storage and decrypted on recall. The encryption key must be 64 hex characters (32 bytes).

Access Control Model

Mnemo implements a three-tier access control model:

1. Owner Access

The agent that created a memory has full access (read, write, delete, share, delegate).

2. ACL-Based Sharing

Explicit access grants via the share tool. Each ACL entry specifies:

  • Target agent ID
  • Permission level (read, write, delete, share, delegate)
  • Optional expiration time

3. Delegation

Agents can delegate their permissions to others with:

  • Scoping (all memories, by ID, or by tag)
  • Maximum transitive depth
  • Time bounds
  • Automatic revocation on expiry

The REST /v1/delegate endpoint verifies the caller has Delegate permission on each target memory before creating the delegation.

Hash Chain Integrity

Every memory record includes a SHA-256 hash chain:

  • content_hash = SHA256(content + agent_id + timestamp)
  • prev_hash links to the previous record’s hash via SHA256(content_hash + prev_content_hash)
  • The verify tool checks the entire chain for tampering
  • Hash comparisons use constant-time operations (subtle::ConstantTimeEq) to prevent timing side-channels

Memory Poisoning Detection

Mnemo monitors agent behavior profiles and flags anomalous memory creation:

  • Rapid creation rate (burst detection)
  • Content length deviation from agent baseline
  • Importance score anomalies
  • Prompt injection patterns — 11 common patterns detected (e.g. “ignore all previous instructions”, “override system prompt”)

Flagged memories are quarantined and excluded from recall results. The anomaly score threshold is 0.5; prompt injection detection alone scores +0.5.

Input Validation

  • agent_id: validated for length (max 256 characters) and allowed characters (alphanumeric, hyphens, underscores, dots)
  • content: must be non-empty
  • importance: must be between 0.0 and 1.0

REST API Security

  • CORS: configurable origin allowlist via MNEMO_CORS_ORIGINS environment variable. Defaults to localhost only (localhost:3000, localhost:8080). Set to * to allow all origins.
  • Body limits: 2 MB maximum request body size to prevent denial-of-service
  • Error handling: internal errors are logged server-side; clients receive generic “internal server error” messages

pgwire Security

  • Authentication: optional cleartext password authentication (configure via PgWireConfig.password)
  • Binding: defaults to 127.0.0.1:5433 (localhost only)
  • For production, deploy behind a TLS-terminating proxy

Environment Variables

VariableDescription
MNEMO_ENCRYPTION_KEYAES-256-GCM key (64 hex chars)
MNEMO_CORS_ORIGINSComma-separated allowed origins, or *
OPENAI_API_KEYOpenAI API key for embeddings

Best Practices

  1. Always set secrets via environment variables, not CLI args
  2. Use time-bounded delegations with minimum required permissions
  3. Regularly run verify to check hash chain integrity
  4. Monitor quarantine events for potential poisoning attempts
  5. Use PostgreSQL mode with TLS for production deployments
  6. Enable encryption for sensitive data with MNEMO_ENCRYPTION_KEY
  7. Configure MNEMO_CORS_ORIGINS explicitly in production

Compliance Overview

Mnemo is an MCP-native memory database for AI agents. This section documents how Mnemo’s architecture and feature set align with industry compliance frameworks, specifically SOC 2 Type II and HIPAA. The goal is to provide operators, auditors, and prospective customers with a clear mapping between regulatory requirements and the technical controls that Mnemo implements.

Compliance Posture Summary

Mnemo was designed with security and auditability as first-class concerns. The following capabilities form the foundation of its compliance story:

CapabilityModuleDescription
Encryption at restencryption.rsAES-256-GCM content encryption with HMAC-based integrity tags
Hash chain verificationhash.rsSHA-256 content hashes linked into a tamper-evident chain
Role-based access controlacl.rsSix-level permission hierarchy (Read through Admin)
Delegation modeldelegation.rsTransitive, scoped, time-bounded permission delegation
Memory poisoning detectionpoisoning.rsAnomaly scoring against agent behavioral baselines
Immutable audit logevent.rsAppend-only AgentEvent log with OpenTelemetry fields
TTL enforcementMemoryRecord.expires_atAutomatic expiration filtering during recall
QuarantineMemoryRecord.quarantinedFlagged memories excluded from recall results
Checkpoint/Branch/Mergecheckpoint.rsGit-like state management with full version history
Cognitive forgettinglifecycle.rsEbbinghaus-inspired decay with configurable functions

Documents in This Section

  • SOC 2 Controls – Maps each SOC 2 Trust Service Criteria category (CC1 through CC9) to specific Mnemo features, implementation modules, and current status.

  • HIPAA Safeguards – Maps HIPAA Administrative, Physical, and Technical Safeguards to Mnemo capabilities, identifies gaps, and provides recommendations for covered-entity deployments.

How to Use This Documentation

For auditors: Each control mapping includes the control identifier, a description of the requirement, the specific Mnemo module or feature that addresses it, the current implementation status, and any known gaps with recommended mitigations.

For operators: Use this documentation to understand which compliance controls Mnemo provides out of the box and which require additional operational procedures, infrastructure configuration, or third-party tooling.

For developers: The module references in each control mapping point directly to source files in crates/mnemo-core/src/. Consult those files for implementation details when extending or auditing controls.

Implementation Status Legend

Throughout the compliance documents, the following status labels are used:

StatusMeaning
ImplementedThe control is fully implemented in code and tested
Partially ImplementedCore functionality exists but additional work is needed for full coverage
PlannedThe control is on the roadmap but not yet implemented
OperationalThe control depends on deployment-time configuration or external processes, not application code

Versioning

This compliance documentation reflects the current compliance posture of Mnemo (23 registered MCP tools; see the tools reference). It should be updated whenever security-relevant features are added or modified.

VersionDateChanges
1.02026-02-07Initial compliance documentation covering SOC 2 and HIPAA

SOC 2 Trust Service Criteria – Control Mapping

This document maps the AICPA SOC 2 Trust Service Criteria (2017 revision) to Mnemo’s security architecture. Each section covers one Common Criteria (CC) category, lists the relevant controls, describes how Mnemo addresses them, and identifies any gaps or recommendations.

For background on Mnemo’s security features, see the Security page and the Compliance Overview.


CC1 – Control Environment

The control environment sets the tone for the organization, influencing the control consciousness of its people. It is the foundation for all other components of internal control.

CC1.1 – Commitment to Integrity and Ethical Values

FieldDetail
Control IDCC1.1
DescriptionThe entity demonstrates a commitment to integrity and ethical values.
Mnemo ImplementationMnemo is an open-source project with public code review. All contributions go through pull request review before merge. The project enforces Rust compiler warnings as errors (#[deny(warnings)]) and maintains a comprehensive test suite (67 tests across unit, integration, and MCP layers).
StatusOperational
Gaps / RecommendationsFormalize a written code of conduct and contributor ethics policy. Document the review and approval process for security-sensitive changes.

CC1.2 – Board Oversight

FieldDetail
Control IDCC1.2
DescriptionThe board of directors demonstrates independence from management and exercises oversight.
Mnemo ImplementationAs a software component rather than a service organization, Mnemo defers board-level governance to the deploying organization. The project provides tools (audit logs, hash chain verification) that enable oversight.
StatusOperational
Gaps / RecommendationsDeploying organizations should establish governance committees with visibility into Mnemo audit logs and verification reports.

CC1.3 – Management Structure and Authority

FieldDetail
Control IDCC1.3
DescriptionManagement establishes structures, reporting lines, and appropriate authorities and responsibilities.
Mnemo ImplementationMnemo’s RBAC model (crates/mnemo-core/src/model/acl.rs) implements a six-level permission hierarchy: Read, Write, Delete, Share, Delegate, Admin. Each permission level satisfies all lower levels. Principal types include Agent, User, Org, Role, and Public. The delegation model (crates/mnemo-core/src/model/delegation.rs) enforces maximum transitive depth and scoped authority.
StatusImplemented
Gaps / RecommendationsNone. The hierarchical permission model maps well to organizational authority structures.

CC1.4 – Competence Commitment

FieldDetail
Control IDCC1.4
DescriptionThe entity demonstrates a commitment to attract, develop, and retain competent individuals.
Mnemo ImplementationMnemo is written in Rust, which enforces memory safety at compile time. The project uses type-safe error handling (crate::error::Error), preventing entire categories of runtime bugs. CI/CD pipelines run the full test suite on every commit.
StatusOperational
Gaps / RecommendationsDocument onboarding procedures for new contributors, including security review training.

CC1.5 – Accountability

FieldDetail
Control IDCC1.5
DescriptionThe entity holds individuals accountable for their internal control responsibilities.
Mnemo ImplementationEvery memory operation is attributed to an agent_id. The AgentEvent log (crates/mnemo-core/src/model/event.rs) records the agent, thread, timestamp, and event type for every action. The created_by field on MemoryRecord tracks who created each memory. Delegation records track both delegator_id and delegate_id.
StatusImplemented
Gaps / RecommendationsNone. Attribution is comprehensive across all data operations.

CC2 – Communication and Information

The entity uses relevant, quality information to support the functioning of internal control and communicates information internally and externally.

CC2.1 – Information Quality

FieldDetail
Control IDCC2.1
DescriptionThe entity obtains or generates and uses relevant, quality information to support the functioning of internal control.
Mnemo ImplementationThe AgentEvent model captures 15 distinct event types covering all data lifecycle operations: MemoryWrite, MemoryRead, MemoryDelete, MemoryShare, Checkpoint, Branch, Merge, UserMessage, AssistantMessage, ToolCall, ToolResult, Error, RetrievalQuery, RetrievalResult, Decision. Each event includes OpenTelemetry fields (trace_id, span_id, model, tokens_input, tokens_output, latency_ms, cost_usd) for observability. Events are hash-chained (content_hash, prev_hash) for integrity.
StatusImplemented
Gaps / RecommendationsConsider adding structured log export (e.g., to SIEM systems) for centralized monitoring.

CC2.2 – Internal Communication

FieldDetail
Control IDCC2.2
DescriptionThe entity internally communicates information necessary to support the functioning of internal control.
Mnemo ImplementationThe event log is queryable via list_events(), get_events_by_thread(), and list_child_events() on the StorageBackend trait. The mnemo.verify MCP tool allows any authorized agent to verify hash chain integrity and report anomalies. Memory poisoning detection results include detailed reasons arrays explaining each anomaly factor.
StatusImplemented
Gaps / RecommendationsAdd webhook or notification support for critical events (quarantine triggers, chain verification failures).

CC2.3 – External Communication

FieldDetail
Control IDCC2.3
DescriptionThe entity communicates with external parties regarding matters affecting the functioning of internal control.
Mnemo ImplementationMnemo provides a REST API and MCP protocol interface for external integration. Audit events can be retrieved programmatically. The Python SDK, TypeScript SDK, and Go SDK enable external systems to consume compliance-relevant data.
StatusPartially Implemented
Gaps / RecommendationsImplement dedicated compliance reporting endpoints that export audit data in standard formats (e.g., CEF, OCSF). Add support for external audit log forwarding.

CC3 – Risk Assessment

The entity identifies and assesses risks to the achievement of its objectives, including risks related to fraud.

CC3.1 – Objective Specification

FieldDetail
Control IDCC3.1
DescriptionThe entity specifies objectives with sufficient clarity to enable the identification and assessment of risks.
Mnemo ImplementationMnemo defines clear security objectives through its data model: memory confidentiality (encryption, scoping), integrity (hash chains, content hashes), availability (TTL management, checkpoint/restore). Each memory has explicit scope (Private, Shared, Public, Global) and importance scoring.
StatusImplemented
Gaps / RecommendationsNone.

CC3.2 – Risk Identification and Analysis

FieldDetail
Control IDCC3.2
DescriptionThe entity identifies risks to the achievement of its objectives and analyzes risks as a basis for determining how the risks should be managed.
Mnemo ImplementationThe memory poisoning detection system (crates/mnemo-core/src/query/poisoning.rs) implements multi-factor anomaly scoring. Three risk indicators are evaluated for every memory write: (1) importance deviation from agent baseline (>0.4 deviation = +0.3 score), (2) content length deviation from agent average (>5x or <0.1x = +0.3 score), (3) high-frequency burst detection (rapid writes = +0.4 score). A composite score >= 0.5 triggers anomaly classification. Agent behavioral baselines are maintained in AgentProfile records (crates/mnemo-core/src/model/agent_profile.rs) with running averages of importance, content length, and total memory count.
StatusImplemented
Gaps / RecommendationsConsider adding configurable thresholds per agent or organization. Add support for custom anomaly detection rules.

CC3.3 – Fraud Risk Assessment

FieldDetail
Control IDCC3.3
DescriptionThe entity considers the potential for fraud in assessing risks.
Mnemo ImplementationMemory poisoning detection directly addresses the risk of agents injecting malicious or misleading memories. The quarantine mechanism (MemoryRecord.quarantined, MemoryRecord.quarantine_reason) isolates suspicious memories from recall results. The hash chain prevents retrospective tampering with the historical record. The delegation model prevents privilege escalation through max_depth limits and time bounds on delegated permissions.
StatusImplemented
Gaps / RecommendationsAdd alerting on repeated quarantine events from a single agent (potential coordinated attack). Consider implementing agent reputation scoring.
FieldDetail
Control IDCC3.4
DescriptionThe entity identifies and assesses changes that could significantly impact the system of internal controls.
Mnemo ImplementationThe checkpoint/branch/merge system (crates/mnemo-core/src/model/checkpoint.rs) provides git-like versioning for agent state. Every checkpoint captures a state_snapshot, optional state_diff, memory_refs, and event_cursor. The version and prev_version_id fields on MemoryRecord track all changes to individual memories.
StatusImplemented
Gaps / RecommendationsNone. Change tracking is comprehensive.

CC5 – Control Activities

The entity selects and develops control activities that contribute to the mitigation of risks to the achievement of objectives to acceptable levels.

CC5.1 – Selection of Control Activities

FieldDetail
Control IDCC5.1
DescriptionThe entity selects and develops control activities that contribute to the mitigation of risks.
Mnemo ImplementationMnemo implements defense in depth through multiple layered controls: encryption at rest, hash chain integrity, RBAC with hierarchical permissions, ACL-based sharing, scoped delegation, anomaly detection, quarantine, and TTL-based expiration.
StatusImplemented
Gaps / RecommendationsNone. Multiple overlapping controls provide robust risk mitigation.

CC5.2 – Technology-Based Control Activities

FieldDetail
Control IDCC5.2
DescriptionThe entity selects and develops general control activities over technology.
Mnemo ImplementationAccess control is enforced at the storage layer through the StorageBackend trait. Key methods include: check_permission(memory_id, principal_id, required_permission) for ACL enforcement, check_delegation(delegate_id, memory_id, required_permission) for delegation enforcement, and list_accessible_memory_ids(agent_id, limit) for permission-safe vector search. The permission hierarchy (Permission::satisfies()) ensures that higher-level permissions automatically grant lower-level access.
StatusImplemented
Gaps / RecommendationsNone.

CC5.3 – Deployment of Control Activities Through Policies

FieldDetail
Control IDCC5.3
DescriptionThe entity deploys control activities through policies that establish what is expected and in procedures that put policies into action.
Mnemo ImplementationAccess policies are encoded in the data model: each Acl record specifies principal_type (Agent, Org, Public, User, Role), principal_id, permission level, granted_by, and optional expires_at. Delegation policies specify scope (AllMemories, ByTag, ByMemoryId), max_depth, current_depth, and expires_at. Memory scope (Private, Shared, Public, Global) sets the default visibility policy.
StatusImplemented
Gaps / RecommendationsAdd organization-level default policies that apply to all agents within an org.

CC6 – Logical and Physical Access Controls

The entity implements logical access security software, infrastructure, and architectures over protected information assets.

CC6.1 – Logical Access Security

FieldDetail
Control IDCC6.1
DescriptionThe entity implements logical access security over protected information assets.
Mnemo ImplementationThree-tier access control: (1) Owner access – the creating agent has full control. (2) ACL-based sharing – explicit grants with specified permission levels and optional expiration. (3) Delegation – transitive permission chains with depth limits and time bounds. All access checks are performed at the storage layer before data is returned. The list_accessible_memory_ids() method ensures that vector similarity search only returns memories the requesting agent is authorized to see.
StatusImplemented
Gaps / RecommendationsNone.

CC6.2 – Authentication and Authorization

FieldDetail
Control IDCC6.2
DescriptionPrior to issuing system credentials and granting system access, the entity registers and authorizes new users.
Mnemo ImplementationAgent identity is established through the agent_id field present on all operations. In MCP mode, the agent identity is bound to the STDIO transport session. The permission system supports five principal types (Agent, User, Org, Role, Public) with hierarchical authorization.
StatusPartially Implemented
Gaps / RecommendationsImplement formal agent registration and credential management. Add support for authentication tokens or API keys. Consider integration with external identity providers (OIDC, SAML).

CC6.3 – Data Encryption

FieldDetail
Control IDCC6.3
DescriptionThe entity protects data in transit and at rest using encryption.
Mnemo ImplementationAt rest: The ContentEncryption module (crates/mnemo-core/src/encryption.rs) provides AES-256-based content encryption. Keys are 256-bit (32 bytes), loaded from the MNEMO_ENCRYPTION_KEY environment variable or provided directly as hex-encoded strings. Each encryption operation produces nonce || ciphertext || tag with a 12-byte nonce and 16-byte HMAC integrity tag. Decryption verifies the tag before returning plaintext, detecting any tampering. In transit: When deployed with PostgreSQL mode, TLS is recommended. The Docker deployment guide recommends reverse proxy with TLS termination.
StatusPartially Implemented
Gaps / RecommendationsUpgrade the encryption implementation from the current simplified XOR-based cipher to the aes-gcm crate for production-grade AES-256-GCM (the code contains a comment noting this: “In production, use aes-gcm crate”). Implement key rotation support. Add envelope encryption for per-record keys. Enforce TLS for all network transports.

CC6.4 – Restriction of Physical Access

FieldDetail
Control IDCC6.4
DescriptionThe entity restricts physical access to facilities and protected information assets.
Mnemo ImplementationAs a software component, Mnemo defers physical access controls to the deployment environment. The Docker deployment (Dockerfile, docker-compose.yml) uses a non-root container image based on debian:bookworm-slim. The data volume (/data) can be mounted with appropriate filesystem permissions.
StatusOperational
Gaps / RecommendationsDocument recommended filesystem permissions for the data volume. Provide Kubernetes deployment guidance with pod security policies and network policies.

CC6.5 – Disposal of Information Assets

FieldDetail
Control IDCC6.5
DescriptionThe entity disposes of protected information assets in a secure manner.
Mnemo ImplementationMnemo implements both soft delete (soft_delete_memory) and hard delete (hard_delete_memory) operations. Soft delete sets deleted_at timestamp, preserving the record for audit purposes. Hard delete permanently removes the record from storage. The cleanup_expired() method removes memories past their TTL. Cognitive forgetting (lifecycle.rs) provides decay-based archival and forgetting with configurable thresholds. Consolidation states track the full lifecycle: Raw, Active, Pending, Consolidated, Archived, Forgotten.
StatusImplemented
Gaps / RecommendationsAdd secure wipe (zeroing) for hard-deleted records to prevent forensic recovery. Document data retention policies and destruction schedules.

CC6.6 – Protection Against External Threats

FieldDetail
Control IDCC6.6
DescriptionThe entity implements controls to prevent or detect and act upon the introduction of unauthorized or malicious software.
Mnemo ImplementationMemory poisoning detection (crates/mnemo-core/src/query/poisoning.rs) monitors all incoming memories against agent behavioral baselines. Anomalous memories are automatically quarantined. The hash chain prevents injection of fabricated historical records. Content hashing detects any post-insertion modification. Source type tracking (SourceType enum with 9 variants) identifies the provenance of each memory.
StatusImplemented
Gaps / RecommendationsAdd content validation rules (e.g., maximum content length, prohibited patterns). Consider integrating with external threat intelligence feeds.

CC7 – System Operations

The entity uses detection and monitoring procedures to identify changes to configurations and system components that may indicate an attack.

CC7.1 – Detection of System Changes

FieldDetail
Control IDCC7.1
DescriptionThe entity detects changes to system components and configurations.
Mnemo ImplementationThe hash chain verification system (crates/mnemo-core/src/hash.rs) enables detection of any tampering with stored memories. verify_chain() iterates through all records, verifying both content hashes and chain linkage. The ChainVerificationResult reports: valid (boolean), total_records, verified_records, first_broken_at (UUID of first tampered record), and error_message. The mnemo.verify MCP tool exposes this capability to agents. The checkpoint system tracks state changes with state_diff fields.
StatusImplemented
Gaps / RecommendationsAdd automated periodic verification (cron-based or event-triggered). Implement alerting on verification failures.

CC7.2 – Monitoring for Anomalies

FieldDetail
Control IDCC7.2
DescriptionThe entity monitors system components and operations for anomalies indicative of malicious acts, natural disasters, or errors.
Mnemo ImplementationAnomaly detection runs on every memory write via check_for_anomaly(). Three indicators are scored: importance deviation (+0.3), content length deviation (+0.3), and burst frequency (+0.4). The AnomalyCheckResult struct provides is_anomalous, score, and detailed reasons. Agent profiles (AgentProfile) track running averages to establish baselines. The event log captures all operations with timestamps and OpenTelemetry correlation IDs for distributed tracing.
StatusImplemented
Gaps / RecommendationsAdd configurable anomaly thresholds. Implement time-series anomaly detection for longer-term behavioral drift. Export metrics to Prometheus or similar monitoring systems.

CC7.3 – Evaluation and Response

FieldDetail
Control IDCC7.3
DescriptionThe entity evaluates anomalies to determine whether they represent security events and responds accordingly.
Mnemo ImplementationWhen a memory scores >= 0.5 on the anomaly scale, it is automatically quarantined via quarantine_memory(). Quarantined memories have quarantined = true and quarantine_reason set with the specific anomaly details. Quarantined memories are excluded from recall results, preventing poisoned data from affecting agent behavior. The agent profile is updated after each write via update_agent_profile() to refine baselines.
StatusImplemented
Gaps / RecommendationsAdd a quarantine review workflow allowing administrators to release or permanently delete quarantined memories. Implement escalation procedures for repeated anomalies from the same agent.

CC7.4 – Incident Response

FieldDetail
Control IDCC7.4
DescriptionThe entity responds to identified security incidents.
Mnemo ImplementationThe delegation revocation mechanism (revoke_delegation()) enables immediate access termination. The event log provides a complete forensic trail. Hash chain verification can identify the exact point of any data tampering. Checkpoint restore enables rollback to a known-good state.
StatusPartially Implemented
Gaps / RecommendationsImplement a formal incident response runbook. Add bulk quarantine and bulk revocation capabilities. Create forensic export tools for incident investigation.

CC8 – Change Management

The entity authorizes, designs, develops, configures, documents, tests, approves, and implements changes to infrastructure and software.

CC8.1 – Change Authorization

FieldDetail
Control IDCC8.1
DescriptionThe entity authorizes, designs, develops, tests, and implements changes to meet its objectives.
Mnemo ImplementationThe checkpoint/branch/merge system provides version control for agent state. Key features: checkpoint – captures a point-in-time snapshot with state_snapshot, state_diff, memory_refs, event_cursor, and optional label. branch – creates a named branch from a checkpoint (branch_name field, parent_id linking). merge – combines branch state back into the main line. replay – replays events from a checkpoint forward. Every MemoryRecord tracks version (incrementing integer) and prev_version_id (UUID linking to the prior version). The mnemo.checkpoint, mnemo.branch, mnemo.merge, and mnemo.replay MCP tools expose these capabilities.
StatusImplemented
Gaps / RecommendationsAdd merge conflict detection and resolution strategies. Implement branch protection rules.

CC8.2 – Testing of Changes

FieldDetail
Control IDCC8.2
DescriptionThe entity tests changes before implementation.
Mnemo ImplementationThe project maintains 67 tests across three layers: 46 unit tests, 16 integration tests, and 5 MCP protocol tests. Criterion benchmarks (benches/engine_bench.rs) track performance regressions. The branching system allows agents to test changes on a branch before merging into the main line.
StatusImplemented
Gaps / RecommendationsAdd security-specific test suites (fuzzing, property-based testing). Implement CI gates that block merges on test failures.

CC8.3 – Change Documentation

FieldDetail
Control IDCC8.3
DescriptionThe entity documents changes to meet its objectives.
Mnemo ImplementationEvery state change is documented through the event log (AgentEvent). The checkpoint system captures state_diff fields showing what changed between checkpoints. Memory versioning (version, prev_version_id) creates a complete change history for every record. The consolidation state machine (Raw -> Active -> Pending -> Consolidated -> Archived -> Forgotten) tracks lifecycle transitions.
StatusImplemented
Gaps / RecommendationsNone. Change documentation is thorough and machine-readable.

CC9 – Risk Mitigation

The entity identifies, selects, and develops risk mitigation activities.

CC9.1 – Risk Mitigation Selection

FieldDetail
Control IDCC9.1
DescriptionThe entity identifies, selects, and develops risk mitigation activities.
Mnemo ImplementationMnemo provides a comprehensive set of risk mitigation controls: TTL enforcement – memories with expires_at are automatically excluded from recall results and cleaned up by cleanup_expired(). Quarantine – anomalous memories are isolated from the data pool. Cognitive forgetting – the Ebbinghaus-inspired decay model (lifecycle.rs) automatically reduces the importance of aging memories through configurable functions (Exponential, Linear, StepFunction, PowerLaw). run_decay_pass() archives or forgets memories below configurable thresholds. Delegation boundsmax_depth prevents infinite permission chains, expires_at ensures time-limited grants, DelegationScope restricts access to specific memories or tags.
StatusImplemented
Gaps / RecommendationsNone. Multiple complementary mitigation strategies are available.

CC9.2 – Vendor and Business Partner Risk

FieldDetail
Control IDCC9.2
DescriptionThe entity assesses and manages risks associated with vendors and business partners.
Mnemo ImplementationMnemo tracks the source of every memory via SourceType (Agent, Human, System, UserInput, ToolOutput, ModelResponse, Retrieval, Consolidation, Import) and source_id. The created_by field identifies the creating entity. The poisoning detection system applies equally to memories from all sources, including external imports.
StatusPartially Implemented
Gaps / RecommendationsAdd vendor/source trust levels with different anomaly thresholds. Implement source allowlisting for import operations.

Summary Matrix

CC CategoryStatusKey Modules
CC1 – Control EnvironmentImplemented / Operationalacl.rs, delegation.rs, event.rs
CC2 – Communication and InformationImplementedevent.rs, hash.rs, StorageBackend
CC3 – Risk AssessmentImplementedpoisoning.rs, agent_profile.rs, checkpoint.rs
CC5 – Control ActivitiesImplementedacl.rs, delegation.rs, StorageBackend
CC6 – Logical and Physical AccessPartially Implementedencryption.rs, acl.rs, delegation.rs
CC7 – System OperationsImplementedhash.rs, poisoning.rs, event.rs
CC8 – Change ManagementImplementedcheckpoint.rs, event.rs, MemoryRecord versioning
CC9 – Risk MitigationImplementedlifecycle.rs, poisoning.rs, delegation.rs

Priority Gaps

The following items represent the highest-priority gaps for achieving full SOC 2 compliance. They are listed in recommended order of implementation:

  1. Upgrade encryption to production-grade AES-256-GCM (CC6.3) – Replace the simplified XOR cipher with the aes-gcm crate. This is the most critical gap.

  2. Implement formal authentication (CC6.2) – Add agent registration, API key management, and external identity provider integration.

  3. Add automated hash chain verification (CC7.1) – Schedule periodic verification runs with alerting on failures.

  4. Implement incident response tooling (CC7.4) – Build forensic export, bulk quarantine, and bulk revocation capabilities.

  5. Add compliance reporting endpoints (CC2.3) – Export audit data in standard formats for external consumption.

HIPAA Safeguards – Control Mapping

This document maps the HIPAA Security Rule safeguards (45 CFR Part 164, Subpart C) to Mnemo’s security architecture. It is intended for organizations that deploy Mnemo in environments where Protected Health Information (PHI) may be stored as agent memories.

HIPAA compliance is a shared responsibility between Mnemo (as the software component) and the deploying organization (as the covered entity or business associate). This document identifies which safeguards Mnemo addresses through its architecture and which require operational controls from the deploying organization.

For background on Mnemo’s security features, see the Security page and the Compliance Overview.


Administrative Safeguards (Section 164.308)

Administrative safeguards are administrative actions, policies, and procedures to manage the selection, development, implementation, and maintenance of security measures to protect ePHI.

164.308(a)(1) – Security Management Process

Requirement: Implement policies and procedures to prevent, detect, contain, and correct security violations.

(i) Risk Analysis (Required)

FieldDetail
HIPAA Reference164.308(a)(1)(ii)(A)
RequirementConduct an accurate and thorough assessment of the potential risks and vulnerabilities to the confidentiality, integrity, and availability of ePHI.
Mnemo ImplementationMnemo provides built-in risk analysis capabilities through the memory poisoning detection system (crates/mnemo-core/src/query/poisoning.rs). The check_for_anomaly() function evaluates three risk vectors for every memory write: importance deviation from agent baseline, content length anomalies, and high-frequency burst detection. Agent behavioral profiles (AgentProfile) are maintained with running averages to establish baselines. The anomaly scoring system produces quantified risk assessments (AnomalyCheckResult with score and reasons).
StatusPartially Implemented
GapsMnemo provides automated risk detection for data integrity threats but does not replace a comprehensive organizational risk analysis. Deploying organizations must conduct their own risk assessment covering infrastructure, personnel, and operational risks.

(ii) Risk Management (Required)

FieldDetail
HIPAA Reference164.308(a)(1)(ii)(B)
RequirementImplement security measures sufficient to reduce risks and vulnerabilities to a reasonable and appropriate level.
Mnemo ImplementationMnemo implements multiple security measures: AES-256-based encryption at rest (encryption.rs), SHA-256 hash chain integrity verification (hash.rs), six-level RBAC (acl.rs), scoped delegation with depth limits (delegation.rs), automatic quarantine of anomalous memories, TTL enforcement for data retention, and cognitive forgetting for automatic data lifecycle management (lifecycle.rs).
StatusImplemented
GapsEncryption implementation should be upgraded to production-grade aes-gcm crate. See SOC 2 CC6.3 for details.

(iii) Sanction Policy (Required)

FieldDetail
HIPAA Reference164.308(a)(1)(ii)(C)
RequirementApply appropriate sanctions against workforce members who fail to comply with security policies.
Mnemo ImplementationThe delegation model supports revocation (revoke_delegation()) to immediately terminate an agent’s delegated access. Quarantine isolates suspect agent activity. The event log provides evidence for sanction decisions.
StatusPartially Implemented
GapsSanction policies are organizational responsibilities. Mnemo provides the enforcement mechanisms but does not define the policies themselves.

(iv) Information System Activity Review (Required)

FieldDetail
HIPAA Reference164.308(a)(1)(ii)(D)
RequirementImplement procedures to regularly review records of information system activity, such as audit logs, access reports, and security incident tracking reports.
Mnemo ImplementationThe AgentEvent log (crates/mnemo-core/src/model/event.rs) provides an immutable, hash-chained audit trail. It captures 15 event types covering all data operations. Events include OpenTelemetry fields for correlation. The StorageBackend trait provides query methods: list_events(agent_id, limit, offset), get_events_by_thread(thread_id, limit), list_child_events(parent_event_id, limit). The mnemo.verify MCP tool enables integrity verification of the event chain.
StatusImplemented
GapsAdd scheduled activity review reports and dashboards. Implement automated alerting for suspicious activity patterns.

164.308(a)(2) – Assigned Security Responsibility

FieldDetail
HIPAA Reference164.308(a)(2)
RequirementIdentify the security official responsible for developing and implementing security policies.
Mnemo ImplementationMnemo’s permission model supports Admin-level principals who have full control over all operations. The PrincipalType::Role type enables mapping organizational security roles to Mnemo permissions.
StatusOperational
GapsThis is an organizational requirement. Mnemo provides the RBAC infrastructure to support it. The deploying organization must designate a security official and map their role to Mnemo’s Admin permission.

164.308(a)(3) – Workforce Security

Requirement: Implement policies and procedures to ensure that all members of the workforce have appropriate access to ePHI.

(i) Authorization and/or Supervision (Addressable)

FieldDetail
HIPAA Reference164.308(a)(3)(ii)(A)
RequirementImplement procedures for the authorization and/or supervision of workforce members who work with ePHI.
Mnemo ImplementationThe three-tier access control model (Owner, ACL, Delegation) ensures that agents only access memories they are authorized for. The list_accessible_memory_ids() method on StorageBackend enforces this during vector search. Every ACL entry records granted_by to track authorization chains. Delegation records track both delegator_id and delegate_id with max_depth and current_depth for oversight.
StatusImplemented
GapsNone at the application level.

(ii) Workforce Clearance Procedure (Addressable)

FieldDetail
HIPAA Reference164.308(a)(3)(ii)(B)
RequirementImplement procedures to determine that the access of a workforce member to ePHI is appropriate.
Mnemo ImplementationThe permission hierarchy (Permission::satisfies()) enforces that each agent has only the minimum required permission level. Delegation scope (DelegationScope::AllMemories, ByTag, ByMemoryId) restricts access to relevant data subsets. Time-bounded ACLs and delegations (expires_at) ensure access is reviewed and renewed.
StatusImplemented
GapsAdd periodic access review reports listing all active permissions and delegations per agent.

(iii) Termination Procedures (Addressable)

FieldDetail
HIPAA Reference164.308(a)(3)(ii)(C)
RequirementImplement procedures for terminating access to ePHI when employment or access is no longer required.
Mnemo ImplementationDelegation revocation (revoke_delegation()) sets revoked_at timestamp to immediately terminate delegated access. ACL entries support expires_at for automatic expiration. Soft delete (soft_delete_memory()) preserves audit history while removing access to the content.
StatusImplemented
GapsAdd a bulk access termination API that revokes all permissions for a given agent in a single operation.

164.308(a)(4) – Information Access Management

Requirement: Implement policies and procedures for authorizing access to ePHI.

(i) Isolating Health Care Clearinghouse Functions (Required)

FieldDetail
HIPAA Reference164.308(a)(4)(ii)(A)
RequirementIf a health care clearinghouse is part of a larger organization, isolate its functions.
Mnemo ImplementationMemory scoping (Private, Shared, Public, Global) combined with org_id field enables organizational isolation. Multi-tenant deployments can use org_id to enforce data separation at the storage layer.
StatusPartially Implemented
GapsImplement strict tenant isolation enforcement at the database level. Add cross-org access prevention in all query paths.

(ii) Access Authorization (Addressable)

FieldDetail
HIPAA Reference164.308(a)(4)(ii)(B)
RequirementImplement policies and procedures for granting access to ePHI.
Mnemo ImplementationThe mnemo.share MCP tool provides explicit access granting. The mnemo.delegate MCP tool enables controlled permission delegation. Both record the granting agent and support time bounds.
StatusImplemented
GapsNone.

(iii) Access Establishment and Modification (Addressable)

FieldDetail
HIPAA Reference164.308(a)(4)(ii)(C)
RequirementImplement policies and procedures that establish, document, review, and modify access.
Mnemo ImplementationAll access changes are logged as AgentEvent records (MemoryShare event type). ACL entries include created_at and expires_at for temporal tracking. Delegation records include creation time, expiration, and revocation timestamps.
StatusImplemented
GapsNone.

164.308(a)(5) – Security Awareness and Training

Requirement: Implement a security awareness and training program for all members of the workforce.

FieldDetail
HIPAA Reference164.308(a)(5)
RequirementSecurity reminders, malicious software protection, log-in monitoring, password management.
Mnemo ImplementationMnemo provides documentation on security best practices (see docs/src/security.md). The memory poisoning detection system protects against malicious data injection. The event log enables monitoring of all access attempts.
StatusPartially Implemented
GapsThis is primarily an organizational requirement. Create deployment-specific security guides for teams handling PHI. Add security warning messages for operations involving high-sensitivity memories.

164.308(a)(6) – Security Incident Procedures

Requirement: Implement policies and procedures to address security incidents.

FieldDetail
HIPAA Reference164.308(a)(6)(ii)
RequirementIdentify and respond to suspected or known security incidents; mitigate harmful effects; document incidents and outcomes.
Mnemo ImplementationQuarantine mechanism automatically responds to detected anomalies. Hash chain verification (mnemo.verify) identifies data tampering incidents. The event log provides a forensic trail for incident investigation. Checkpoint restore enables rollback to pre-incident state. Delegation revocation enables immediate access termination.
StatusPartially Implemented
GapsImplement a formal incident tracking system within Mnemo (incident records, severity levels, resolution status). Add automated incident notification capabilities.

164.308(a)(7) – Contingency Plan

Requirement: Establish policies and procedures for responding to an emergency or other occurrence that damages systems containing ePHI.

(i) Data Backup Plan (Required)

FieldDetail
HIPAA Reference164.308(a)(7)(ii)(A)
RequirementEstablish and implement procedures to create and maintain retrievable exact copies of ePHI.
Mnemo ImplementationThe checkpoint system (crates/mnemo-core/src/model/checkpoint.rs) creates point-in-time snapshots with state_snapshot, memory_refs, and event_cursor. Checkpoints include parent_id for history linking. The mnemo.checkpoint MCP tool enables programmatic backup creation. DuckDB storage supports file-level backups of the database file.
StatusPartially Implemented
GapsImplement automated scheduled backups. Add backup verification (restore testing). Implement offsite backup replication.

(ii) Disaster Recovery Plan (Required)

FieldDetail
HIPAA Reference164.308(a)(7)(ii)(B)
RequirementEstablish procedures to restore any loss of data.
Mnemo ImplementationThe mnemo.replay MCP tool replays events from a checkpoint to restore state. Branch and merge operations enable state recovery from alternative timelines. The checkpoint system captures sufficient state for full reconstruction.
StatusPartially Implemented
GapsDocument formal disaster recovery procedures. Define Recovery Time Objective (RTO) and Recovery Point Objective (RPO). Implement automated recovery testing.

(iii) Emergency Mode Operation Plan (Required)

FieldDetail
HIPAA Reference164.308(a)(7)(ii)(C)
RequirementEstablish procedures to enable continuation of critical business processes during an emergency.
Mnemo ImplementationMnemo can operate with a local DuckDB file, enabling standalone operation without network dependencies. The NoopEmbedding provider allows operation without external API access.
StatusPartially Implemented
GapsDocument emergency operating procedures. Define minimum viable configuration for emergency operation.

164.308(a)(8) – Evaluation

FieldDetail
HIPAA Reference164.308(a)(8)
RequirementPerform periodic technical and nontechnical evaluation of security controls.
Mnemo ImplementationThe mnemo.verify MCP tool enables on-demand integrity verification. Criterion benchmarks track performance characteristics. The test suite (67 tests) validates security controls.
StatusPartially Implemented
GapsImplement scheduled security evaluations. Add compliance assessment tooling. Create security metrics dashboards.

Physical Safeguards (Section 164.310)

Physical safeguards are physical measures, policies, and procedures to protect electronic information systems and related buildings and equipment from natural and environmental hazards and unauthorized intrusion.

164.310(a)(1) – Facility Access Controls

FieldDetail
HIPAA Reference164.310(a)(1)
RequirementImplement policies and procedures to limit physical access to electronic information systems while ensuring that properly authorized access is allowed.
Mnemo ImplementationAs a software component, Mnemo defers facility-level controls to the deployment environment. The Docker deployment (Dockerfile) uses a minimal debian:bookworm-slim base image, reducing the attack surface. The Kubernetes deployment guide provides pod security recommendations.
StatusOperational
GapsThis is entirely an operational requirement. Document recommended deployment environments with facility access controls.

164.310(b) – Workstation Use

FieldDetail
HIPAA Reference164.310(b)
RequirementImplement policies and procedures that specify the proper functions to be performed and the physical attributes of the surroundings of workstations that access ePHI.
Mnemo ImplementationNot directly applicable to Mnemo as a server-side component. The MCP STDIO transport binds sessions to individual agent processes.
StatusOperational
GapsDocument workstation security requirements for operators who administer Mnemo deployments.

164.310(c) – Workstation Security

FieldDetail
HIPAA Reference164.310(c)
RequirementImplement physical safeguards for all workstations that access ePHI.
Mnemo ImplementationNot directly applicable. See workstation use above.
StatusOperational
GapsDocument workstation security requirements in the deployment guide.

164.310(d)(1) – Device and Media Controls

Requirement: Implement policies and procedures that govern the receipt and removal of hardware and electronic media containing ePHI.

(i) Disposal (Required)

FieldDetail
HIPAA Reference164.310(d)(2)(i)
RequirementImplement policies for the final disposition of ePHI and/or the hardware or electronic media on which it is stored.
Mnemo Implementationhard_delete_memory() permanently removes records from DuckDB storage. cleanup_expired() removes expired memories. Cognitive forgetting (run_decay_pass()) automatically transitions aging memories through the Archived and Forgotten states. Encrypted content requires the encryption key for meaningful access.
StatusPartially Implemented
GapsImplement secure wipe (zero-fill) for hard-deleted records. Add cryptographic erasure support (destroying the encryption key to render stored ciphertext unrecoverable). Document media disposal procedures.

(ii) Media Re-use (Required)

FieldDetail
HIPAA Reference164.310(d)(2)(ii)
RequirementImplement procedures for removal of ePHI from electronic media before re-use.
Mnemo ImplementationDuckDB file storage can be wiped by deleting the database file. Encrypted content is not recoverable without the encryption key.
StatusOperational
GapsDocument media re-use procedures. Implement database purge utilities.

Technical Safeguards (Section 164.312)

Technical safeguards are the technology, and the policy and procedures for its use, that protect ePHI and control access to it.

164.312(a)(1) – Access Control

Requirement: Implement technical policies and procedures for electronic information systems that maintain ePHI to allow access only to those persons or software programs that have been granted access rights.

(i) Unique User Identification (Required)

FieldDetail
HIPAA Reference164.312(a)(2)(i)
RequirementAssign a unique name and/or number for identifying and tracking user identity.
Mnemo ImplementationEvery agent is identified by a unique agent_id string. All operations (memory CRUD, events, delegations) are attributed to the performing agent. The PrincipalType enum supports five identity types: Agent, User, Org, Role, Public. Memory records track created_by for creator attribution. Event records include agent_id, thread_id, and run_id for operation attribution.
StatusImplemented
GapsNone. Unique identification is comprehensive.

(ii) Emergency Access Procedure (Required)

FieldDetail
HIPAA Reference164.312(a)(2)(ii)
RequirementEstablish procedures for obtaining necessary ePHI during an emergency.
Mnemo ImplementationAdmin-level permissions provide unrestricted access. Mnemo can operate locally with DuckDB without network dependencies. Checkpoint restore enables recovery of specific state snapshots.
StatusPartially Implemented
GapsDocument emergency access procedures. Implement break-glass access mechanism with enhanced audit logging.

(iii) Automatic Logoff (Addressable)

FieldDetail
HIPAA Reference164.312(a)(2)(iii)
RequirementImplement electronic procedures that terminate an electronic session after a predetermined time of inactivity.
Mnemo ImplementationMCP STDIO sessions are bound to process lifetime. ACL entries and delegations support expires_at for time-based access termination.
StatusPartially Implemented
GapsImplement session timeout for REST API connections. Add configurable inactivity timeout for MCP sessions.

(iv) Encryption and Decryption (Addressable)

FieldDetail
HIPAA Reference164.312(a)(2)(iv)
RequirementImplement a mechanism to encrypt and decrypt ePHI.
Mnemo ImplementationThe ContentEncryption module (crates/mnemo-core/src/encryption.rs) provides encryption/decryption of memory content. Keys are 256-bit, loaded from environment variables. The encryption produces nonce || ciphertext || tag format with integrity verification on decryption.
StatusPartially Implemented
GapsUpgrade to production-grade AES-256-GCM using the aes-gcm crate (currently uses a simplified XOR cipher). Implement key rotation. Add per-field encryption for metadata.

164.312(b) – Audit Controls

FieldDetail
HIPAA Reference164.312(b)
RequirementImplement hardware, software, and/or procedural mechanisms that record and examine activity in information systems that contain or use ePHI.
Mnemo ImplementationThe AgentEvent system provides comprehensive audit logging. Every data access operation generates an event record with: unique id (UUID v7, time-ordered), agent_id, thread_id, run_id, event_type (15 types covering all operations), payload (JSON with operation details), timestamp, logical_clock (monotonic ordering), content_hash and prev_hash (hash chain integrity). OpenTelemetry fields (trace_id, span_id) enable correlation with external observability systems. Query methods support review by agent, thread, or event hierarchy.
StatusImplemented
GapsAdd tamper-evident log export to external storage. Implement log retention policies. Add real-time audit stream for SIEM integration.

164.312(c)(1) – Integrity

Requirement: Implement policies and procedures to protect ePHI from improper alteration or destruction.

(i) Mechanism to Authenticate ePHI (Addressable)

FieldDetail
HIPAA Reference164.312(c)(2)
RequirementImplement electronic mechanisms to corroborate that ePHI has not been altered or destroyed in an unauthorized manner.
Mnemo ImplementationThe hash chain system (crates/mnemo-core/src/hash.rs) provides two levels of integrity verification: (1) Content hashcompute_content_hash(content, agent_id, timestamp) produces a SHA-256 hash of each memory’s content, agent, and timestamp. (2) Chain hashcompute_chain_hash(content_hash, prev_hash) links each record to its predecessor, creating a tamper-evident chain. verify_chain() validates both content hashes and chain linkage, reporting ChainVerificationResult with the exact record where tampering is detected. The encryption module adds a 16-byte HMAC tag to ciphertext, verified on decryption. Memory versioning (version, prev_version_id) tracks all modifications.
StatusImplemented
GapsAdd automated periodic integrity verification. Consider adding digital signatures for non-repudiation.

164.312(d) – Person or Entity Authentication

FieldDetail
HIPAA Reference164.312(d)
RequirementImplement procedures to verify that a person or entity seeking access to ePHI is the one claimed.
Mnemo ImplementationAgent identity is established through the agent_id field on all operations. The MCP STDIO transport binds sessions to OS-level processes. The permission system verifies that the requesting agent has appropriate authorization before returning data.
StatusPartially Implemented
GapsImplement cryptographic authentication (API keys, mTLS, JWT). Add support for multi-factor authentication for administrative operations. Integrate with external identity providers (OIDC, SAML, LDAP).

164.312(e)(1) – Transmission Security

Requirement: Implement technical security measures to guard against unauthorized access to ePHI that is being transmitted over an electronic communications network.

(i) Integrity Controls (Addressable)

FieldDetail
HIPAA Reference164.312(e)(2)(i)
RequirementImplement security measures to ensure that electronically transmitted ePHI is not improperly modified without detection.
Mnemo ImplementationContent hashes travel with memory records, enabling integrity verification at the receiving end. The hash chain provides ordering integrity across sequences of records.
StatusPartially Implemented
GapsImplement message-level signatures for MCP protocol messages. Add integrity verification for REST API responses.

(ii) Encryption (Addressable)

FieldDetail
HIPAA Reference164.312(e)(2)(ii)
RequirementImplement a mechanism to encrypt ePHI whenever deemed appropriate during transmission.
Mnemo ImplementationThe MCP STDIO transport operates over local Unix pipes, which are not exposed to network transmission. For network deployments, the documentation recommends TLS. The PostgreSQL mode supports TLS connections. The Docker deployment guide recommends reverse proxy with TLS termination.
StatusPartially Implemented
GapsEnforce TLS for all network transports (reject non-TLS connections). Implement TLS certificate pinning for PostgreSQL connections. Add MCP-over-TLS support for remote agent connections.

Summary Matrix

Safeguard CategorySectionStatusKey Modules
Security Management164.308(a)(1)Partially Implementedpoisoning.rs, encryption.rs, hash.rs, acl.rs
Assigned Security Responsibility164.308(a)(2)Operationalacl.rs (Admin role)
Workforce Security164.308(a)(3)Implementedacl.rs, delegation.rs
Information Access Management164.308(a)(4)Implementedacl.rs, delegation.rs, MCP tools
Security Awareness164.308(a)(5)Partially Implementedpoisoning.rs, documentation
Security Incident Procedures164.308(a)(6)Partially ImplementedQuarantine, hash.rs, event.rs
Contingency Plan164.308(a)(7)Partially Implementedcheckpoint.rs, MCP tools
Evaluation164.308(a)(8)Partially Implementedhash.rs, test suite
Facility Access164.310(a)(1)OperationalDocker, Kubernetes
Workstation Use/Security164.310(b-c)OperationalN/A
Device and Media Controls164.310(d)(1)Partially ImplementedDelete operations, encryption.rs
Access Control164.312(a)(1)Partially Implementedacl.rs, delegation.rs, encryption.rs
Audit Controls164.312(b)Implementedevent.rs
Integrity164.312(c)(1)Implementedhash.rs, encryption.rs
Authentication164.312(d)Partially Implementedagent_id, MCP session binding
Transmission Security164.312(e)(1)Partially ImplementedTLS recommendations, hash.rs

Priority Gaps for HIPAA Compliance

The following items represent the highest-priority gaps for organizations deploying Mnemo in HIPAA-regulated environments. They are listed in recommended order of implementation:

  1. Upgrade encryption to production-grade AES-256-GCM (164.312(a)(2)(iv)) – Replace the simplified XOR cipher with the aes-gcm crate. This is the single most critical gap for HIPAA compliance.

  2. Implement cryptographic authentication (164.312(d)) – Add API key management, mTLS, or JWT-based authentication. Agent identity must be cryptographically verified, not just asserted.

  3. Enforce TLS for all network transports (164.312(e)(2)(ii)) – Reject non-TLS connections in network deployment modes. Implement certificate validation.

  4. Add key rotation and management (164.312(a)(2)(iv)) – Implement encryption key rotation without downtime. Add envelope encryption for per-record key management.

  5. Implement automated backup and recovery (164.308(a)(7)) – Add scheduled checkpoint creation, backup verification, and documented recovery procedures with defined RTO/RPO.

  6. Add session timeout (164.312(a)(2)(iii)) – Implement configurable inactivity timeout for REST API and MCP sessions.

  7. Implement tenant isolation (164.308(a)(4)) – Enforce strict data separation by org_id at the database query level to prevent cross-tenant data leakage.

  8. Implement break-glass access (164.312(a)(2)(ii)) – Add an emergency access mechanism with enhanced audit logging for HIPAA-mandated emergency access procedures.


Deployment Recommendations for Covered Entities

Organizations subject to HIPAA that deploy Mnemo should implement the following operational controls in addition to Mnemo’s built-in safeguards:

Infrastructure

  • Deploy Mnemo behind a TLS-terminating reverse proxy (e.g., nginx, Envoy).
  • Use PostgreSQL mode with TLS-encrypted connections for production.
  • Store the encryption key (MNEMO_ENCRYPTION_KEY) in a secrets manager (e.g., HashiCorp Vault, AWS Secrets Manager), not in environment files.
  • Run Mnemo containers with read-only root filesystems and non-root users.
  • Implement network policies restricting Mnemo’s inbound and outbound traffic.

Operations

  • Assign a security official responsible for Mnemo deployment and configuration.
  • Conduct a risk assessment specific to your PHI data flows through Mnemo.
  • Establish backup schedules using the checkpoint system with offsite replication.
  • Document and test disaster recovery procedures quarterly.
  • Implement log forwarding from Mnemo’s event log to your SIEM system.
  • Schedule periodic hash chain verification using the mnemo.verify tool.

Access Management

  • Map organizational roles to Mnemo’s permission hierarchy.
  • Use time-bounded delegations with the minimum required permission level.
  • Review active ACLs and delegations quarterly.
  • Implement agent deprovisioning procedures that revoke all permissions.
  • Maintain an access authorization matrix mapping agents to data categories.

Incident Response

  • Define incident severity levels for Mnemo security events.
  • Establish escalation procedures for quarantine events and verification failures.
  • Document breach notification procedures per HIPAA requirements (60-day notification timeline).
  • Conduct tabletop exercises simulating data integrity incidents.

Training

  • Train operators on Mnemo’s security features and compliance controls.
  • Include Mnemo-specific content in HIPAA security awareness training.
  • Document procedures for handling PHI within agent memory workflows.

DPDPA — Digital Personal Data Protection Act (India)

Enforceable from 13 November 2026, the DPDPA requires Indian data fiduciaries to consult a DPB-registered Consent Manager before processing personal data and to honour consent withdrawal as an erasure right.

Mnemo’s mnemo-compliance crate provides two primitives to help with this; both are behind the compliance feature flag so v0.1.1 callers stay compiling.

ConsentSource trait

crates/mnemo-compliance/src/consent.rs. A pluggable interface that looks up the current consent state for a subject.

#![allow(unused)]
fn main() {
use mnemo_compliance::{ConsentSource, ConsentState, HttpConsentManager};

let cm = HttpConsentManager::new("https://consent.example.com/v1")
    .with_bearer(std::env::var("CONSENT_TOKEN")?);
let state: ConsentState = cm.fetch_consent("user-42").await?;
if state.has_scope("remember") && state.is_active() {
    // proceed with writing personal data
}
}

Available implementations

  • HttpConsentManager — generic HTTP binding. Expects GET {base_url}/consent/{subject_id} to return a body matching [ConsentState]. Optional bearer-token auth.
  • StaticConsentSource — in-memory map, for tests and single-tenant self-hosting.

ConsentState shape

#![allow(unused)]
fn main() {
pub struct ConsentState {
    pub subject_id: String,
    pub scopes: Vec<String>,          // granted purposes
    pub expires_at: Option<String>,   // optional wall-clock expiry
    pub token_hash: String,           // SHA-256 of the signed token
}
}

Missing scopes are treated as denied. Expired states are rejected by is_active() and by HttpConsentManager::fetch_consent.

Operators should call fetch_consent before every engine.remember that touches personal data, and map a missing scope to ComplianceError::ConsentDenied { subject_id, scope }. A reference middleware is sketched in the compliance feature’s docs but not yet wired into the core remember pipeline — doing so is part of the v0.3.2 roadmap (requires a PolicyHook surface on MnemoEngine).

Wire the consent manager’s withdrawal webhook to [engine.forget_subject(subject_id, ForgetStrategy::Redact)] (which ships since v0.2.0). Redact preserves content_hash + prev_hash so the audit trail stays verifiable even after the content is erased; alternatively use HardDelete if you have no retention obligation.

Audit trail

Every forget_subject emits a MemoryRedact audit event with a hash-chain link to the prior event. Combine with the EU AI Act export surface for a single signed trail.

EU AI Act — audit log export

The EU AI Act (enforceable from 2 August 2026 for GPAI providers) requires retention of event logs with integrity controls and a path to export records for AI Office document requests. Mnemo’s mnemo-compliance crate ships a matching surface.

export_audit_log

#![allow(unused)]
fn main() {
use mnemo_compliance::{
    AuditFormat, AuditSigner, export_audit_log, verify_ndjson_signed,
};

let events = engine.storage.list_events("agent-id", 10_000, 0).await?;
let signer = AuditSigner::from_secret_bytes(&ed25519_secret);

// NDJSON with detached Ed25519 signature chain
let bundle = export_audit_log(
    &events,
    AuditFormat::NdjsonSigned,
    Some(&signer),
)?;
std::fs::write("audit.ndjson", bundle.bytes)?;

// Reverse: verify
let verified = verify_ndjson_signed(
    &std::fs::read("audit.ndjson")?,
    bundle.verifying_key_hex.as_ref().unwrap(),
)?;
}

Supported formats

  • AuditFormat::NdjsonSigned — one JSON line per event plus a detached Ed25519 signature that covers SHA256(index ∥ prev_hash ∥ event_json). Canonicalises through serde_json::Value so the signer and verifier agree on bytes regardless of struct field ordering. Tampering breaks the chain at the first mutated byte and verify_ndjson_signed returns ComplianceError::ChainBroken { index, reason }.
  • AuditFormat::EuAiOfficeCsv — the columnar template the AI Office consumes for GPAI document requests. RFC4180-escaped; header row first. Columns: event_id, timestamp, agent_id, event_type, model, thread_id, tokens_input, tokens_output, content_hash.

Key management

AuditSigner never generates or stores keys on its own. Operators are expected to keep the 32-byte Ed25519 secret behind an HSM or KMS and pass it through AuditSigner::from_secret_bytes. generate_ephemeral exists purely for tests.

Integration with forget_subject

When a DPDPA consent withdrawal triggers forget_subject, the emitted MemoryRedact events land in the audit trail with a proper prev_hash link. A later export_audit_log call signs the chain end-to-end, giving regulators a single artefact that covers both the original write and its regulated erasure.

What’s NOT in v0.3.1

  • No encryption-key rotation story (deferred to v0.4.0).
  • No streaming export from the REST / gRPC surfaces — today the export function is synchronous against an in-memory event list. For very long audit windows, callers should batch via storage.list_events(agent_id, limit, offset) and feed slices into export_audit_log.
  • No retention-policy enforcement. The trail retains whatever the storage backend retains.

Performance

Benchmarks

Every published headline number — retrieval quality, poisoning resistance, audit tamper-evidence — with its exact reproduction command and raw-results file lives in one place: the benchmark index. Start there; each row also says what the number does not show.

Mnemo includes Criterion benchmarks in benches/engine_bench.rs:

cargo bench -p mnemo-core

Retrieval Strategies

StrategySpeedQualityBest For
exactFastestFilter-onlyKnown queries, tag-based
bm25FastGood for keywordsKeyword search
vectorMediumBest semanticSemantic similarity
graphMediumGood for relatedConnected memories
hybridSlowestBest overallGeneral use (default)

Storage Backend Comparison

MetricDuckDBPostgreSQL
Latency (single op)~1ms~5ms
ThroughputHigh (local)High (concurrent)
Memory usageLowMedium
SetupZero-configRequires server

Optimization Tips

  1. Use noop embeddings during development (faster, no API calls)
  2. Set appropriate limits in recall to avoid over-fetching
  3. Use tags and filters to narrow search space before semantic search
  4. Use exact strategy when you know the filtering criteria
  5. Run decay passes periodically to clean up low-importance memories