/mɛm-viː/ · Structured, temporal memory for AI agents
Docs • Getting Started • PyPI
Most memory systems extract everything and rely on retrieval to filter it. memv extracts only what the model failed to predict — importance emerges from prediction error, not upfront scoring.
| Typical Approach | memv |
|---|---|
| Extract all facts upfront | Extract only what we failed to predict |
| Overwrite old facts | Invalidate with temporal bounds |
| Retrieve by similarity | Hybrid vector + BM25 + RRF |
| Timestamps only | Bi-temporal: event time + transaction time |
uv add memvee
# or: pip install memveefrom memv import Memory
from memv.embeddings import OpenAIEmbedAdapter
from memv.llm import PydanticAIAdapter
memory = Memory(
db_url="memory.db", # or "postgresql://user:pass@host/db"
embedding_client=OpenAIEmbedAdapter(),
llm_client=PydanticAIAdapter("openai:gpt-4o-mini"),
)
async with memory:
await memory.add_exchange(
user_id="user-123",
user_message="I just started at Anthropic as a researcher.",
assistant_message="Congrats! What's your focus area?",
)
await memory.process("user-123")
result = await memory.retrieve("What does the user do?", user_id="user-123")
print(result.to_prompt())Predict-Calibrate Extraction · Only extracts what the model failed to predict. Based on Nemori.
Bi-Temporal Validity · Track when facts were true (event time) vs when you learned them (transaction time). Based on Graphiti.
Hybrid Retrieval · Vector similarity + BM25 text search with Reciprocal Rank Fusion.
Episode Segmentation · Groups messages into coherent conversation episodes.
Contradiction Handling · New facts invalidate conflicting old facts. Full audit trail preserved.
SQLite + PostgreSQL · SQLite for local dev, PostgreSQL with pgvector for production. Set db_url to choose between them.
Multiple Embedding Providers · OpenAI, Voyage, Cohere, or local via fastembed. Dimensions detected from the adapter.
memv's bi-temporal model lets you query knowledge as of a specific point in time:
from datetime import datetime
# What did we know about user's job in January 2024?
result = await memory.retrieve(
"Where does user work?",
user_id="user-123",
at_time=datetime(2024, 1, 1),
)
# Show full history including superseded facts
result = await memory.retrieve(
"Where does user work?",
user_id="user-123",
include_expired=True,
)Messages → Episodes → Knowledge → Vector Index + Text Index
(sqlite-vec / pgvector) (FTS5 / tsvector)
- Messages buffered until threshold
- Segmented into coherent episodes
- Predict what episode should contain (given existing KB)
- Compare prediction vs actual — extract the gaps
- Store with embeddings + temporal bounds
class MyAgent:
def __init__(self, memory: Memory):
self.memory = memory
async def run(self, user_input: str, user_id: str) -> str:
context = await self.memory.retrieve(user_input, user_id=user_id)
response = await self.llm.generate(
f"{context.to_prompt()}\n\nUser: {user_input}"
)
await self.memory.add_exchange(user_id, user_input, response)
return responseSee Examples for PydanticAI, LangGraph, LlamaIndex, CrewAI, and AutoGen integrations.
- Getting Started — First example and agent pattern
- Core Concepts — Predict-calibrate, episodes, bi-temporal, retrieval
- Backends — SQLite and PostgreSQL setup
- API Reference — All public classes and methods
git clone https://github.com/vstorm-co/memv.git
cd memv
make install
make allSee CONTRIBUTING.md for details.
MIT — see LICENSE
Built by vstorm
