AsyncMemory gives you a non-blocking interface to Mem0’s storage layer so Python applications can add, search, and manage memories directly from async code. Use it when you embed Mem0 inside FastAPI services, background workers, or any workflow that relies on asyncio.
You’ll use this when…
- Your agent already runs in an async framework and you need memory calls to await cleanly.
- You want to embed Mem0’s storage locally without sending requests through the synchronous client.
- You plan to mix memory operations with other async APIs (OpenAI, HTTP calls, databases).
AsyncMemory expects a running event loop. Always call it inside async def functions or through helpers like asyncio.run() to avoid runtime errors.Working in TypeScript? The Node SDK still uses synchronous calls—use
Memory there and rely on Python’s AsyncMemory when you need awaited operations.Feature anatomy
- Direct storage access:
AsyncMemorytalks to the same backends as the synchronous client but keeps everything in-process for lower latency. - Method parity: Each memory operation (
add,search,get_all,delete, etc.) mirrors the synchronous API, letting you reuse payload shapes. - Concurrent execution: Non-blocking I/O lets you schedule multiple memory tasks with
asyncio.gather. - Scoped organization: Continue using
user_id,agent_id, andrun_idto separate memories across sessions and agents.
Async method parity
Async method parity
| Operation | Async signature | Notes |
|---|---|---|
| Create memories | await memory.add(...) | Same arguments as synchronous Memory.add. |
| Search memories | await memory.search(...) | Returns dict with results, identical shape. |
| List memories | await memory.get_all(...) | Filter by user_id, agent_id, run_id. |
| Retrieve memory | await memory.get(memory_id=...) | Raises ValueError if ID is invalid. |
| Update memory | await memory.update(memory_id=..., data=...) | Accepts partial updates. |
| Delete memory | await memory.delete(memory_id=...) | Returns confirmation payload. |
| Delete in bulk | await memory.delete_all(...) | Requires at least one scope filter. |
| History | await memory.history(memory_id=...) | Fetches change log for auditing. |
Configure it
Initialize the client
Run
await memory.search(...) once right after initialization. If it returns memories without errors, your configuration works.Keep configuration objects close to the async client so you can reuse them across workers without recreating vector store connections.
Manage lifecycle and concurrency
Wrap the client in an async context manager when you need a clean shutdown (for example, inside FastAPI startup/shutdown hooks).
When concurrency works correctly, successful tasks return memory IDs while failures surface as exceptions in the
results list.Add resilience with retries
Always cap retries—runaway loops can keep the event loop busy and block other tasks.
See it in action
Core operations
Confirm each call returns the same response fields as the synchronous client (IDs,
results, or confirmation objects). Missing keys usually mean the coroutine wasn’t awaited.delete_all requires at least one of user_id, agent_id, or run_id. Provide all three to narrow deletion to a single session.Scoped organization
Use
history when you need audit trails for compliance or debugging update logic.Blend with other async APIs
When everything is wired correctly, the OpenAI response should incorporate recent memories and the follow-up
add call should persist the new assistant turn.Handle errors gracefully
Catch and log
ValueError exceptions from invalid inputs—async stack traces can otherwise disappear inside background tasks.Serve through FastAPI
Create one
AsyncMemory instance per process when using FastAPI—startup hooks are a good place to configure and reuse it.Instrument logging
Logged durations give you the baseline needed to spot regressions once AsyncMemory is in production.
Verify the feature is working
- Run a quick add/search cycle and confirm the returned memory content matches your input.
- Inspect application logs to ensure async tasks complete without blocking the event loop.
- In FastAPI or other frameworks, hit health endpoints to verify the shared client handles concurrent requests.
- Monitor retry counters—unexpected spikes indicate configuration or connectivity issues.
Best practices
- Keep operations awaited: Forgetting
awaitis the fastest way to miss writes—lint for it or add helper wrappers. - Scope deletions carefully: Always supply
user_id,agent_id, orrun_idto avoid purging too much data. - Batch writes thoughtfully: Use
asyncio.gatherfor throughput but cap concurrency based on backend capacity. - Log errors with context: Capture user and agent scopes to triage failures quickly.
- Reuse clients: Instantiate
AsyncMemoryonce per worker to avoid repeated backend handshakes.
Troubleshooting
| Issue | Possible causes | Fix |
|---|---|---|
| Initialization fails | Missing dependencies, invalid config | Validate MemoryConfig settings and environment variables. |
| Slow operations | Large datasets, network latency | Cache heavy queries and tune vector store parameters. |
| Memory not found | Invalid ID or deleted record | Check ID source and handle soft-deleted states. |
| Connection timeouts | Network issues, overloaded backend | Apply retries/backoff and inspect infrastructure health. |
| Out-of-memory errors | Oversized batches | Reduce concurrency or chunk operations into smaller sets. |