Agno Memory
A memory-only db for Agno’s MemoryManager: memories extracted by agno’s native pipeline persist to MemorySync and are injected into context on every run — with real semantic recall, an async-native twin, and deletes that cannot nuke an account. Install agno-memorysync from PyPI.
What installs
pip install agno-memorysync
Agno’s BaseDb covers sessions, evals, knowledge, metrics and traces too. MemorySyncDb implements every memory method for real and makes every other surface raise MemorySyncMemoryOnlyError with the fix in the message — a backend that silently pretended to store sessions would lose them. add_memories_to_context auto-enables when a memory manager is set.
| Mem0 (`Mem0Tools` + cookbook) | Zep (`ZepTools` + cookbook) | Supermemory | MemorySync | |
|---|---|---|---|---|
| Integration depth | ✗ LLM tools — the model must *decide* to recall | ✗ LLM tools + a hardcoded time.sleep(10) for indexing | — nothing at all | ✓ native MemoryManager backend — automatic extraction + injection |
| Async agents | ✗ sync client blocks the event loop | ✗ sync | — | ✓ bounded-budget sync db + a true AsyncBaseDb twin |
| Missing user id | ✗ returns error strings as tool output | — | — | ✓ deterministic default namespace, never cross-user |
| Retries / re-runs | ✗ cookbook: *"comment out this line after running once"* | — | — | ✓ revision-hash idempotency seeds — retries converge |
| Memory freshness | ✗ cookbook injects a static snapshot fetched at construction | ✗ same static-dependencies pattern | — | ✓ fresh recall every run |
| Agent scoping | ✗ search/get_all ignore agent_id | — | — | ✓ agent_id/team_id stored and filterable |
| Semantic search | — | — | — | ✓ real vector search via search_content (agno itself has only last_n / first_n / an extra LLM call) |
| Whole-store wipe | — | — | — | ✓ clear_memories() refuses; per-user wipe is explicit |
Real semantic recall
Agno’s search_user_memories offers last_n, first_n, and agentic — the last is an extra LLM round-trip that reads all memories and picks ids. MemorySync serves search_content from its vector index: no LLM call, ranked by similarity.
db = MemorySyncDb()memories = db.get_user_memories(user_id="customer-42",search_content="what does the user like to eat?", # real vector searchlimit=5,)
Deletes that cannot nuke an account
| Call | What happens |
|---|---|
delete_user_memory(id, user_id=...) | Deletes that row; already-gone id is an idempotent no-op; a FAILED delete raises |
delete_user_memories([ids], user_id=...) | Bulk variant, same guarantees |
clear_memories() | Always raises — a nullary everything-wipe is how accounts get destroyed |
forget_user_memories(user_id) | The explicit, scoped, loud per-user wipe |
Reads fail open under a hard 1.2s budget — a slow or down memory service degrades to no memories, never a stalled turn. Writes fail open by default with loud logs and an honest None return, so post-run extraction can never turn a successful agent run into a failure.
Configuration
| Parameter | Default | Meaning |
|---|---|---|
api_key | MEMORYSYNC_API_KEY env var | API key |
default_user_id | default | Namespace when agno passes user_id=None |
recall_timeout | 1.2 | Hard read budget in seconds |
fail_open_writes | True | Extraction failures log instead of raise |
source | agno | Source label on stored rows |
Supported versions
| Surface | Requires | Verified on |
|---|---|---|
agno-memorysync 1.0.0 | agno 2.8+ (Python 3.10+) | 37 CI checks against the latest agno: the REAL MemoryManager add/replace/delete flows and a REAL Agent run (stub model, local session db) asserting MemorySync memories reach the model context — plus the memory-only scope contract, semantic search_content, revision-seed idempotency, the guarded nullary clear, the AsyncBaseDb twin, the 1.2s budget, and both monthly-quota server modes |