Skip to main content

notmemory

Deterministic memory observability for long-lived AI agents.

CI Python License PyPI


What is notmemory?

notmemory is an open-source Python SDK that gives AI agents auditable, reversible, GDPR-compliant memory.

Every memory write is cryptographically hash-chained — like Git commits for agent state. Every mistake can be rolled back. Every deletion leaves a forensic trail. Every read is logged.

Built for production AI systems where trust, compliance, and debuggability are non-negotiable.


Why notmemory?

Problem notmemory solution
Agent hallucinates and corrupts memory rollback(transaction_id) undoes it
GDPR deletion request forget(bank_id) tombstones with audit trail
Can't debug what agent remembered get_audit_trail(cycle_id) forensic replay
Memory grows stale over time Confidence decay c = c₀ · 2^(-t/30)
Need semantic search too Mem0 / SuperMemory sync-layer adapters
Want Claude/Cursor to use agent memory MCP server adapter

Features

  • Cryptographic audit trail — SHA-256 hash chaining on every write
  • Git-like rollback — undo any transaction by ID
  • Conflict detection — duplicate detection with health score 0–100
  • GDPR tombstoning — compliant deletion with forensic trail
  • Full-text search — SQLite FTS5 keyword search
  • Confidence decay — exponential half-life c = c₀ · 2^(-t/30)
  • LangGraph checkpointer — drop-in replacement for MemorySaver
  • LangChain chat history — BaseChatMessageHistory implementation
  • Mem0 sidecar — semantic search via Mem0
  • SuperMemory sidecar — semantic search via SuperMemory
  • MCP server — Claude Desktop / Cursor / Windsurf integration

Install

# Core SDK
pip install notmemory

# With LangChain / LangGraph
pip install "notmemory[langchain]"

# With Mem0 semantic search
pip install "notmemory[mem0]" mem0ai

# With MCP server
pip install "notmemory[mcp]"

# Everything
pip install "notmemory[langchain,mcp]" mem0ai

Quickstart

import asyncio
from notmemory import AgentMemory, MemoryConfig

async def main():
    async with AgentMemory() as memory:

        # Store a memory
        entry = await memory.retain(
            bank_id="facts",
            content={"fact": "The Eiffel Tower is in Paris"},
            source="user",
        )
        print(f"Stored: {entry.id}")

        # Search memory
        result = await memory.recall(
            bank_id="facts",
            query="Eiffel Tower",
        )
        for e in result.entries:
            print(e.content)

        # Rollback a bad write
        await memory.rollback(entry.transaction_id)

        # GDPR delete entire bank
        await memory.forget("facts")

asyncio.run(main())

Core API

AgentMemory

from notmemory import AgentMemory, MemoryConfig

config = MemoryConfig(db_url="sqlite+aiosqlite:///./myagent.db")

async with AgentMemory(config=config) as memory:
    ...
Method Returns Description
retain(*, bank_id, content, ...) MemoryEntry Store with hash chain
recall(*, bank_id, query, ...) RecallResult Keyword / temporal search
rollback(transaction_id) RollbackResult Tombstone a transaction
detect_conflicts(*, bank_id) ConflictReport Find duplicates, health score
log_cycle_event(*, cycle_id, ...) CycleEvent DAG audit event
get_audit_trail(*, cycle_id) AuditTrail Forensic reconstruction
verify_integrity(bank_id) bool Verify SHA-256 hash chain
forget(bank_id, *, entry_ids) int GDPR tombstone

Confidence Decay

Memories lose confidence over time using exponential half-life decay: c(t) = c₀ · 2^(-t / half_life_days)

Age Confidence (from 1.0)
0 days 1.000
30 days 0.500
60 days 0.250
90 days 0.125
from notmemory.memory.decay import decayed_confidence, filter_fresh

# Current decayed score
score = decayed_confidence(entry, half_life_days=30.0)

# Filter stale entries out, sort fresh ones by score
fresh = filter_fresh(entries, half_life_days=30.0, deprecation_threshold=0.05)

Adapters

LangChain / LangGraph

from notmemory.adapters.langchain import (
    NotMemoryCheckpointer,
    NotMemoryChatHistory,
)

# Drop-in for MemorySaver — adds hash-chained audit trail
checkpointer = NotMemoryCheckpointer()
graph = builder.compile(checkpointer=checkpointer)

async with checkpointer:
    result = await graph.ainvoke(inputs, config)

# Chat history with GDPR tombstoning
history = NotMemoryChatHistory(session_id="user-42")
async with history:
    await history.aadd_messages(messages)
    msgs = await history.aget_messages()

Mem0

from notmemory.adapters.mem0 import NotMemoryMem0Adapter
import os

adapter = NotMemoryMem0Adapter(
    mem0_api_key=os.environ["MEM0_API_KEY"],
    user_id="agent-1",
)
async with adapter:
    # Writes to SQLite + mirrors to Mem0
    await adapter.retain(bank_id="facts", content={"fact": "..."})

    # Keyword search (SQLite)
    result = await adapter.recall(bank_id="facts", query="Paris")

    # Semantic search (Mem0)
    results = await adapter.semantic_recall("European capitals")

SuperMemory

from notmemory.adapters.supermemory import NotMemorySuperMemoryAdapter
import os

adapter = NotMemorySuperMemoryAdapter(
    api_key=os.environ["SUPERMEMORY_API_KEY"],
    user_id="agent-1",
)
async with adapter:
    await adapter.retain(bank_id="facts", content={"fact": "..."})
    results = await adapter.semantic_recall("European capitals")

MCP Server (Claude Desktop / Cursor / Windsurf)

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "notmemory": {
      "command": "python",
      "args": ["-m", "notmemory.adapters.mcp"],
      "env": {
        "NOTMEMORY_DB_URL": "sqlite+aiosqlite:///./notmemory.db"
      }
    }
  }
}

Available tools: notmemory_retain, notmemory_recall, notmemory_rollback, notmemory_forget, notmemory_health


Configuration

from notmemory import MemoryConfig
from notmemory.core.config import HashChainConfig, RetentionConfig

config = MemoryConfig(
    storage="sqlite",
    db_url="sqlite+aiosqlite:///./agent.db",
    hash_chain=HashChainConfig(
        enabled=True,
        algorithm="sha256",
    ),
    retention=RetentionConfig(
        confidence_half_life_days=30.0,
        deprecation_threshold=0.05,
    ),
)

Project Structure

notmemory/ ├── core/ │ ├── agent_memory.py # AgentMemory — main interface │ ├── config.py # MemoryConfig (Pydantic v2) │ └── exceptions.py # exception hierarchy ├── memory/ │ ├── models.py # domain models │ └── decay.py # confidence decay ├── storage/ │ └── backends/ │ ├── base.py # abstract storage interface │ └── sqlite.py # SQLite + FTS5 + hash chaining └── adapters/ ├── base.py # BaseAdapter abstract class ├── langchain.py # LangChain / LangGraph ├── mem0.py # Mem0 sync-layer ├── supermemory.py # SuperMemory sync-layer └── mcp.py # MCP server


Development

git clone https://github.com/notmemory/notmemory
cd notmemory

python -m venv .venv
# Windows:
.venv\Scripts\Activate.ps1
# macOS/Linux:
source .venv/bin/activate

pip install -e ".[dev,langchain,mcp]" mem0ai

# Before every commit
ruff check . --fix
ruff format .
pytest --tb=short

Contributing

  1. Fork the repo
  2. Branch from develop: git checkout -b feature/your-feature
  3. Make changes, run ruff + pytest
  4. Open PR targeting develop
  5. CI must be green on Python 3.11, 3.12, 3.13

License

MIT — see LICENSE.

Release files for notmemory 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for notmemory 0.1.0
File Size Uploaded
notmemory-0.1.0.tar.gz 34.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for notmemory 0.1.0
File Interpreter ABI Platform
notmemory-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 69.7 kB

Release files / notmemory-0.1.0.tar.gz

Download URL notmemory-0.1.0.tar.gz
Size 34.8 kB
Tags Source
SHA-256 checksum
How to use checksums
3f31d96291ba60fe8411293edf1d96af33eb9417c91084696b1d36e00a32a672
BLAKE2b-256 checksum
How to use checksums
8a8b5ea629b44cbc865f794d897aba53bff33727c7a39b227b90cb53449c5c11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.

Transparency log

Release files / notmemory-0.1.0-py3-none-any.whl

Download URL notmemory-0.1.0-py3-none-any.whl
Size 34.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
833d7fc859ce2017aecb4aebdf54913e1787afc2426ad347337924064a028ee0
BLAKE2b-256 checksum
How to use checksums
cacc945bfbb97cac352706084ef3a95d48c137a12159fcce5241625b42dc48bd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page