Skip to main content

Production-grade plug-and-play memory for AI agents. Zero config, single-file storage, framework-agnostic.

Project description

membox

Production-grade plug-and-play memory for AI agents.

Give any LLM, agent, or rule-based system persistent episodic + semantic memory. Zero config, single-file storage, framework-agnostic.

from membox import Membox

memory = Membox("my_agent.db")
memory.record("User said they love hiking in the Himalayas", importance=0.8)
memory.learn("user", "prefers", "black coffee", confidence=0.9)

# Retrieve relevant memories
results = memory.recall("what are the user's hobbies?", k=3)

# Get prompt-ready context string
context = memory.context("what does the user like?")
# → "## User Profile\n- user prefers black coffee (90%)\n\n## Relevant Memories\n- ..."

Features

Feature Description
Episodic memory Timestamped events with importance + emotion scoring
Semantic memory Fact triples with reinforcement & contradiction
Procedural memory Trigger → action routines, surfaced in context
Temporal facts valid_from / valid_until windows + recurrence patterns
Reflection Synthesizes higher-order patterns across episodes
Smart retrieval Recency × relevance × importance (keyword or embeddings)
Context builder Token-budgeted prompt string: profile + procedures + memories + patterns
Thread summarization pi-style compaction of long conversation threads
Consolidation Compress episodes → stable facts
Forgetting Importance-weighted decay (trivial memories die, critical ones survive)
Editing & correction In-place episode edits + timestamped annotation audit trail
Multi-user isolation owner_id scoping — one DB, many users, no cross-contamination
Embeddings (optional) SQLite-backed semantic retrieval via sentence-transformers
Zero dependencies Core runs on Python stdlib only (SQLite)
Single-file storage One .db file = entire memory. Copy it, back it up, version it.

Install

# From source (development)
git clone <repo-url> && cd membox
uv sync --extra dev

# Coming soon: pip install membox

Quick Start

Want to run these examples in a browser? Open notebooks/quickstart.ipynb — a 5-minute executable version of everything below. For the full simple→advanced tour, see notebooks/walkthrough.ipynb.

1. Record Events

from membox import Membox

memory = Membox("jarvis.db")

# Record what happens
memory.record("User got promoted to Director of Engineering!", importance=1.0, emotion="ecstatic")
memory.record("User ordered black coffee", importance=0.3)
memory.record("User's dog Rocky had a vet visit. All clear.", importance=0.5, emotion="relieved")

2. Learn Facts

# Semantic facts with automatic conflict resolution
memory.learn("user", "name", "Pranav", confidence=0.95)
memory.learn("user", "prefers", "black coffee", confidence=0.9)
memory.learn("user", "lives_in", "Delhi", confidence=0.8)

# Repeat a fact → confidence increases (reinforcement)
memory.learn("user", "prefers", "black coffee")  # → confidence: 0.9 → 0.915

# New info → old fact deactivated (contradiction)
memory.learn("user", "lives_in", "Mumbai")  # Delhi deactivated, Mumbai active

3. Retrieve Memories

# Keyword + recency + importance scoring
results = memory.recall("coffee", k=3)
for r in results:
    print(f"Score: {r.score:.3f} | {r.episode.content}")
    # Score breakdown: R=recency, V=relevance, I=importance
    print(f"  R={r.recency:.2f} V={r.relevance:.2f} I={r.importance:.2f}")

4. Build LLM Context

# Generate a prompt-ready context string
context = memory.context("What should I get for dinner?", max_tokens=2000)
print(context)
# Output:
# ## User Profile
# - user name Pranav (95%)
# - user prefers black coffee (92%)
# - user lives_in Mumbai (80%)
#
# ## Relevant Memories
# - (2h ago) User ordered black coffee
# - (1d ago [ecstatic]) User got promoted to Director of Engineering!
# (when procedures or reflections exist, `## Active Procedures` and `## Patterns`
#  sections are added too)

# Plug into any LLM:
messages = [
    {"role": "system", "content": f"You are a helpful assistant.\n\n{context}"},
    {"role": "user", "content": "What should I get for dinner?"},
]
# → Send to OpenAI, Anthropic, Ollama, etc.

5. Maintenance

# Compress old episodes into semantic facts
memory.consolidate()        # one batch; use consolidate_all() to drain the backlog

# Synthesize higher-order patterns across episodes
memory.reflect()

# Prune stale memories (importance-weighted; critical ones survive)
result = memory.forget()
print(f"Deleted: {result['deleted']}, Archived: {result['archived']}")

# …or run all of the above in one call:
memory.maintain()

# Health check
print(memory.stats())

Configuration

from membox import Membox, MemoryConfig

# Custom config
config = MemoryConfig(
    decay_rate=0.05,          # How fast memories fade (higher = faster)
    w_recency=0.3,            # Retrieval weight: recency
    w_relevance=0.4,          # Retrieval weight: keyword match
    w_importance=0.3,         # Retrieval weight: stored importance
    max_context_tokens=2000,  # Token budget for context()
)
memory = Membox("agent.db", config=config)

# Or use presets:
fast_memory = Membox("chatbot.db", config=MemoryConfig.fast())    # Aggressive forgetting
deep_memory = Membox("assistant.db", config=MemoryConfig.deep())  # Long retention

Integration Examples

With OpenAI

from openai import OpenAI
from membox import Membox

client = OpenAI()
memory = Membox("openai_agent.db")

def chat(user_message: str) -> str:
    # Store the user message
    memory.record(f"User: {user_message}", importance=0.5)

    # Build context-enhanced prompt
    context = memory.context(user_message)
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": f"You are a helpful assistant.\n\n{context}"},
            {"role": "user", "content": user_message},
        ],
    )
    reply = response.choices[0].message.content

    # Store the response
    memory.record(f"Assistant: {reply}", importance=0.2, source="response")
    return reply

With Anthropic

import anthropic
from membox import Membox

client = anthropic.Anthropic()
memory = Membox("claude_agent.db")

def chat(user_message: str) -> str:
    memory.record(f"User: {user_message}")
    context = memory.context(user_message)

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        system=f"You are a helpful assistant.\n\n{context}",
        messages=[{"role": "user", "content": user_message}],
        max_tokens=1024,
    )
    reply = response.content[0].text
    memory.record(f"Assistant: {reply}", importance=0.2, source="response")
    return reply

With Any Agent Framework

from membox import Membox

memory = Membox("agent.db")

# In your agent's observe/act loop:
def agent_step(observation: str) -> str:
    # 1. Store observation
    memory.record(observation, importance=score_importance(observation))

    # 2. Retrieve relevant context
    context = memory.context(observation)

    # 3. Generate action (your logic here)
    action = your_llm_or_rules(observation, context)

    # 4. Periodic maintenance
    if should_consolidate():
        memory.consolidate()
        memory.forget()

    return action

Architecture

┌─────────────────────────────────────────────────────────────┐
│                      Membox                            │
│                                                              │
│  record()  recall()  learn()  context()  consolidate()      │
│     │         │        │         │            │              │
│     ▼         ▼        ▼         ▼            ▼              │
│  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐   │
│  │Episodic│ │Retriev.│ │Semantic│ │Context │ │Consol. │   │
│  │ Store  │ │ Engine │ │ Store  │ │Builder │ │Pipeline│   │
│  └───┬────┘ └────────┘ └───┬────┘ └────────┘ └────────┘   │
│      │                      │                               │
│      └──────────┬───────────┘                               │
│                 ▼                                            │
│           ┌──────────┐                                      │
│           │  SQLite   │  ← Single .db file                  │
│           │  (WAL)    │                                      │
│           └──────────┘                                      │
└─────────────────────────────────────────────────────────────┘

API Reference

Grouped by memory type. All methods are on Membox.

Category Method Returns
Episodic record(content, importance, emotion, source, context, thread_id, parent_id, depth) Episode
Episodic recall(query, k, min_score) list[RetrievalResult]
Episodic recent(n) list[Episode]
Episodic search(keyword, limit) list[Episode]
Threads thread(thread_id, limit) list[Episode]
Threads thread_children(episode_id, limit) list[Episode]
Threads threads(limit) list[str]
Threads summarize_thread(thread_id) ThreadSummaryResult
Semantic learn(subject, predicate, obj, confidence, valid_from, valid_until, recurrence) (Fact, action)
Semantic about(subject, at_time) list[Fact]
Semantic find_fact(subject, predicate, at_time) list[Fact]
Procedural learn_procedure(trigger, action, confidence) Procedure
Procedural match_procedures(text) list[Procedure]
Procedural procedures() / delete_procedure(id) list[Procedure] / bool
Context context(query, max_tokens, min_score, profile_subject) str
Maintenance consolidate() / consolidate_all() dict
Maintenance reflect(episodes) / reflections(subject) dict / list
Maintenance forget() dict
Maintenance maintain() — runs consolidate → reflect → summarize → forget dict
Editing update_episode(id, ...) / annotate_episode(id, ...) Episode
Editing edit_fact(id, ...) / correct_fact(id, ...) Fact / (Fact, action)
Lifecycle stats() / close() dict / None

learn()'s action is 'new' / 'reinforced' / 'contradicted'. Retrieval scores combine as w_recency·R + w_relevance·V + w_importance·I (see notebooks/walkthrough.ipynb §5).

Design Decisions

Decision Why
SQLite, not Postgres Zero config, ~0.05ms reads, single-file backup. Handles 18M rows (10yr heavy use).
Stdlib only No supply-chain risk. Embedding search is an optional extra.
Sync API Lowest latency path. SQLite calls are <1ms — async overhead isn't worth it.
Store protocols EpisodicStoreProtocol / SemanticStoreProtocol — swap in Postgres/Redis by implementing the protocol.
Tiered forgetting Critical memories (importance ≥ 0.9) never die. Trivial ones fade in days.

Development

# Install dev deps
uv sync --extra dev

# Run tests (262 passed, 19 skipped, ~1.5s)
uv run pytest

# Run with verbose output
uv run pytest -v

# Run scale tests only
uv run pytest tests/test_episodic.py::TestEpisodicScale -v

Documentation

Doc What it's for
README.md (this file) Front door: features, install, quick start, API, design
notebooks/ Runnable examples — quickstart.ipynb (5-min) and walkthrough.ipynb (simple→advanced)
CHANGELOG.md History of changes, release by release
BUGS.md Known-issues tracker — audit with severity, status, and fix notes
lessons/ 8 incremental teaching scripts that build the library from scratch
demos/ demo_openrouter.py — live end-to-end run with a real LLM
integrations/pi/ Long-term memory for pi: HTTP sidecar + TypeScript extension

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

remembox-0.2.0.tar.gz (188.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

remembox-0.2.0-py3-none-any.whl (56.7 kB view details)

Uploaded Python 3

File details

Details for the file remembox-0.2.0.tar.gz.

File metadata

  • Download URL: remembox-0.2.0.tar.gz
  • Upload date:
  • Size: 188.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for remembox-0.2.0.tar.gz
Algorithm Hash digest
SHA256 0697f5ecb165e1678d4a4b7a59c3721821cb87422aa7a6214f6b4eeb707add57
MD5 b6e6a2108c1c3046efd0f0f19273e132
BLAKE2b-256 49bc5a6e314fa0c23f570c6b18e336cc78ba9aa0cb3f0c44b511b9f415ae5655

See more details on using hashes here.

File details

Details for the file remembox-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: remembox-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 56.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for remembox-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e5d198457047fd247c46b6d41b171ffdbcd28f756ea980b457e0ff2d7af15dc6
MD5 75b31dba3e9e7aad91478d041e7195b2
BLAKE2b-256 127b20a81d553ab7073f044e4843aefa322124bdd805d0bfcc1902a5b996d4ab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page