Belief-based agent memory: correct under evolution, cheap on recall
Project description
mem01
Self-hosted long-term memory for AI agents.
mem01 extracts durable facts from conversation, stores them as beliefs with an explicit lifecycle (ADD / UPDATE / SUPERSEDE / INVALIDATE / MERGE), and retrieves a token-budgeted, conflict-filtered context block on each turn. Writes may call an LLM once per batch; reads do not call an LLM.
| Deploy | Self-hosted (your infrastructure) |
| Store | PostgreSQL + pgvector |
| Interfaces | HTTP API, Python SDK |
| Requirements | Docker (recommended), OpenAI-compatible API key for extraction/embeddings |
Product intent and constraints: PRODUCT.md.
Architecture
Agents / apps
│ HTTP or Python SDK
▼
┌──────────────────┐ ┌─────────────────────────┐
│ mem01 API │─────▶│ PostgreSQL + pgvector │
│ (FastAPI) │ │ beliefs + embeddings │
└──────────────────┘ └─────────────────────────┘
| Path | Behavior |
|---|---|
Write (remember) |
Messages → LLM extraction → belief ops → embed → Postgres |
Read (recall) |
Embed query → vector search + scope filters → conflict rules → token packer → context string |
Default model stack (configurable): gpt-5.6-sol for OpenAI extraction,
text-embedding-3-small (1536-d) for vectors. Anthropic is supported for
extraction; embeddings still need an embedding provider.
Quick start
1. Configure
cp .env.example .env
Set at least:
OPENAI_API_KEY=sk-...
MEM01_LLM_MODEL=gpt-5.6-sol
MEM01_LLM_MODEL is passed into the API container by Docker Compose and selected
by the API at startup. gpt-5.6-sol is the default for both the API and the
embedded Mem01Session runtime.
Docker Compose sets DATABASE_URL for the API container. Host-side Python tools should use:
DATABASE_URL=postgresql://mem01:mem01@localhost:5433/mem01
2. Run the stack
docker compose up -d --build
| Service | Address |
|---|---|
| API | http://localhost:8080 |
| OpenAPI | http://localhost:8080/docs |
| Health | http://localhost:8080/health |
| PostgreSQL | localhost:5433 (user / password / db: mem01) |
3. Call the API
curl -s http://localhost:8080/v1/remember \
-H 'Content-Type: application/json' \
-d '{
"user_id": "user_1",
"messages": [{"role": "user", "content": "I live in San Francisco."}]
}'
curl -s http://localhost:8080/v1/recall \
-H 'Content-Type: application/json' \
-d '{
"user_id": "user_1",
"query": "Where does the user live?",
"max_memory_tokens": 800
}'
Stop:
docker compose down
HTTP API
| Method | Path | Description |
|---|---|---|
GET |
/health |
Process liveness |
POST |
/v1/remember |
Ingest messages; extract and apply belief operations |
POST |
/v1/recall |
Retrieve a budgeted memory block for a query (include_history optional) |
POST |
/v1/history |
Full belief timeline (active + superseded + invalidated) |
POST |
/v1/correct |
Supersede a belief by id with a corrected value |
POST |
/v1/forget |
Invalidate a belief by id |
Request shapes
POST /v1/remember
{
"user_id": "user_1",
"project_id": "optional",
"messages": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
]
}
POST /v1/recall
{
"user_id": "user_1",
"query": "Where does the user live?",
"max_memory_tokens": 800,
"k": 20,
"include_history": false
}
- Default (
include_history: false): active only — single current truth for the agent. include_history: true: also returns superseded/invalidated, labeled as[active]/[superseded]so temporal questions (“before SF?”) work without polluting every turn.
POST /v1/history
{
"user_id": "user_1",
"include_invalidated": true,
"limit": 100
}
Chronological audit timeline (no vector search). Use for admin UI, medical-style charts, or “show me what changed.”
POST /v1/correct
{
"memory_id": "bel_...",
"new_value": "User lives in Oakland",
"confidence": 0.95
}
POST /v1/forget
{
"memory_id": "bel_...",
"reason": "optional"
}
Interactive schema: http://localhost:8080/docs
Python SDK
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,openai]"
Ensure Postgres is running (docker compose up -d or your own instance) and DATABASE_URL is set in .env.
from mem01 import MemoryClient, create_belief_store
from mem01.embeddings.openai_embedder import OpenAIEmbedder
from mem01.llm.openai_compat import OpenAICompatLLM
store = create_belief_store() # requires DATABASE_URL → Postgres + pgvector
client = MemoryClient(
store=store,
embedder=OpenAIEmbedder(),
llm=OpenAICompatLLM(),
)
client.remember(
[{"role": "user", "content": "I prefer TypeScript."}],
user_id="user_1",
)
block = client.recall("language preference", user_id="user_1", max_memory_tokens=800)
print(block.text, block.tokens_used, block.latency_ms)
| Method | Description |
|---|---|
remember(messages, user_id=...) |
Extract ops and persist |
recall(query, user_id=..., max_memory_tokens=800) |
Retrieve packed context |
correct(memory_id, new_value) |
Supersede by id |
forget(memory_id) |
Invalidate by id |
Configuration
| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY |
For real extract/embed | OpenAI (or compatible) API key |
DATABASE_URL |
For API / SDK | postgresql://... (Docker host: port 5433) |
MEM01_EMBEDDING_DIM |
No (default 1536) |
Must match embedding model dimensions |
MEM01_LLM_MODEL |
No (default gpt-5.6-sol) |
OpenAI extraction model used by the API and embedded runtime |
MEM01_EMBEDDING_MODEL |
No (default text-embedding-3-small) |
OpenAI embedding model name |
Neon: use a Neon connection string as DATABASE_URL (include sslmode=require). No application code changes.
Belief model (summary)
Stored units are beliefs, not raw chat chunks. Operations:
| Op | Effect |
|---|---|
ADD |
Insert active belief |
UPDATE |
Revise content/confidence in place |
SUPERSEDE |
New active belief; previous marked superseded |
INVALIDATE |
Soft-delete (excluded from default recall) |
MERGE |
Collapse duplicates into one canonical belief |
Scopes: user, project, agent, session. Default sharing is user- and project-level.
Full design: PRODUCT.md.
Development
# Stack
docker compose up -d --build
# Tests (unit tests use an in-process store; Postgres tests need DATABASE_URL)
source .venv/bin/activate
pip install -e ".[dev,openai]"
pytest
# Postgres integration tests
export DATABASE_URL=postgresql://mem01:mem01@localhost:5433/mem01
pytest tests/test_postgres_store.py
Repository layout:
| Path | Role |
|---|---|
src/mem01/ |
Library and API |
src/mem01/api/app.py |
FastAPI application |
src/mem01/store/postgres_store.py |
Postgres + pgvector backend |
docker-compose.yml |
API + database |
examples/basic_usage.py |
CLI walkthrough |
Status
| Component | Status |
|---|---|
| Belief store + ops | Implemented |
| Write path (extract → apply) | Implemented |
| Read path (search → conflict → pack) | Implemented |
| HTTP API + Docker Compose | Implemented |
| MCP server | Not yet |
| Background consolidation | Not yet |
| Multi-tenant hosted SaaS | Out of scope for v1 |
License
See repository license file when published.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mem01_engine-0.1.0.tar.gz.
File metadata
- Download URL: mem01_engine-0.1.0.tar.gz
- Upload date:
- Size: 70.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7bfda2c2688e733c43896ead0655cb43361687bddd01a262f00b9e7448ba7359
|
|
| MD5 |
2ac1b828c38c836bb86d51c4e37b3e44
|
|
| BLAKE2b-256 |
1a2ac30fab27ce78388398bffec3fcb5474873791af04239bb064e3c5c2ab7db
|
File details
Details for the file mem01_engine-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mem01_engine-0.1.0-py3-none-any.whl
- Upload date:
- Size: 47.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b33eb4a86d05610dc42797791c767b192e711e42f58dc0956deeb2a52c10f3c6
|
|
| MD5 |
c5be0764f285de360300acc20ba456fd
|
|
| BLAKE2b-256 |
a1e021bab0fbbef32ab520455ac68da345cbd26ddbd09251eddf152709ff168a
|