
Mem0
- 1.8k installs
- 62.5k repo stars
- Updated August 5, 2026
- mem0ai/mem0
Mem0 Platform SDK for adding persistent memory to AI applications. TRIGGER when: user mentions "mem0", "MemoryClient", "memory layer", "remember user preferences", "persistent context", "personalizati
About
The mem0 skill Mem0 Platform SDK for adding persistent memory to AI applications. TRIGGER when: user mentions "mem0", "MemoryClient", "memory layer", "remember user preferences", "persistent context", "personalization", or needs to add long-term memory to chatbots, agents, or AI apps. Covers Python SDK (mem0ai), TypeScript SDK (mem0ai), and framework integrations (LangChain, CrewAI, OpenAI Agents SDK, Pipecat, LlamaIndex, AutoGen, LangGraph). Also covers the open-source self-hosted Memory class. This is the DEFAULT mem0 skill for ambiguous queries. DO NOT TRIGGER when: user asks about CLI commands, terminal usage, or shell scripts (use mem0-cli), or Vercel AI SDK / @mem0/vercel-ai-provider / createMem0 (use mem0-vercel-ai-sdk). Documentation covers workflows, commands, and guardrails agents should follow when users invoke this capability. Key documented areas include **Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_id` matches exactly (case-sensitive) and use `filters={"user_; **AND filter with user_id + agent_id returns empty:** Entities are stored separately. Use `OR` instead, or query separately.; **Duplicate.
- **Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_i
- **AND filter with user_id + agent_id returns empty:** Entities are stored separately. Use `OR` instead, or query separat
- **Duplicate memories:** Don't mix `infer=True` (default) and `infer=False` for the same data. Stick to one mode.
- **Wrong import:** Always use `from mem0 import MemoryClient` (or `AsyncMemoryClient` for async). Do not use `from mem0 i
- **v3 defaults:** `top_k=20`, `threshold=0.1`, `rerank=False`. Adjust as needed for your use case.
Mem0 by the numbers
- 1,765 all-time installs (skills.sh)
- +96 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #724 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
mem0 capabilities & compatibility
- Capabilities
- **search returns empty:** memories process async · **and filter with user_id + agent_id returns emp · **duplicate memories:** don't mix `infer=true` ( · **wrong import:** always use `from mem0 import m · **v3 defaults:** `top_k=20`, `threshold=0.1`, `r
- Use cases
- planning
What mem0 says it does
**Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_i
npx skills add https://github.com/mem0ai/mem0 --skill mem0Add your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.8k |
|---|---|
| repo stars | ★ 62.5k |
| Security audit | 2 / 3 scanners passed |
| Last updated | August 5, 2026 |
| Repository | mem0ai/mem0 ↗ |
How do I handle mem0 tasks with agent guidance?
Mem0 Platform SDK for adding persistent memory to AI applications. TRIGGER when: user mentions "mem0", "MemoryClient", "memory layer", "remember user preferences", "persistent context", "personalizati
Who is it for?
Teams needing documented mem0 workflows.
Skip if: Generic advice without reading bundled docs.
When should I use this skill?
Mem0 Platform SDK for adding persistent memory to AI applications. TRIGGER when: user mentions "mem0", "MemoryClient", "memory layer", "remember user preferences", "persistent context", "personalizati
What you get
Structured workflow from mem0 documentation applied to the user request.
- memory integration code
- persistent context store
- cross-session recall configuration
By the numbers
- Documents Python and TypeScript SDK API differences across both Platform and OSS modes
Files
Mem0 Platform Integration
Skill Graph: This skill is part of the Mem0 skill graph:
- mem0 (this skill) -- Platform Client SDK + OSS (Python + TypeScript)
- [mem0-cli](../mem0-cli/SKILL.md) (GitHub) -- Command-line interface
- [mem0-vercel-ai-sdk](../mem0-vercel-ai-sdk/SKILL.md) (GitHub) -- Vercel AI SDK provider
Mem0 is a managed memory layer for AI applications. It stores, retrieves, and manages user memories via API — no infrastructure to deploy. For self-hosted usage, see the OSS section in the client references below.
Step 1: Install and authenticate
Python:
pip install mem0ai
export MEM0_API_KEY="m0-your-api-key"TypeScript/JavaScript:
npm install mem0ai
export MEM0_API_KEY="m0-your-api-key"Get an API key at: https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=skill-mem0
Don't have a `MEM0_API_KEY`? Runmem0 init --agent --agent-caller <your-name> --json(afterpip install mem0-cliornpm install -g @mem0/cli), substituting your agent identity (e.g.claude-code,cursor). If you forgot to pass--agent-caller, runmem0 identify <your-name>after init. The human can claim later withmem0 init --email <your-email>.
Step 2: Initialize the client
Python:
from mem0 import MemoryClient
client = MemoryClient(api_key="m0-xxx")TypeScript:
import MemoryClient from 'mem0ai';
const client = new MemoryClient({ apiKey: 'm0-xxx' });For async Python, use AsyncMemoryClient.
Step 3: Core operations
Every Mem0 integration follows the same pattern: retrieve → generate → store.
Add memories
messages = [
{"role": "user", "content": "I'm a vegetarian and allergic to nuts."},
{"role": "assistant", "content": "Got it! I'll remember that."}
]
client.add(messages, user_id="alice")Search memories
results = client.search("dietary preferences", filters={"user_id": "alice"})
for mem in results.get("results", []):
print(mem["memory"])Get all memories
all_memories = client.get_all(filters={"user_id": "alice"})Update a memory
client.update("memory-uuid", text="Updated: vegetarian, nut allergy, prefers organic")Delete a memory
client.delete("memory-uuid")
client.delete_all(user_id="alice") # delete all for a userCommon integration pattern
from mem0 import MemoryClient
from openai import OpenAI
mem0 = MemoryClient()
openai = OpenAI()
def chat(user_input: str, user_id: str) -> str:
# 1. Retrieve relevant memories
memories = mem0.search(user_input, filters={"user_id": user_id})
context = "\n".join([m["memory"] for m in memories.get("results", [])])
# 2. Generate response with memory context
response = openai.chat.completions.create(
model="gpt-5-mini",
messages=[
{"role": "system", "content": f"User context:\n{context}"},
{"role": "user", "content": user_input},
]
)
reply = response.choices[0].message.content
# 3. Store interaction for future context
mem0.add(
[{"role": "user", "content": user_input}, {"role": "assistant", "content": reply}],
user_id=user_id
)
return replyCommon edge cases
- Search returns empty: Memories process asynchronously. Wait 2-3s after
add()before searching. Also verifyuser_idmatches exactly (case-sensitive) and usefilters={"user_id": "..."}syntax. - AND filter with user_id + agent_id returns empty: Entities are stored separately. Use
ORinstead, or query separately. - Duplicate memories: Don't mix
infer=True(default) andinfer=Falsefor the same data. Stick to one mode. - Wrong import: Always use
from mem0 import MemoryClient(orAsyncMemoryClientfor async). Do not usefrom mem0 import Memory. - v3 defaults:
top_k=20,threshold=0.1,rerank=False. Adjust as needed for your use case.
v2 Compatibility
If you're using SDK v2.x, note these differences:
- Entity IDs: Pass
user_idas top-level kwarg tosearch()instead of insidefilters - Defaults:
top_k=100, no threshold,rerank=True - Graph memory: Available via
enable_graph=True
See the migration guide for details.
Live documentation search
For the latest docs beyond what's in the references, use the doc search tool:
python ${CLAUDE_SKILL_DIR}/scripts/mem0_doc_search.py --query "topic"
python ${CLAUDE_SKILL_DIR}/scripts/mem0_doc_search.py --page "/platform/features/graph-memory"
python ${CLAUDE_SKILL_DIR}/scripts/mem0_doc_search.py --indexNo API key needed — searches docs.mem0.ai directly.
Client SDK References
Language-specific deep references (Platform + OSS):
| Language | File |
|---|---|
| Python (MemoryClient + AsyncMemoryClient + Memory OSS) | client/python.md |
| TypeScript/Node.js (MemoryClient + Memory OSS) | client/node.md |
| Python vs TypeScript differences | client/differences.md |
Platform References
Load these on demand for deeper detail:
| Topic | File |
|---|---|
| Quickstart (Python, TS, cURL) | references/quickstart.md |
| SDK guide (all methods, both languages) | references/sdk-guide.md |
| API reference (endpoints, filters, object schema) | references/api-reference.md |
| Architecture (pipeline, lifecycle, scoping, performance) | references/architecture.md |
| Platform features (retrieval, graph, categories, MCP, etc.) | references/features.md |
| Framework integrations (LangChain, CrewAI, OpenAI Agents, etc.) | references/integration-patterns.md |
| Use cases & examples (real-world patterns with code) | references/use-cases.md |
Related Mem0 Skills
| Skill | When to use | Link |
|---|---|---|
| mem0-cli | Terminal commands, scripting, CI/CD, agent tool loops | local / GitHub |
| mem0-vercel-ai-sdk | Vercel AI SDK provider with automatic memory | local / GitHub |
Python vs TypeScript SDK Differences
Quick-reference cheatsheet for developers working across both Mem0 SDKs.
Constructor
| Aspect | Python | TypeScript |
|---|---|---|
| Import (Platform) | from mem0 import MemoryClient | import MemoryClient from 'mem0ai' |
| Import (OSS) | from mem0 import Memory | import { Memory } from 'mem0ai/oss' |
| Constructor | MemoryClient(api_key="m0-xxx") | new MemoryClient({ apiKey: 'm0-xxx' }) |
| Required param | api_key (positional or kwarg) | apiKey (in options object) |
Both read from MEM0_API_KEY env var if no key provided.
Method Naming
| Operation | Python | TypeScript |
|---|---|---|
| Add | add() | add() |
| Search | search() | search() |
| Get | get() | get() |
| Get all | get_all() | getAll() |
| Update | update() | update() |
| Delete | delete() | delete() |
| Delete all | delete_all() | deleteAll() |
| History | history() | history() |
| Batch update | batch_update() | batchUpdate() |
| Batch delete | batch_delete() | batchDelete() |
| List users | users() | users() |
| Delete users | delete_users() | deleteUsers() |
| Get project | project.get() | getProject() |
| Update project | project.update() | updateProject() |
| Create webhook | create_webhook() | createWebhook() |
| Get webhooks | get_webhooks() | getWebhooks() |
| Update webhook | update_webhook() | updateWebhook() |
| Delete webhook | delete_webhook() | deleteWebhook() |
| Create export | create_memory_export() | createMemoryExport() |
| Get export | get_memory_export() | getMemoryExport() |
| Feedback | feedback() | feedback() |
Rule: Python uses snake_case, TypeScript uses camelCase for method names.
Parameter Passing
# Python: kwargs
client.add(messages, user_id="alice", metadata={"source": "chat"})
client.search("query", filters={"user_id": "alice"}, top_k=5, rerank=True)// TypeScript: options object with camelCase for top-level params, snake_case for filter keys
await client.add(messages, { userId: 'alice', metadata: { source: 'chat' } });
await client.search('query', { filters: { user_id: 'alice' }, topK: 5, rerank: true });v3: Python uses snake_case everywhere. TypeScript uses camelCase for top-level params (userId, topK) but snake_case for filter keys (user_id, agent_id).
Architectural Differences
| Aspect | Python | TypeScript |
|---|---|---|
| HTTP library | httpx | axios |
| Default timeout | 300s | 60s |
| Sync support | Yes (MemoryClient) | No (all async) |
| Async support | Yes (AsyncMemoryClient) | All methods are async |
| Project management | client.project.* (separate class) | client.getProject() / client.updateProject() |
| Context manager | async with AsyncMemoryClient() | Not supported |
Platform Features: Python-only
These methods exist in Python but not TypeScript:
| Method | Description |
|---|---|
get_summary(filters) | Get summary of memories |
reset() | Delete ALL data (users + memories) |
project.create(name) | Create a new project |
project.delete() | Delete current project |
project.get_members() | List project members |
project.add_member(email, role) | Add member to project |
project.update_member(email, role) | Change member role |
project.remove_member(email) | Remove member |
Platform Features: TypeScript-only
| Method | Description |
|---|---|
deleteUser(data) | Convenience method for single entity deletion |
ping() | Health check endpoint |
OSS Config Naming
| Python config key | TypeScript config key |
|---|---|
vector_store | vectorStore |
history_db_path | historyDbPath |
custom_instructions | customInstructions |
OSS Scope Parameter Naming
| Python | TypeScript |
|---|---|
user_id="alice" | userId: 'alice' |
agent_id="bot" | agentId: 'bot' |
run_id="session" | runId: 'session' |
Entity ID Passing (v3)
| Method | Python | TypeScript |
|---|---|---|
| add() | Top-level: user_id="alice" | Top-level: { userId: 'alice' } |
| search() | In filters: filters={"user_id": "alice"} | In filters: { filters: { user_id: 'alice' } } |
| get_all() | In filters: filters={"user_id": "alice"} | In filters: { filters: { user_id: 'alice' } } |
Common Gotcha
When searching/filtering, both Python and TypeScript use snake_case for filter keys. TypeScript only uses camelCase for top-level method parameters:
# Python - snake_case in filters
results = client.search("query", filters={"user_id": "alice"})// TypeScript - snake_case in filters, camelCase for top-level params
const results = await client.search('query', { filters: { user_id: 'alice' }, topK: 20 });Mem0 Node.js / TypeScript SDK Reference
Complete reference for the mem0ai npm package. Covers both the Platform client (managed API) and the Open Source self-hosted variant.
---
Platform Client
Installation
npm install mem0ai
export MEM0_API_KEY="m0-your-api-key"MemoryClient
import MemoryClient from 'mem0ai';
const client = new MemoryClient({ apiKey: 'm0-xxx' });Constructor: new MemoryClient({ apiKey }). If apiKey is not provided, reads from MEM0_API_KEY environment variable.
- HTTP library:
axios - Timeout: 60 seconds
- Base URL:
https://api.mem0.ai - All methods are async (return
Promise)
---
Memory Methods
add(messages, options?)
Store new memories from messages.
const messages = [
{ role: 'user', content: "I'm a vegetarian and allergic to nuts." },
{ role: 'assistant', content: "Got it! I'll remember that." },
];
await client.add(messages, { userId: 'alice' });| Parameter | Type | Description |
|---|---|---|
messages | Message[] | Array of {role, content} objects |
options.userId | string | User identifier |
options.agentId | string | Agent identifier |
options.appId | string | Application identifier |
options.runId | string | Session identifier |
options.metadata | object | Custom key-value pairs |
options.infer | boolean | If false, store raw text (default: true) |
Returns: Promise<any> -- list of events
search(query, options?)
Search memories by semantic similarity.
const results = await client.search('dietary preferences', { filters: { user_id: 'alice' }, topK: 20 });
for (const mem of results.results) {
console.log(mem.memory, mem.score);
}| Parameter | Type | Description |
|---|---|---|
query | string | Natural language search query |
options.filters | object | Filter object with entity IDs (user_id, agent_id, etc.) and/or AND/OR/NOT conditions |
options.topK | number | Number of results (default: 20) |
options.rerank | boolean | Enable semantic reranking (default: false) |
options.threshold | number | Minimum similarity (default: 0.1) |
Returns: Promise<SearchResult> -- {results: [{id, memory, score, ...}]}
get(memoryId)
const memory = await client.get('ea925981-...');getAll(options?)
Retrieve all memories. Requires at least one entity identifier in filters.
const memories = await client.getAll({ filters: { user_id: 'alice' } });
// With filters
const filtered = await client.getAll({
filters: { AND: [{ user_id: 'alice' }, { categories: { contains: 'health' } }] },
});| Parameter | Type | Description |
|---|---|---|
options.filters | object | Filter object with entity IDs (user_id, agent_id, etc.) and/or AND/OR/NOT conditions |
options.page | number | Page number |
options.pageSize | number | Results per page |
update(memoryId, data)
await client.update('ea925981-...', { text: 'Updated: vegan since 2024' });
await client.update('ea925981-...', { text: 'Updated', metadata: { verified: true } });| Parameter | Type | Description |
|---|---|---|
memoryId | string | Memory ID |
data.text | string | New content |
data.metadata | object | New metadata |
data.timestamp | string | New timestamp |
delete(memoryId)
await client.delete('ea925981-...');deleteAll(options?)
await client.deleteAll({ userId: 'alice' });history(memoryId)
const history = await client.history('ea925981-...');
// Returns: [{previousValue, newValue, action, timestamps}]---
Batch Methods
batchUpdate(memories)
await client.batchUpdate([
{ memoryId: 'uuid-1', text: 'Updated text' },
{ memoryId: 'uuid-2', text: 'Another update' },
]);batchDelete(memories)
await client.batchDelete(['uuid-1', 'uuid-2', 'uuid-3']);---
User/Entity Management
users()
const users = await client.users();
// Returns: {results: [{type: "user", name: "alice"}, ...]}deleteUser(data) / deleteUsers(data)
await client.deleteUser({ userId: 'alice' }); // Single entity
await client.deleteUsers({ agentId: 'bot-1' }); // Flexible---
Project Management
// Get project config
const config = await client.getProject({ fields: ['customCategories'] });
// Update project settings
await client.updateProject({
customInstructions: 'Extract dietary preferences and health info',
customCategories: [{ health: 'Medical and dietary info' }],
});---
Webhooks
// List
const webhooks = await client.getWebhooks({ projectId: 'proj_123' });
// Create
const webhook = await client.createWebhook({
url: 'https://your-app.com/webhook',
name: 'Memory Logger',
projectId: 'proj_123',
eventTypes: ['memory_add', 'memory_update'],
});
// Update
await client.updateWebhook({
webhookId: 'wh_123',
name: 'Updated Logger',
url: 'https://new-url.com',
});
// Delete
await client.deleteWebhook({ webhookId: 'wh_123' });---
Feedback
await client.feedback({
memoryId: 'mem-123',
feedback: 'POSITIVE',
feedbackReason: 'Accurately captured preference',
});---
Export
const exportReq = await client.createMemoryExport({
schema: JSON.stringify({ type: 'object', properties: { name: { type: 'string' } } }),
filters: { user_id: 'alice' },
});
const result = await client.getMemoryExport({ memoryExportId: exportReq.id });---
TypeScript Types
Key interfaces from mem0.types.ts:
interface Message { role: string; content: string; }
interface Memory { id: string; memory: string; userId: string; categories: string[]; score?: number; /* ... */ }
interface MemoryOptions { userId?: string; agentId?: string; appId?: string; runId?: string; metadata?: object; /* ... */ }
interface SearchOptions { filters?: object; topK?: number; rerank?: boolean; threshold?: number; /* ... */ }
interface MemoryHistory { id: string; memoryId: string; previousValue: string; newValue: string; action: string; /* ... */ }
interface FeedbackPayload { memoryId: string; feedback: string; feedbackReason?: string; }
interface WebhookCreatePayload { url: string; name: string; projectId: string; eventTypes: string[]; }---
Open Source / Self-Hosted
Installation
npm install mem0aiMemory Class
import { Memory } from 'mem0ai/oss';
const m = new Memory(); // Uses default configImport: from 'mem0ai/oss' (NOT the default export -- that is MemoryClient for Platform)
Configuration
const config = {
llm: {
provider: 'openai', // openai, groq, anthropic, google, ollama, lmstudio, mistral, azure
config: {
model: 'gpt-5-mini',
apiKey: 'sk-xxx',
},
},
embedder: {
provider: 'openai', // openai, ollama, lmstudio, google, azure, langchain, anthropic
config: {
model: 'text-embedding-3-small',
apiKey: 'sk-xxx',
},
},
vectorStore: {
provider: 'qdrant', // memory, qdrant, redis, supabase, langchain, azure_ai_search, pgvector
config: {
collectionName: 'my_memories',
host: 'localhost',
port: 6333,
},
},
historyDbPath: 'history.db',
customInstructions: '...',
disableHistory: false,
};
const m = new Memory(config);
// Or from dict with validation:
const m2 = Memory.fromConfig(config);Methods
All methods are async (return Promise):
add(messages, config)
await m.add('I prefer dark mode', { userId: 'alice' });
await m.add([
{ role: 'user', content: 'I like hiking' },
{ role: 'assistant', content: 'Great outdoor activity!' },
], { userId: 'alice' });| Parameter | Type | Description |
|---|---|---|
messages | `string \ | Message[]` |
config.userId | string | User identifier (at least one scope required) |
config.agentId | string | Agent identifier |
config.runId | string | Session identifier |
config.metadata | object | Custom key-value pairs |
config.filters | object | Additional filters |
config.infer | boolean | LLM inference (default: true) |
Returns: Promise<{results: [...], relations?: [...]}>
search(query, config)
const results = await m.search('dietary preferences', { filters: { user_id: 'alice' }, topK: 5 });| Parameter | Type | Description |
|---|---|---|
query | string | Search query |
config.filters | object | Filter object with entity IDs (user_id, agent_id, run_id, etc.) |
config.topK | number | Max results (default: 20) |
get(memoryId) / getAll(config) / update(memoryId, data) / delete(memoryId) / deleteAll(config) / history(memoryId)
Same interface patterns. Note: OSS update takes a string for data, not an object.
await m.update('mem-id', 'new content');reset()
Clear the entire vector store and history.
await m.reset();---
Key Differences: Platform vs OSS
| Aspect | Platform (MemoryClient) | OSS (Memory) |
|---|---|---|
| Import | import MemoryClient from 'mem0ai' | import { Memory } from 'mem0ai/oss' |
| Auth | API key required (MEM0_API_KEY) | No API key -- config-based |
| Execution | API calls to api.mem0.ai | Local execution |
| Infrastructure | Fully managed | Self-managed vector DB, embedder, LLM |
| Param style | Top-level: camelCase (userId, topK), filter keys: snake_case (user_id) | Top-level: camelCase (userId, topK), filter keys: snake_case (user_id) |
| Batch ops | batchUpdate, batchDelete | Not available |
| Webhooks | Full CRUD | Not available |
| Export | createMemoryExport | Not available |
| Feedback | feedback() | Not available |
| Project mgmt | getProject, updateProject | Not available |
| User listing | users(), deleteUser() | Not available |
| History | Platform-managed | SQLite (configurable) |
---
v2 Compatibility
If you're using SDK v2.x:
Naming Changes:
- Top-level params now use camelCase:
topK,rerank(nottop_k) - Filter keys use snake_case:
user_id,agent_id - OSS:
limitrenamed totopK
API Changes:
// v2 - top-level entity IDs, snake_case
await client.search("query", { user_id: "alice", top_k: 20 });
// v3 - filters object with snake_case keys, camelCase top-level params
await client.search("query", { filters: { user_id: "alice" }, topK: 20 });Default Changes:
| Param | v2 | v3 |
|---|---|---|
topK | 100 | 20 |
threshold | none | 0.1 |
rerank | true | false |
Removed:
OutputFormatandAPI_VERSIONenumsorganizationId,projectIdfrom constructorenableGraph,asyncMode,outputFormat,immutable,expirationDate,filterMemories,batchSize,forceAddOnly,includes,excludes,keywordSearch
See the v2 to v3 migration guide for details.
Mem0 Python SDK Reference
Complete reference for the mem0ai Python package. Covers both the Platform client (managed API) and the Open Source self-hosted variant.
---
Platform Client
Installation
pip install mem0ai
export MEM0_API_KEY="m0-your-api-key"MemoryClient (Synchronous)
from mem0 import MemoryClient
client = MemoryClient(api_key="m0-xxx")Constructor: MemoryClient(api_key=None). If api_key is not provided, reads from MEM0_API_KEY environment variable. Raises ValueError if no key found.
- HTTP library:
httpx - Timeout: 300 seconds
- Base URL:
https://api.mem0.ai
AsyncMemoryClient (Asynchronous)
from mem0 import AsyncMemoryClient
client = AsyncMemoryClient(api_key="m0-xxx")
# Or use as context manager
async with AsyncMemoryClient(api_key="m0-xxx") as client:
results = await client.search("query", filters={"user_id": "alice"})Same methods as MemoryClient, all async/await. Supports async context manager.
---
Memory Methods
add(messages, **kwargs)
Store new memories from messages.
messages = [
{"role": "user", "content": "I'm a vegetarian and allergic to nuts."},
{"role": "assistant", "content": "Got it! I'll remember that."}
]
client.add(messages, user_id="alice")| Parameter | Type | Default | Description |
|---|---|---|---|
messages | str \ | dict \ | list[dict] |
user_id | str | None | User identifier |
agent_id | str | None | Agent identifier |
app_id | str | None | Application identifier |
run_id | str | None | Session/run identifier |
metadata | dict | None | Custom key-value pairs |
infer | bool | True | If False, store raw text without LLM inference |
custom_categories | list | None | Override project categories |
custom_instructions | str | None | Override extraction instructions |
timestamp | int \ | float \ | str |
Returns: dict -- list of events: [{"id": "...", "event": "ADD", "data": {"memory": "..."}}]
search(query, **kwargs)
Search memories by semantic similarity.
results = client.search("dietary preferences", filters={"user_id": "alice"})
for mem in results.get("results", []):
print(mem["memory"], mem["score"])| Parameter | Type | Default | Description |
|---|---|---|---|
query | str | required | Natural language search query |
filters | dict | None | Filter object with entity IDs and/or AND/OR/NOT conditions (e.g., {"user_id": "alice"}) |
top_k | int | 10 | Number of results |
rerank | bool | False | Enable deep semantic reranking (+150-200ms) |
threshold | float | 0.1 | Minimum similarity score |
fields | list | None | Specific fields to return |
categories | list | None | Filter by category |
Returns: dict -- {"results": [{id, memory, user_id, categories, score, created_at, ...}]}
get(memory_id)
Retrieve a single memory by ID.
memory = client.get(memory_id="ea925981-...")Returns: dict -- full memory object
get_all(**kwargs)
Retrieve all memories with optional filtering. Requires at least one entity identifier.
memories = client.get_all(filters={"user_id": "alice"})
# With compound filters
memories = client.get_all(filters={"AND": [{"user_id": "alice"}, {"categories": {"contains": "health"}}]})| Parameter | Type | Default | Description |
|---|---|---|---|
filters | dict | None | Filter object with entity IDs and/or AND/OR/NOT conditions |
top_k | int | None | Limit results |
page | int | None | Page number |
page_size | int | None | Results per page |
Returns: dict -- {"results": [...]}
update(memory_id, text=None, metadata=None, timestamp=None)
Update a memory's content, metadata, or timestamp. At least one parameter required.
client.update("ea925981-...", text="Updated: vegan since 2024")
client.update("ea925981-...", metadata={"verified": True})Returns: dict -- updated memory
delete(memory_id)
Permanently delete a single memory.
client.delete("ea925981-...")delete_all(**kwargs)
Delete all memories matching filters. Irreversible.
client.delete_all(user_id="alice")history(memory_id)
Get the change history of a memory.
history = client.history("ea925981-...")
# Returns: [{previous_value, new_value, action, timestamps}]---
Batch Methods
batch_update(memories)
Update up to 1000 memories in a single request.
client.batch_update([
{"memory_id": "uuid-1", "text": "Updated text"},
{"memory_id": "uuid-2", "text": "Another update", "metadata": {"verified": True}},
])batch_delete(memories)
Delete up to 1000 memories in a single request.
client.batch_delete([
{"memory_id": "uuid-1"},
{"memory_id": "uuid-2"},
])---
User/Entity Management
users()
List all users, agents, and sessions that have memories.
users = client.users()
# Returns: {"results": [{"type": "user", "name": "alice"}, ...]}delete_users(user_id=None, agent_id=None, app_id=None, run_id=None)
Delete a specific entity and all its memories.
client.delete_users(user_id="alice")reset()
Delete ALL users, agents, sessions, and memories. Complete data reset.
client.reset()---
Export & Summary
create_memory_export(schema, **kwargs)
Create a structured export of memories.
import json
schema = json.dumps({
"type": "object",
"properties": {
"name": {"type": "string"},
"preferences": {"type": "array", "items": {"type": "string"}},
}
})
export = client.create_memory_export(schema=schema, user_id="alice")get_memory_export(**kwargs)
Retrieve a previously created export.
result = client.get_memory_export(memory_export_id=export["id"])get_summary(filters=None)
Get a summary of memories.
summary = client.get_summary(filters={"user_id": "alice"})---
Feedback
feedback(memory_id, feedback=None, feedback_reason=None)
Provide quality feedback on a memory.
client.feedback(
memory_id="mem-123",
feedback="POSITIVE", # POSITIVE | NEGATIVE | VERY_NEGATIVE | None (clear)
feedback_reason="Accurately captured preference"
)---
Webhooks
# List
webhooks = client.get_webhooks(project_id="proj_123")
# Create
webhook = client.create_webhook(
url="https://your-app.com/webhook",
name="Memory Logger",
project_id="proj_123",
event_types=["memory_add", "memory_update"]
)
# Update
client.update_webhook(webhook_id=123, name="Updated", url="https://new-url.com")
# Delete
client.delete_webhook(webhook_id=123)---
Project Management
Access via client.project.*:
# Get project config
config = client.project.get(fields=["custom_categories", "custom_instructions"])
# Update project settings
client.project.update(
custom_instructions="Extract dietary preferences and health info",
custom_categories=[{"health": "Medical and dietary info"}],
multilingual=True,
)
# Create/delete project
client.project.create(name="My Project", description="...")
client.project.delete()
# Member management
members = client.project.get_members()
client.project.add_member(email="user@example.com", role="READER") # READER or OWNER
client.project.update_member(email="user@example.com", role="OWNER")
client.project.remove_member(email="user@example.com")---
Open Source / Self-Hosted
Installation
pip install mem0aiMemory Class
from mem0 import Memory
m = Memory() # Uses default config (OpenAI embedder + in-memory vector store)Import: from mem0 import Memory (NOT MemoryClient -- that is the Platform client)
Configuration
config = {
"llm": {
"provider": "openai", # openai, groq, azure, ollama, lmstudio, google, anthropic, mistral
"config": {
"model": "gpt-5-mini",
"api_key": "sk-xxx",
}
},
"embedder": {
"provider": "openai", # openai, ollama, azure, lmstudio, google, huggingface
"config": {
"model": "text-embedding-3-small",
"api_key": "sk-xxx",
}
},
"vector_store": {
"provider": "qdrant", # faiss, qdrant, pgvector, redis, supabase, azure_ai_search, memory
"config": {
"collection_name": "my_memories",
"host": "localhost",
"port": 6333,
}
},
"history_db_path": "history.db", # SQLite path for change history
"custom_instructions": "...", # Custom LLM prompt for extraction
}
m = Memory.from_config(config)Context Manager
with Memory(config) as m:
m.add("I prefer dark mode", user_id="alice")
results = m.search("preferences", filters={"user_id": "alice"})
# SQLite connections released automaticallyMethods
All methods mirror the Platform client but run locally:
add(messages, *, user_id, agent_id, run_id, metadata, infer=True)
m.add("I'm a vegetarian", user_id="alice")
m.add([
{"role": "user", "content": "I like hiking"},
{"role": "assistant", "content": "Great outdoor activity!"}
], user_id="alice")At least one of user_id, agent_id, run_id required.
Returns: {"results": [...], "relations": [...]}
search(query, *, filters=None, top_k=20, threshold=0.1, rerank=False)
results = m.search("dietary preferences", filters={"user_id": "alice"}, top_k=5)Entity IDs (user_id, agent_id, run_id) must be passed inside the filters dict.
Supports filter operators: eq, ne, in, nin, gt, gte, lt, lte, contains, not_contains.
get(memory_id) / get_all(kwargs) / update(memory_id, data, metadata=None) / delete(memory_id) / delete_all(kwargs) / history(memory_id)
Same interface as Platform client.
reset()
Clear the entire vector store collection and history database. Recreates the vector store.
m.reset()close()
Release SQLite connections. Called automatically when using context manager.
AsyncMemory
from mem0 import AsyncMemory
m = AsyncMemory(config)
await m.add("text", user_id="alice")
results = await m.search("query", filters={"user_id": "alice"})---
Key Differences: Platform vs OSS
| Aspect | Platform (MemoryClient) | OSS (Memory) |
|---|---|---|
| Import | from mem0 import MemoryClient | from mem0 import Memory |
| Auth | API key required (MEM0_API_KEY) | No API key -- config-based |
| Execution | API calls to api.mem0.ai | Local execution |
| Infrastructure | Fully managed | Self-managed vector DB, embedder, LLM |
| Entity filtering | filters={"user_id": "..."} | filters={"user_id": "..."} |
| Batch ops | batch_update, batch_delete | Not available |
| Webhooks | Full CRUD | Not available |
| Export | create_memory_export, get_memory_export | Not available |
| Feedback | feedback() | Not available |
| Project mgmt | client.project.* | Not available |
| User listing | users(), delete_users() | Not available |
| Custom prompts | Via project settings | Direct config (custom_instructions) |
| History | Platform-managed | SQLite (configurable) |
| Async | AsyncMemoryClient | AsyncMemory |
---
v2 Compatibility
If you're using SDK v2.x or the v2 API:
API Changes:
- Entity IDs in search/get_all: Pass
user_id,agent_idas top-level kwargs instead of insidefilters
# v2
results = client.search("query", user_id="alice")
# v3
results = client.search("query", filters={"user_id": "alice"})- add() returns: v2 returns ADD, UPDATE, DELETE events; v3 returns ADD only
Default Changes:
| Param | v2 | v3 |
|---|---|---|
top_k | 100 | 20 |
threshold | None | 0.1 |
rerank | True | False |
Removed Parameters:
- Constructor:
org_id,project_id - add():
async_mode,output_format,enable_graph,immutable,expiration_date,filter_memories,batch_size,force_add_only,includes,excludes,keyword_search - search()/get_all():
enable_graph - Config:
enable_graph,graph_store,custom_fact_extraction_prompt(renamed tocustom_instructions)
See the v2 to v3 migration guide for full details.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but not
limited to compiled object code, generated documentation, and
conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work.
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2024 Mem0.ai
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Mem0 Skill for Claude
Add persistent memory to any AI application in minutes using Mem0 Platform or the open-source self-hosted SDK.
Part of the Mem0 Skill Graph: See also mem0-cli (terminal) and mem0-vercel-ai-sdk (Vercel AI SDK).
What This Skill Does
When installed, Claude can:
- Set up Mem0 in your Python or TypeScript project (Platform or OSS)
- Integrate memory into your existing AI app (LangChain, CrewAI, OpenAI Agents, LangGraph, LlamaIndex, etc.)
- Generate working code using real API references and tested patterns
- Search live docs on demand for the latest Mem0 documentation
Installation
CLI (Claude Code, OpenCode, OpenClaw, or any tool that supports skills)
npx skills add https://github.com/mem0ai/mem0 --skill mem0Claude.ai
1. Download this skills/mem0 folder as a ZIP 2. Go to Settings > Capabilities > Skills 3. Click Upload skill and select the ZIP
Claude API (Skills API)
curl -X POST https://api.anthropic.com/v1/skills \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "mem0", "source": "https://github.com/mem0ai/mem0/tree/main/skills/mem0"}'Prerequisites
- A Mem0 Platform API key (Get one here)
- Python 3.10+ or Node.js 18+
- Set the environment variable:
export MEM0_API_KEY="m0-your-api-key"Quick Start
After installing, just ask Claude:
- "Set up mem0 in my project"
- "Add memory to my chatbot"
- "Help me search user memories with filters"
- "Integrate mem0 with my LangChain app"
- "Add graph memory to track entity relationships"
What's Inside
skills/mem0/
├── SKILL.md # Skill definition and instructions
├── README.md # This file
├── LICENSE # Apache-2.0
├── client/ # Language-specific SDK references (Platform + OSS)
│ ├── python.md # Python SDK (MemoryClient + Memory OSS)
│ ├── node.md # TypeScript SDK (MemoryClient + Memory OSS)
│ └── differences.md # Python vs TypeScript comparison
├── scripts/
│ └── mem0_doc_search.py # Search live Mem0 docs on demand
└── references/ # Documentation (loaded on demand)
├── quickstart.md # Full quickstart (Python, TS, cURL)
├── sdk-guide.md # All SDK methods (Python + TypeScript)
├── api-reference.md # REST endpoints, filters, memory object
├── architecture.md # Processing pipeline, lifecycle, scoping, performance
├── features.md # Retrieval, graph, categories, MCP, webhooks, multimodal
├── integration-patterns.md # LangChain, CrewAI, OpenAI Agents, LangGraph, LlamaIndex, etc.
└── use-cases.md # 7 real-world patterns with Python + TypeScript codeLinks
License
Apache-2.0
Mem0 Platform API Reference
REST API endpoints for the Mem0 Platform. Base URL: https://api.mem0.ai
All endpoints require: Authorization: Token <MEM0_API_KEY>
Endpoints
| Operation | Method | URL |
|---|---|---|
| Add Memories | POST | /v3/memories/add/ |
| Search Memories | POST | /v3/memories/search/ |
| Get All Memories | POST | /v3/memories/ |
| Get Single Memory | GET | /v1/memories/{memory_id}/ |
| Update Memory | PUT | /v1/memories/{memory_id}/ |
| Delete Memory | DELETE | /v1/memories/{memory_id}/ |
Note: v1/v2 endpoints still work (backward compatible).
Memory Object Structure
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique memory identifier |
memory | string | Text content of the memory |
user_id | string | Associated user |
agent_id | string (nullable) | Agent identifier |
app_id | string (nullable) | Application identifier |
run_id | string (nullable) | Run/session identifier |
metadata | object | Custom key-value pairs |
categories | array of strings | Auto-assigned category tags |
hash | string | Content hash |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last modification timestamp |
Search results additionally include score (relevance metric).
Scoping Identifiers
Memories can be scoped to different levels:
| Scope | Parameter | Use Case |
|---|---|---|
| User | user_id | Per-user memory isolation |
| Agent | agent_id | Per-agent memory partitioning |
| Application | app_id | Cross-agent app-level memory |
| Run/Session | run_id | Session-scoped temporary memory |
Critical: Combining user_id and agent_id in a single AND filter yields empty results. Entities are stored separately. Use OR logic or separate queries.
Processing Model
- Memories are processed asynchronously (v3 default)
- Add responses return queued
ADDevents only (v3 is ADD-only, no UPDATE/DELETE) - Poll status via
GET /v1/event/{event_id}/
Filter System
Filters use nested JSON with a logical operator at the root:
{
"AND": [
{"user_id": "alice"},
{"categories": {"contains": "finance"}},
{"created_at": {"gte": "2024-01-01"}}
]
}Root must be AND, OR, or NOT. Simple shorthand {"user_id": "alice"} also works.
Supported Operators
| Operator | Description |
|---|---|
eq | Equal to (default) |
ne | Not equal to |
in | Matches any value in array |
gt, gte | Greater than / greater than or equal |
lt, lte | Less than / less than or equal |
contains | Case-sensitive containment |
icontains | Case-insensitive containment |
* | Wildcard -- matches any non-null value |
Filterable Fields
| Field | Valid Operators |
|---|---|
user_id, agent_id, app_id, run_id | eq, ne, in, * |
created_at, updated_at, timestamp | gt, gte, lt, lte, eq, ne |
categories | eq, ne, in, contains |
metadata | eq, ne, contains (top-level keys only) |
keywords | contains, icontains |
memory_ids | in |
Filter Constraints
1. Entity scope partitioning: user_id AND agent_id in one AND block yields empty results. 2. Metadata limitations: Only top-level keys. Only eq, contains, ne. No in or gt. 3. Operator syntax: Use gte, lt, ne. SQL-style (>=, !=) rejected. 4. Entity filter required for get-all: At least one of user_id, agent_id, app_id, or run_id. 5. Wildcard excludes null: * matches only non-null values. 6. Date format: ISO 8601 (YYYY-MM-DDTHH:MM:SSZ). Timezone-naive defaults to UTC.
Response Formats
Add Response (v3)
{
"message": "Memory processing has been queued for background execution",
"status": "PENDING",
"event_id": "evt-uuid"
}v3 is ADD-only. No UPDATE or DELETE events.
Search Response
{
"results": [
{
"id": "ea925981-...",
"memory": "Is a vegetarian and allergic to nuts.",
"user_id": "user123",
"categories": ["food", "health"],
"score": 0.89,
"created_at": "2024-07-26T10:29:36.630547-07:00"
}
]
}In v3, score is a combined multi-signal relevance score.
Get All Response (v3)
{
"count": 123,
"next": "https://api.mem0.ai/v3/memories/?page=2&page_size=50",
"previous": null,
"results": [...]
}v3 returns paginated envelope. Use page and page_size query params.
Mem0 Platform Architecture
How Mem0 processes, stores, and retrieves memories under the hood.
Table of Contents
- Core Concept
- Memory Processing Pipeline
- Retrieval Pipeline
- Memory Lifecycle
- Memory Object Structure
- Scoping & Multi-Tenancy
- Memory Layers
- Performance Characteristics
---
Core Concept
Mem0 is a managed memory layer that sits between your AI application and users. Every integration follows the same 3-step loop:
User Input → Retrieve relevant memories → Enrich LLM prompt → Generate response → Store new memoriesMem0 handles the complexity of extraction, deduplication, conflict resolution, and semantic retrieval so your application only needs to call search() and add().
Storage architecture:
- Vector store: Embeddings for semantic similarity search
- Entity store: Automatic entity linking for relationship-aware retrieval
---
Memory Processing Pipeline
What happens when you call client.add()
Messages In
│
▼
┌─────────────────────┐
│ 1. EXTRACTION │ Single LLM call extracts all distinct new facts
│ (infer=True) │ If infer=False, stores raw text as-is
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ 2. DEDUPLICATION │ Hash-based dedup (MD5 prevents exact duplicates)
│ │ No UPDATE/DELETE - v3 is ADD-only
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ 3. STORAGE │ Batch embed → vector store
│ │ Entity extraction → entity store
└─────────┬───────────┘
│
▼
Memory ObjectProcessing (v3)
v3 processes memories asynchronously by default:
- API returns immediately:
{"status": "PENDING", "event_id": "evt-..."} - Poll status via
GET /v1/event/{event_id}/ - Use webhooks for completion notifications
Extraction modes
Inferred (`infer=True`, default):
- LLM extracts structured facts from conversation
- Conflict resolution deduplicates and resolves contradictions
- Best for: natural conversation → memory
Raw (`infer=False`):
- Stores text exactly as provided, no LLM processing
- Skips conflict resolution — same fact can be stored twice
- Only
userrole messages are stored;assistantmessages ignored - Best for: bulk imports, pre-structured data, migrations
Warning: Don't mix infer=True and infer=False for the same data — the same fact will be stored twice.
---
Retrieval Pipeline (v3)
What happens when you call client.search()
Query In
│
▼
┌─────────────────────┐
│ 1. PREPROCESSING │ Lemmatize keywords, extract entities
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ 2. PARALLEL SCORING │ Semantic search (vector similarity)
│ │ BM25 keyword search (term matching)
│ │ Entity matching (entity graph boost)
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ 3. SCORE FUSION │ Combine signals into single score
│ │ Optional: rerank=True for deep reordering
└─────────┬───────────┘
│
▼
Results (combined score per memory)v3 Search Defaults
| Parameter | Default | Notes |
|---|---|---|
top_k | 20 | Was 100 in v2 |
threshold | 0.1 | Was None in v2 |
rerank | False | Was True in v2 |
Implicit null scoping
When you search with filters={"user_id": "alice"} only, Mem0 returns memories where agent_id, app_id, and run_id are all null. This prevents cross-scope leakage by default.
To include memories with non-null fields, use explicit filters:
# Gets memories for alice regardless of agent/app/run
filters={"OR": [{"user_id": "alice"}]}---
Memory Lifecycle (v3)
v3 uses ADD-only extraction. Memories accumulate over time rather than being consolidated.
Creation
client.add(messages, user_id="...")- Single-pass extraction → deduplication → storage
- Returns
{"event_id": "...", "status": "PENDING"}
Updates
client.update(memory_id, text="...")replaces text- Batch:
client.batch_update([...])
Deletion
- Single:
client.delete(memory_id) - Batch:
client.batch_delete([...]) - Bulk:
client.delete_all(filters={"user_id": "alice"})
---
Memory Object Structure
{
"id": "uuid-string",
"memory": "Extracted memory text",
"user_id": "user-identifier",
"agent_id": null,
"app_id": null,
"run_id": null,
"metadata": { "source": "chat", "priority": "high" },
"categories": ["health", "preferences"],
"created_at": "2025-03-12T12:34:56Z",
"updated_at": "2025-03-12T12:34:56Z",
"structured_attributes": {
"day": 12, "month": 3, "year": 2025,
"hour": 12, "minute": 34,
"day_of_week": "wednesday",
"is_weekend": false,
"quarter": 1, "week_of_year": 11
},
"score": 0.85
}| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier, used for update/delete |
memory | string | Extracted or stored text content |
user_id | string | Primary entity scope |
agent_id | string | Agent scope |
app_id | string | Application scope |
run_id | string | Session/run scope |
metadata | object | Custom key-value pairs for filtering |
categories | array | Auto-assigned or custom category tags |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last modification timestamp |
structured_attributes | object | Temporal breakdown for time-based queries |
score | float | Semantic similarity (search results only, 0-1) |
---
Scoping & Multi-Tenancy
Mem0 separates memories across four dimensions to prevent data mixing:
| Dimension | Field | Purpose | Example |
|---|---|---|---|
| User | user_id | Persistent persona or account | "customer_6412" |
| Agent | agent_id | Distinct agent or tool | "meal_planner" |
| App | app_id | Product surface or deployment | "ios_retail_app" |
| Session | run_id | Short-lived flow or thread | "ticket-9241" |
Storage model
Each entity combination creates separate records. A memory with user_id="alice" is stored separately from one with user_id="alice" + agent_id="bot".
Critical: cross-entity queries
# This returns NOTHING — user and agent memories are stored separately
filters={"AND": [{"user_id": "alice"}, {"agent_id": "bot"}]}
# Use OR to query multiple scopes
filters={"OR": [{"user_id": "alice"}, {"agent_id": "bot"}]}
# Use wildcard to include any non-null value
filters={"AND": [{"user_id": "*"}]} # All users (excludes null)Recommended scoping patterns
# User-level: persistent preferences
client.add(messages, user_id="alice")
# Session-level: temporary context
client.add(messages, user_id="alice", run_id="session_123")
# Clean up when done: client.delete_all(run_id="session_123")
# Agent-level: agent-specific knowledge
client.add(messages, agent_id="support_bot", app_id="helpdesk")
# Multi-tenant: full isolation
client.add(messages, user_id="alice", agent_id="bot", app_id="acme_corp", run_id="ticket_42")---
Memory Layers
Mem0 supports three layers of memory, from shortest to longest lived:
Conversation memory
- In-flight messages within a single turn
- Tool calls, chain-of-thought reasoning
- Lifetime: Single response — lost after turn finishes
- Managed by: Your application, not Mem0
Session memory
- Short-lived facts for current task or channel
- Multi-step flows (onboarding, debugging, support tickets)
- Lifetime: Minutes to hours
- Managed by: Mem0 via
run_idparameter - Clean up with
client.delete_all(run_id="session_id")
User memory
- Long-lived knowledge tied to a person or account
- Personal preferences, account state, compliance details
- Lifetime: Weeks to forever
- Managed by: Mem0 via
user_idparameter - Persists across all sessions and interactions
How layering works in practice
def chat(user_input: str, user_id: str, session_id: str) -> str:
# 1. Retrieve user memories (long-term preferences)
user_mems = mem0.search(user_input, filters={"user_id": user_id})
# 2. Retrieve session memories (current task context)
session_mems = mem0.search(user_input, filters={
"AND": [{"user_id": user_id}, {"run_id": session_id}]
})
# 3. Combine both layers for LLM context
context = format_memories(user_mems) + format_memories(session_mems)
# 4. Generate response
response = llm.generate(context=context, input=user_input)
# 5. Store in session scope (temporary) + user scope (persistent)
messages = [{"role": "user", "content": user_input}, {"role": "assistant", "content": response}]
mem0.add(messages, user_id=user_id, run_id=session_id)
return response---
Performance Characteristics
Latency
| Operation | Typical Latency |
|---|---|
| Hybrid search (v3 default) | ~100-150ms |
| + reranking | +150-200ms |
| Add (async) | < 50ms response |
Processing
- Async (default): Returns immediately, processes in background
- Batch operations: Up to 1000 memories per batch_update/batch_delete
- Webhooks: Real-time notifications when async processing completes
Scoping strategy for performance
- Use
user_idfor all user-facing queries (most common, fastest) - Add
run_idfor session isolation (narrows search space) - Avoid wildcard
"*"filters on large datasets (scans all non-null records) - Use
top_kto limit result count when you only need a few memories
---
Comparison with Alternatives
| Approach | Pros | Cons |
|---|---|---|
| Raw vector DB | Fast, full control | No extraction, no dedup, no conflict resolution |
| In-memory chat history | Zero latency | Lost on restart, no cross-session, grows unbounded |
| RAG over documents | Good for static knowledge | No personalization, no memory updates |
| Mem0 Platform | Managed extraction + dedup + graph + scoping | External dependency, async processing delay |
Mem0 combines the best of vector search (semantic retrieval) with automatic extraction (LLM-powered), conflict resolution (deduplication), and structured scoping (multi-tenancy) — in a single managed API.
Platform Features -- Mem0 Platform
Additional platform capabilities beyond core CRUD operations.
Table of Contents
- Advanced Retrieval
- Entity Linking
- Custom Categories
- Custom Instructions
- Criteria Retrieval
- Feedback Mechanism
- Memory Export
- Group Chat
- MCP Integration
- Webhooks
- Multimodal Support
Advanced Retrieval
Hybrid Search (v3 Default)
v3 uses multi-signal hybrid search combining:
- Semantic search (vector similarity)
- BM25 keyword search (normalized term matching)
- Entity matching (entity graph boost)
This is automatic — no configuration needed.
Reranking (rerank=True)
Deep semantic reordering of results — most relevant first.
- Latency: +150-200ms
- Default:
False(wasTruein v2) - Best for: user-facing results, top-N precision
Python:
results = client.search(query, filters={"user_id": "user123"}, rerank=True)TypeScript:
const results = await client.search(query, {
filters: { user_id: 'user123' },
rerank: true,
});---
Entity Linking
v3 replaces graph memory with built-in entity linking. Entities (proper nouns, quoted text, compound noun phrases) are automatically extracted and linked across memories.
How It Works
1. Extraction: During add(), entities are automatically extracted from memory text 2. Storage: Entities are stored in a parallel collection ({collection}_entities) 3. Retrieval: During search(), query entities are matched and used to boost relevant memories
Entity linking is automatic — no configuration required. The boost is folded into the combined score on each result.
v2 Migration Note
If you were using enable_graph=True in v2:
- Remove
enable_graphfrom all API calls - Remove
graph_storefrom OSS configuration - Entity relationships are now consumed through retrieval ranking, not exposed as a separate
relationsarray
See the v2 to v3 migration guide for details.
---
Custom Categories
Replace Mem0's default 15 labels with domain-specific categories. The system automatically tags memories to the closest matching category.
Default Categories (15)
personal_details, family, professional_details, sports, travel, food, music, health, technology, hobbies, fashion, entertainment, milestones, user_preferences, misc
Configuration
Set project-level categories:
new_categories = [
{"lifestyle_management": "Tracks daily routines, habits, wellness activities"},
{"seeking_structure": "Documents goals around creating routines and systems"},
{"personal_information": "Basic information about the user"}
]
client.project.update(custom_categories=new_categories)await client.updateProject({ customCategories: newCategories });Retrieve active categories:
categories = client.project.get(fields=["custom_categories"])Key Constraint
Per-request overrides (custom_categories=... on client.add) are not supported on the managed API. Only project-level configuration works. Workaround: store ad-hoc labels in metadata field.
---
Custom Instructions
Natural language filters that control what information Mem0 extracts when creating memories.
Set Instructions
client.project.update(custom_instructions="Your guidelines here...")await client.updateProject({ customInstructions: "Your guidelines here..." });Template Structure
1. Task Description -- brief extraction overview 2. Information Categories -- numbered sections with specific details to capture 3. Processing Guidelines -- quality and handling rules 4. Exclusion List -- sensitive/irrelevant data to filter out
Domain Examples
E-commerce: Capture product issues, preferences, service experience; exclude payment data.
Education: Extract learning progress, student preferences, performance patterns; exclude specific grades.
Finance: Track financial goals, life events, investment interests; exclude account numbers and SSNs.
Best Practices
- Start simply, test with sample messages, iterate based on results
- Avoid overly lengthy instructions
- Be specific about what to include AND exclude
---
Criteria Retrieval
Custom attribute-based memory ranking using LLM-evaluated criteria with weights. Goes beyond semantic similarity to prioritize memories based on domain-specific signals.
Configuration
# Define criteria at project level
retrieval_criteria = [
{"name": "joy", "description": "Positive emotions like happiness and excitement", "weight": 3},
{"name": "curiosity", "description": "Inquisitiveness and desire to learn", "weight": 2},
{"name": "urgency", "description": "Time-sensitive or high-priority items", "weight": 4},
]
client.project.update(retrieval_criteria=retrieval_criteria)await client.updateProject({
retrievalCriteria: [
{ name: 'joy', description: 'Positive emotions', weight: 3 },
{ name: 'urgency', description: 'Time-sensitive items', weight: 4 },
],
});Usage
Once configured, client.search() automatically applies criteria ranking:
# Criteria-weighted results returned automatically
results = client.search("Why am I feeling happy?", filters={"user_id": "alice"})Best for: Wellness assistants, tutoring platforms, productivity tools — any app needing intent-aware retrieval.
---
Feedback Mechanism
Provide feedback on extracted memories to improve system quality over time.
Feedback Types
| Type | Meaning |
|---|---|
POSITIVE | Memory is useful and accurate |
NEGATIVE | Memory is not useful |
VERY_NEGATIVE | Memory is harmful or completely wrong |
None | Clear existing feedback |
Usage
Python:
client.feedback(
memory_id="mem-123",
feedback="POSITIVE",
feedback_reason="Accurately captured dietary preference"
)
# Bulk feedback
for item in feedback_data:
client.feedback(**item)TypeScript:
await client.feedback('mem-123', {
feedback: 'POSITIVE',
feedbackReason: 'Accurately captured dietary preference',
});---
Memory Export
Create structured exports of memories using customizable schemas with filters.
Usage
import json
# Define export schema
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"preferences": {"type": "array", "items": {"type": "string"}},
"health_info": {"type": "string"},
}
}
# Create export
response = client.create_memory_export(
schema=json.dumps(schema),
filters={"user_id": "alice"},
export_instructions="Create comprehensive profile based on all memories"
)
# Retrieve export (may take a moment to process)
result = client.get_memory_export(memory_export_id=response["id"])Best for: Data analytics, user profile generation, compliance audits, CRM sync.
---
Group Chat
Process multi-participant conversations and automatically attribute memories to individual speakers.
Usage
messages = [
{"role": "user", "name": "Alice", "content": "I think we should use React for the frontend"},
{"role": "user", "name": "Bob", "content": "I prefer Vue.js, it's simpler for our use case"},
{"role": "assistant", "content": "Both are great choices. Let me note your preferences."},
]
# Mem0 automatically attributes memories to each speaker
response = client.add(messages, run_id="team_meeting_1")
# Retrieve Alice's memories from that session
alice_mems = client.get_all(
filters={"AND": [{"user_id": "alice"}, {"run_id": "team_meeting_1"}]}
)Use the name field in messages to identify speakers. Mem0 maps names to entity scopes automatically.
---
MCP Integration
Model Context Protocol integration enables AI clients (Claude, Claude Code, Cursor, Windsurf, VS Code, OpenCode) to manage Mem0 memory autonomously.
Setup
Add Mem0 MCP to your clients with a single command:
npx mcp-add \
--name mem0-mcp \
--type http \
--url "https://mcp.mem0.ai/mcp" \
--clients "claude,claude code,cursor,windsurf,vscode,opencode"Available MCP Tools
The MCP server exposes 9 memory tools that AI agents can use autonomously:
- Add, search, get, update, delete memories
- Get history, list users, delete users
- Search Mem0 documentation
How It Works
1. Add Mem0 MCP to your AI client using the setup command above 2. The agent autonomously decides when to store/retrieve memories 3. No manual API calls needed — the agent manages memory as part of its reasoning
Best for: Universal AI client integration — one protocol works everywhere.
---
Webhooks
Real-time event notifications for memory operations.
Supported Events
| Event | Trigger |
|---|---|
memory_add | Memory created |
memory_update | Memory modified |
memory_delete | Memory removed |
memory_categorize | Memory tagged |
Create Webhook
Note: project_id here refers to the Mem0 dashboard project scope for webhooks — not the deprecated client init parameter.
webhook = client.create_webhook(
url="https://your-app.com/webhook",
name="Memory Logger",
project_id="proj_123",
event_types=["memory_add", "memory_categorize"]
)Manage Webhooks
# Retrieve
webhooks = client.get_webhooks(project_id="proj_123")
# Update
client.update_webhook(
name="Updated Logger",
url="https://your-app.com/new-webhook",
event_types=["memory_update", "memory_add"],
webhook_id="wh_123"
)
# Delete
client.delete_webhook(webhook_id="wh_123")Payload Structure
Memory events contain: ID, data object with memory content, event type (ADD/UPDATE/DELETE). Categorization events contain: memory ID, event type (CATEGORIZE), assigned category labels.
---
Multimodal Support
Mem0 can process images and documents alongside text.
Supported Media Types
- Images: JPG, PNG
- Documents: MDX, TXT, PDF
Image via URL
image_message = {
"role": "user",
"content": {
"type": "image_url",
"image_url": {"url": "https://example.com/image.jpg"}
}
}
client.add([image_message], user_id="alice")Image via Base64
import base64
with open("photo.jpg", "rb") as f:
base64_image = base64.b64encode(f.read()).decode("utf-8")
image_message = {
"role": "user",
"content": {
"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}
}
}
client.add([image_message], user_id="alice")Document (MDX/TXT)
doc_message = {
"role": "user",
"content": {"type": "mdx_url", "mdx_url": {"url": document_url}}
}
client.add([doc_message], user_id="alice")PDF Document
pdf_message = {
"role": "user",
"content": {"type": "pdf_url", "pdf_url": {"url": pdf_url}}
}
client.add([pdf_message], user_id="alice")Mem0 Integration Patterns
Working code examples for integrating Mem0 Platform with popular AI frameworks. All examples use MemoryClient (Platform API key).
Code examples are sourced from official Mem0 integration docs at docs.mem0.ai, simplified for quick reference.
---
Common Pattern
Every integration follows the same 3-step loop:
1. Retrieve -- search relevant memories before generating a response 2. Generate -- include memories as context in the LLM prompt 3. Store -- save the interaction back to Mem0 for future use
---
LangChain
Source: docs.mem0.ai/integrations/langchain
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from mem0 import MemoryClient
llm = ChatOpenAI(model="gpt-5-mini")
mem0 = MemoryClient()
prompt = ChatPromptTemplate.from_messages([
SystemMessage(content="You are a helpful travel agent AI. Use the provided context to personalize your responses."),
MessagesPlaceholder(variable_name="context"),
HumanMessage(content="{input}")
])
def retrieve_context(query: str, user_id: str):
"""Retrieve relevant memories from Mem0"""
memories = mem0.search(query, user_id=user_id)
memory_list = memories['results']
serialized = ' '.join([m["memory"] for m in memory_list])
return [
{"role": "system", "content": f"Relevant information: {serialized}"},
{"role": "user", "content": query}
]
def chat_turn(user_input: str, user_id: str) -> str:
# 1. Retrieve
context = retrieve_context(user_input, user_id)
# 2. Generate
chain = prompt | llm
response = chain.invoke({"context": context, "input": user_input})
# 3. Store
mem0.add(
[{"role": "user", "content": user_input}, {"role": "assistant", "content": response.content}],
user_id=user_id
)
return response.content---
CrewAI
Source: docs.mem0.ai/integrations/crewai
CrewAI has native Mem0 integration via memory_config:
from crewai import Agent, Task, Crew, Process
from mem0 import MemoryClient
client = MemoryClient()
# Store user preferences first
messages = [
{"role": "user", "content": "I am more of a beach person than a mountain person."},
{"role": "assistant", "content": "Noted! I'll recommend beach destinations."},
{"role": "user", "content": "I like Airbnb more than hotels."},
]
client.add(messages, user_id="crew_user_1")
# Create agent
travel_agent = Agent(
role="Personalized Travel Planner",
goal="Plan personalized travel itineraries",
backstory="You are a seasoned travel planner.",
memory=True,
)
# Create task
task = Task(
description="Find places to live, eat, and visit in San Francisco.",
expected_output="A detailed list of places to live, eat, and visit.",
agent=travel_agent,
)
# Setup crew with Mem0 memory
crew = Crew(
agents=[travel_agent],
tasks=[task],
process=Process.sequential,
memory=True,
memory_config={
"provider": "mem0",
"config": {"user_id": "crew_user_1"},
}
)
result = crew.kickoff()---
Vercel AI SDK
Dedicated skill available. For comprehensive Vercel AI SDK documentation, see the mem0-vercel-ai-sdk skill (GitHub).
Install: npm install @mem0/vercel-ai-provider
Quick example (wrapped model with automatic memory):
import { generateText } from "ai";
import { createMem0 } from "@mem0/vercel-ai-provider";
const mem0 = createMem0();
const { text } = await generateText({
model: mem0("gpt-5-mini", { user_id: "borat" }),
prompt: "Suggest me a good car to buy!",
});Supported providers: openai, anthropic, google, groq, cohere
---
OpenAI Agents SDK
Source: docs.mem0.ai/integrations/openai-agents-sdk
from agents import Agent, Runner, function_tool
from mem0 import MemoryClient
mem0 = MemoryClient()
@function_tool
def search_memory(query: str, user_id: str) -> str:
"""Search through past conversations and memories"""
memories = mem0.search(query, user_id=user_id, top_k=3)
if memories and memories.get('results'):
return "\n".join([f"- {mem['memory']}" for mem in memories['results']])
return "No relevant memories found."
@function_tool
def save_memory(content: str, user_id: str) -> str:
"""Save important information to memory"""
mem0.add([{"role": "user", "content": content}], user_id=user_id)
return "Information saved to memory."
agent = Agent(
name="Personal Assistant",
instructions="""You are a helpful personal assistant with memory capabilities.
Use search_memory to recall past conversations.
Use save_memory to store important information.""",
tools=[search_memory, save_memory],
model="gpt-5-mini"
)
result = Runner.run_sync(agent, "I love Italian food and I'm planning a trip to Rome next month")
print(result.final_output)Multi-Agent with Handoffs
from agents import Agent, Runner, function_tool
travel_agent = Agent(
name="Travel Planner",
instructions="You are a travel planning specialist. Use search_memory and save_memory tools.",
tools=[search_memory, save_memory],
model="gpt-5-mini"
)
health_agent = Agent(
name="Health Advisor",
instructions="You are a health and wellness advisor. Use search_memory and save_memory tools.",
tools=[search_memory, save_memory],
model="gpt-5-mini"
)
triage_agent = Agent(
name="Personal Assistant",
instructions="""Route travel questions to Travel Planner, health questions to Health Advisor.""",
handoffs=[travel_agent, health_agent],
model="gpt-5-mini"
)
result = Runner.run_sync(triage_agent, "Plan a healthy meal for my Italy trip")---
Pipecat (Voice / Real-Time)
Source: docs.mem0.ai/integrations/pipecat
from pipecat.services.mem0 import Mem0MemoryService
memory = Mem0MemoryService(
api_key=os.getenv("MEM0_API_KEY"),
user_id="alice",
agent_id="voice_bot",
params={
"search_limit": 10,
"search_threshold": 0.1,
"system_prompt": "Here are your past memories:",
"add_as_system_message": True,
}
)
# Use in pipeline
pipeline = Pipeline([
transport.input(),
stt,
user_context,
memory, # Memory enhances context automatically
llm,
transport.output(),
assistant_context
])---
LangGraph
Source: docs.mem0.ai/integrations/langgraph
State-based agent workflows with memory persistence. Best for complex conversation flows with branching logic.
from typing import Annotated, TypedDict, List
from langgraph.graph import StateGraph, START
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
from mem0 import MemoryClient
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
llm = ChatOpenAI(model="gpt-5-mini")
mem0 = MemoryClient()
class State(TypedDict):
messages: Annotated[List[HumanMessage | AIMessage], add_messages]
mem0_user_id: str
def chatbot(state: State):
messages = state["messages"]
user_id = state["mem0_user_id"]
# Retrieve relevant memories
memories = mem0.search(messages[-1].content, user_id=user_id)
context = "Relevant context:\n"
for memory in memories["results"]:
context += f"- {memory['memory']}\n"
system_message = SystemMessage(content=f"""You are a helpful support assistant.
{context}""")
response = llm.invoke([system_message] + messages)
# Store the interaction
mem0.add(
[{"role": "user", "content": messages[-1].content},
{"role": "assistant", "content": response.content}],
user_id=user_id
)
return {"messages": [response]}
graph = StateGraph(State)
graph.add_node("chatbot", chatbot)
graph.add_edge(START, "chatbot")
app = graph.compile()
# Usage
result = app.invoke({
"messages": [HumanMessage(content="I need help with my order")],
"mem0_user_id": "customer_123"
})---
LlamaIndex
Source: docs.mem0.ai/integrations/llama-index
Install: pip install llama-index-core llama-index-memory-mem0
LlamaIndex has native Mem0 support via Mem0Memory. Works with ReAct and FunctionCalling agents.
from llama_index.memory.mem0 import Mem0Memory
context = {"user_id": "alice", "agent_id": "llama_agent_1"}
memory = Mem0Memory.from_client(
context=context,
search_msg_limit=4, # messages from chat history used for retrieval (default: 5)
)
# Use with LlamaIndex agent
from llama_index.core.agent import FunctionCallingAgent
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-5-mini")
agent = FunctionCallingAgent.from_tools(
tools=[],
llm=llm,
memory=memory,
verbose=True,
)
response = agent.chat("I prefer vegetarian restaurants")
# Memory automatically stores and retrieves context
response = agent.chat("What kind of food do I like?")
# Agent retrieves the vegetarian preference from Mem0---
AutoGen
Source: docs.mem0.ai/integrations/autogen
Install: pip install autogen mem0ai
Multi-agent conversational systems with memory persistence.
from autogen import ConversableAgent
from mem0 import MemoryClient
memory_client = MemoryClient()
USER_ID = "alice"
agent = ConversableAgent(
"chatbot",
llm_config={"config_list": [{"model": "gpt-5-mini", "api_key": os.environ["OPENAI_API_KEY"]}]},
code_execution_config=False,
human_input_mode="NEVER",
)
def get_context_aware_response(question: str) -> str:
# Retrieve memories for context
relevant_memories = memory_client.search(question, user_id=USER_ID)
context = "\n".join([m["memory"] for m in relevant_memories.get("results", [])])
prompt = f"""Answer considering previous interactions:
Previous context: {context}
Question: {question}"""
reply = agent.generate_reply(messages=[{"content": prompt, "role": "user"}])
# Store the new interaction
memory_client.add(
[{"role": "user", "content": question}, {"role": "assistant", "content": reply}],
user_id=USER_ID
)
return reply---
All Supported Frameworks
Beyond the examples above, Mem0 integrates with:
| Framework | Type | Install |
|---|---|---|
| Mastra | TS agent framework | npm install @mastra/mem0 |
| ElevenLabs | Voice AI | pip install elevenlabs mem0ai |
| LiveKit | Real-time voice/video | pip install livekit-agents mem0ai |
| Camel AI | Multi-agent framework | pip install camel-ai[all] mem0ai |
| AWS Bedrock | Cloud LLM provider | pip install boto3 mem0ai |
| Dify | Low-code AI platform | Plugin-based |
| Google AI ADK | Google agent framework | pip install google-adk mem0ai |
For the general Python pattern (no framework), see the "Common integration pattern" in SKILL.md.
Mem0 Platform Quickstart
Get running with Mem0 in 2 minutes. No infrastructure to deploy -- just an API key.
Prerequisites
- Python 3.10+ or Node.js 18+
- A Mem0 Platform API key (Get one here)
Python Setup
pip install mem0ai
export MEM0_API_KEY="m0-your-api-key"from mem0 import MemoryClient
client = MemoryClient(api_key="your-api-key")
# Add a memory
messages = [
{"role": "user", "content": "I'm a vegetarian and allergic to nuts."},
{"role": "assistant", "content": "Got it! I'll remember your dietary preferences."}
]
client.add(messages, user_id="user123")
# Search memories
results = client.search("What are my dietary restrictions?", user_id="user123")
print(results)Async Client
from mem0 import AsyncMemoryClient
client = AsyncMemoryClient(api_key="your-api-key")
await client.add(messages, user_id="user123")
results = await client.search("query", user_id="user123")TypeScript / JavaScript Setup
npm install mem0ai
export MEM0_API_KEY="m0-your-api-key"import MemoryClient from 'mem0ai';
const client = new MemoryClient({ apiKey: 'your-api-key' });
// Add a memory
const messages = [
{"role": "user", "content": "I'm a vegetarian and allergic to nuts."},
{"role": "assistant", "content": "Got it! I'll remember your dietary preferences."}
];
await client.add(messages, { userId: "user123" });
// Search memories
const results = await client.search("What are my dietary restrictions?", {
filters: { user_id: "user123" }
});
console.log(results);cURL
export MEM0_API_KEY="m0-your-api-key"
# Add memory
curl -X POST https://api.mem0.ai/v1/memories/ \
-H "Authorization: Token $MEM0_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "user", "content": "I am a vegetarian and allergic to nuts."},
{"role": "assistant", "content": "Got it! I will remember your dietary preferences."}
],
"user_id": "user123"
}'
# Search memories
curl -X POST https://api.mem0.ai/v2/memories/search/ \
-H "Authorization: Token $MEM0_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "What are my dietary restrictions?",
"filters": {"user_id": "user123"}
}'Sample Response
{
"results": [
{
"id": "14e1b28a-2014-40ad-ac42-69c9ef42193d",
"memory": "Allergic to nuts",
"user_id": "user123",
"categories": ["health"],
"created_at": "2025-10-22T04:40:22.864647-07:00",
"score": 0.30
}
]
}Next Steps
- SDK Guide -- all methods for Python and TypeScript
- API Reference -- REST endpoints and memory object structure
- Integration Patterns -- LangChain, CrewAI, Vercel AI, etc.
Mem0 SDK Guide
Complete SDK reference for Python and TypeScript. All methods use MemoryClient (Platform API).
For language-specific deep references (including OSS): See client/python.md and client/node.md. For Python vs TypeScript differences: client/differences.md.
Initialization
Python:
from mem0 import MemoryClient
client = MemoryClient(api_key="m0-your-api-key")Python (Async):
from mem0 import AsyncMemoryClient
client = AsyncMemoryClient(api_key="m0-your-api-key")TypeScript:
import MemoryClient from 'mem0ai';
const client = new MemoryClient({ apiKey: 'm0-your-api-key' });Constructor accepts apiKey (required) and host (optional, default: https://api.mem0.ai).
---
add() -- Store Memories
Python:
messages = [
{"role": "user", "content": "I'm a vegetarian and allergic to nuts."},
{"role": "assistant", "content": "Got it! I'll remember that."}
]
client.add(messages, user_id="alice")
# With metadata
client.add(messages, user_id="alice", metadata={"source": "onboarding"})TypeScript:
await client.add(messages, { userId: "alice" });
await client.add(messages, { userId: "alice", metadata: { source: "onboarding" } });Parameters
| Name | Type | Description |
|---|---|---|
messages | array | [{"role": "user", "content": "..."}] |
user_id | string | User identifier (recommended) |
agent_id | string | Agent identifier |
run_id | string | Session identifier |
metadata | object | Custom key-value pairs |
infer | boolean | If false, store raw text without inference (default: true) |
Advanced Add Options
# Agent + session scoping
client.add(messages, user_id="alice", agent_id="nutrition-agent", run_id="session-456")
# Raw text -- skip LLM inference
client.add(
[{"role": "user", "content": "User prefers dark mode."}],
user_id="alice",
infer=False,
)---
search() -- Find Memories
Python:
results = client.search("dietary preferences?", filters={"user_id": "alice"})
# With filters and reranking
results = client.search(
query="work experience",
filters={"AND": [{"user_id": "alice"}, {"categories": {"contains": "professional_details"}}]},
top_k=5,
rerank=True,
threshold=0.5
)TypeScript:
const results = await client.search("dietary preferences", { filters: { user_id: "alice" } });
const results = await client.search("work experience", {
filters: { AND: [{ user_id: "alice" }, { categories: { contains: "professional_details" } }] },
topK: 5,
rerank: true,
});Parameters
| Name | Type | Description |
|---|---|---|
query | string | Natural language search query |
filters | object | Filter object (AND/OR operators). Use {"user_id": "..."} to filter by user |
top_k | number | Number of results (default: 10 for Platform) |
rerank | boolean | Enable reranking for better relevance (default: false) |
threshold | number | Minimum similarity score (default: 0.1) |
Common Filter Patterns
Python:
# Single user filter
filters={"user_id": "alice"}
# OR across agents
filters={"OR": [{"user_id": "alice"}, {"agent_id": {"in": ["travel-agent", "sports-agent"]}}]}
# Category filtering (partial match)
filters={"AND": [{"user_id": "alice"}, {"categories": {"contains": "finance"}}]}
# Category filtering (exact match)
filters={"AND": [{"user_id": "alice"}, {"categories": {"in": ["personal_information"]}}]}
# Wildcard (match any non-null run)
filters={"AND": [{"user_id": "alice"}, {"run_id": "*"}]}
# Date range
filters={"AND": [
{"user_id": "alice"},
{"created_at": {"gte": "2024-01-01T00:00:00Z"}},
{"created_at": {"lt": "2024-02-01T00:00:00Z"}}
]}
# Exclude categories with NOT
filters={"AND": [{"user_id": "user_123"}, {"NOT": {"categories": {"in": ["spam", "test"]}}}]}
# Multi-dimensional query
filters={"AND": [
{"user_id": "user_123"},
{"keywords": {"icontains": "invoice"}},
{"categories": {"in": ["finance"]}},
{"created_at": {"gte": "2024-01-01T00:00:00Z"}}
]}TypeScript:
// Single user filter
filters: { user_id: "alice" }
// OR across agents
filters: { OR: [{ user_id: "alice" }, { agent_id: { in: ["travel-agent", "sports-agent"] } }] }
// Category filtering (partial match)
filters: { AND: [{ user_id: "alice" }, { categories: { contains: "finance" } }] }
// Category filtering (exact match)
filters: { AND: [{ user_id: "alice" }, { categories: { in: ["personal_information"] } }] }---
get() / getAll() -- Retrieve Memories
Python:
# Single memory by ID
memory = client.get(memory_id="ea925981-...")
# All memories for a user
memories = client.get_all(filters={"user_id": "alice"})
# With date range
memories = client.get_all(
filters={"AND": [
{"user_id": "alex"},
{"created_at": {"gte": "2024-07-01", "lte": "2024-07-31"}}
]}
)TypeScript:
const memory = await client.get("ea925981-...");
const memories = await client.getAll({ filters: { user_id: "alice" } });Note: get_all requires at least one of user_id, agent_id, app_id, or run_id in filters.
---
update() -- Modify Memories
Python:
client.update(memory_id="ea925981-...", text="Updated: vegan since 2024")
client.update(memory_id="ea925981-...", text="Updated", metadata={"verified": True})TypeScript:
await client.update("ea925981-...", { text: "Updated: vegan since 2024" });---
delete() / deleteAll() -- Remove Memories
Python:
client.delete(memory_id="ea925981-...")
client.delete_all(user_id="alice") # Irreversible bulk deleteTypeScript:
await client.delete("ea925981-...");
await client.deleteAll({ userId: "alice" });---
history() -- Track Changes
Python:
history = client.history(memory_id="ea925981-...")
# Returns: [{previous_value, new_value, action, timestamps}]TypeScript:
const history = await client.history("ea925981-...");---
Batch Operations (TypeScript)
// Batch update
await client.batchUpdate([
{ memoryId: "uuid-1", text: "Updated text" },
{ memoryId: "uuid-2", text: "Another updated text" },
]);
// Batch delete
await client.batchDelete(["uuid-1", "uuid-2", "uuid-3"]);---
Additional Methods
# List all users/agents/sessions with memories
users = client.users()
# Delete a user/agent entity
client.delete_users(user_id="alice")
# Submit feedback on a memory
client.feedback(memory_id="...", feedback="POSITIVE", feedback_reason="Accurate extraction")
# Export memories
export = client.create_memory_export(filters={"AND": [{"user_id": "alice"}]})
data = client.get_memory_export(memory_export_id=export["id"])---
Common Pitfalls
1. Entity cross-filtering fails silently -- AND with user_id + agent_id returns empty. Use OR. 2. SQL operators rejected -- use gte, lt, etc. Not >=, <. 3. Metadata filtering is limited -- only top-level keys with eq, contains, ne. 4. *Wildcard ` excludes null** -- only matches non-null values. 5. **Default threshold is 0.1** -- increase for stricter matching. 6. **Async processing** -- memories process asynchronously. Wait 2-3s after add()` before searching.
Naming Conventions
Python uses snake_case everywhere (user_id, memory_id, get_all). TypeScript uses camelCase for methods (getAll, deleteAll, batchUpdate) and top-level parameters (userId, topK, pageSize), but filter keys use snake_case (user_id, agent_id).
---
v2 to v3 Migration
Breaking Changes in v3
1. Entity IDs in search() and getAll()
v3 requires entity IDs (user_id, agent_id, run_id) inside filters instead of as top-level parameters:
# v2 (deprecated)
client.search("query", user_id="alice")
client.get_all(user_id="alice")
# v3
client.search("query", filters={"user_id": "alice"})
client.get_all(filters={"user_id": "alice"})// v2 (deprecated)
await client.search("query", { user_id: "alice" });
await client.getAll({ user_id: "alice" });
// v3
await client.search("query", { filters: { user_id: "alice" } });
await client.getAll({ filters: { user_id: "alice" } });2. TypeScript Parameter Naming
v3 TypeScript uses camelCase for all parameters:
| v2 | v3 |
|---|---|
user_id | userId |
agent_id | agentId |
run_id | runId |
top_k | topK |
page_size | pageSize |
3. Default Values Changed
| Parameter | v2 Default | v3 Default |
|---|---|---|
threshold | 0.3 | 0.1 |
rerank | (not specified) | false |
4. Removed Parameters
The following parameters are no longer supported:
| Parameter | Status |
|---|---|
enable_graph | Removed from add/search/getAll |
keyword_search | Removed from search |
filter_memories | Removed |
immutable | Removed from add |
expiration_date | Removed from add |
includes | Removed from add |
excludes | Removed from add |
async_mode | Removed from add |
Mem0 Use Cases & Examples
Real-world implementation patterns for Mem0 Platform. Each use case includes complete, runnable code in both Python and TypeScript.
Table of Contents
- Personalized AI Companion
- Customer Support with Categories
- Healthcare Coach
- Content Creation Workflow
- Multi-Agent / Multi-Tenant
- Personalized Search
- Email Intelligence
- Common Patterns Across Use Cases
---
1. Personalized AI Companion
A fitness coach that remembers goals, preferences, and progress across sessions. Mem0 persists context across app restarts — no session state needed.
Implementation (Python)
from mem0 import MemoryClient
from openai import OpenAI
mem0 = MemoryClient()
openai_client = OpenAI()
def chat(user_input: str, user_id: str) -> str:
# 1. Retrieve relevant memories
memories = mem0.search(user_input, user_id=user_id)
context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])])
# 2. Generate response with memory context
system_prompt = f"""You are Ray, a personal fitness coach.
Use these known facts about the user to personalize your response:
{context if context else 'No prior context yet.'}"""
response = openai_client.chat.completions.create(
model="gpt-5-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_input},
]
)
reply = response.choices[0].message.content
# 3. Store interaction for future context
mem0.add(
[{"role": "user", "content": user_input}, {"role": "assistant", "content": reply}],
user_id=user_id
)
return reply
# Usage
chat("I want to run a marathon in under 4 hours", user_id="max")
# Next day, app restarted:
chat("What should I focus on today?", user_id="max")
# Ray remembers the sub-4 marathon goalImplementation (TypeScript)
import MemoryClient from 'mem0ai';
import OpenAI from 'openai';
const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
const openai = new OpenAI();
async function chat(userInput: string, userId: string): Promise<string> {
// 1. Retrieve relevant memories
const memories = await mem0.search(userInput, { filters: { user_id: userId } });
const context = memories.results
?.map((m: any) => `- ${m.memory}`)
.join('\n') || 'No prior context yet.';
// 2. Generate response with memory context
const response = await openai.chat.completions.create({
model: 'gpt-5-mini',
messages: [
{ role: 'system', content: `You are Ray, a personal fitness coach.\nUser context:\n${context}` },
{ role: 'user', content: userInput },
],
});
const reply = response.choices[0].message.content!;
// 3. Store interaction
await mem0.add(
[{ role: 'user', content: userInput }, { role: 'assistant', content: reply }],
{ userId: userId }
);
return reply;
}Key Benefits
- Context persists across app restarts — no session management needed
- Memories are automatically deduplicated and updated
- Works with any LLM provider (OpenAI, Anthropic, etc.)
Best for: Fitness coaches, tutors, therapists — any assistant that needs to remember goals across sessions.
---
2. Customer Support with Categories
Auto-categorize support data so teams retrieve the right facts fast. Uses custom categories for structured retrieval.
Implementation (Python)
from mem0 import MemoryClient
client = MemoryClient()
# 1. Define categories at the project level (one-time setup)
custom_categories = [
{"support_tickets": "Customer issues and resolutions"},
{"account_info": "Account details and preferences"},
{"billing": "Payment history and billing questions"},
{"product_feedback": "Feature requests and feedback"},
]
client.project.update(custom_categories=custom_categories)
# 2. Store interactions — auto-classified into categories
def log_support_interaction(user_id: str, message: str, priority: str = "normal"):
client.add(
[{"role": "user", "content": message}],
user_id=user_id,
metadata={"priority": priority, "source": "support_chat"}
)
# 3. Retrieve by category
def get_billing_issues(user_id: str):
return client.get_all(
filters={
"AND": [
{"user_id": user_id},
{"categories": {"in": ["billing"]}}
]
}
)
def search_support_history(user_id: str, query: str):
return client.search(
query,
filters={
"AND": [
{"user_id": user_id},
{"categories": {"contains": "support_tickets"}}
]
},
top_k=5
)
# Usage
log_support_interaction("maria", "I was charged twice for last month's subscription", priority="high")
log_support_interaction("maria", "The dashboard is loading slowly on mobile")
billing = get_billing_issues("maria") # Returns only billing-related memoriesImplementation (TypeScript)
import MemoryClient from 'mem0ai';
const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
// Setup categories (one-time)
await client.updateProject({
custom_categories: [
{ support_tickets: 'Customer issues and resolutions' },
{ billing: 'Payment history and billing questions' },
{ product_feedback: 'Feature requests and feedback' },
],
});
async function logInteraction(userId: string, message: string, priority = 'normal') {
await client.add(
[{ role: 'user', content: message }],
{ userId: userId, metadata: { priority, source: 'support_chat' } }
);
}
async function getBillingIssues(userId: string) {
return client.getAll({
filters: { AND: [{ user_id: userId }, { categories: { in: ['billing'] } }] },
});
}Key Benefits
- Automatic categorization — no manual tagging
- Filter by category for structured retrieval
- Metadata (
priority,source) enables multi-dimensional queries
Best for: Help desks, SaaS support, e-commerce — structured retrieval by category eliminates manual scanning.
---
3. Healthcare Coach
Guide patients with an assistant that remembers medical history. Uses high threshold for confident retrieval in safety-critical contexts.
Implementation (Python)
from mem0 import MemoryClient
from openai import OpenAI
mem0 = MemoryClient()
openai_client = OpenAI()
def save_patient_info(user_id: str, information: str):
mem0.add(
[{"role": "user", "content": information}],
user_id=user_id,
run_id="healthcare_session",
metadata={"type": "patient_information"}
)
def consult(user_id: str, question: str) -> str:
# High threshold for medical accuracy
memories = mem0.search(question, user_id=user_id, top_k=5, threshold=0.7)
context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])])
response = openai_client.chat.completions.create(
model="gpt-5-mini",
messages=[
{"role": "system", "content": f"You are a health coach. Patient context:\n{context}"},
{"role": "user", "content": question},
]
)
reply = response.choices[0].message.content
# Store the interaction
mem0.add(
[{"role": "user", "content": question}, {"role": "assistant", "content": reply}],
user_id=user_id,
run_id="healthcare_session",
)
return reply
# Usage
save_patient_info("alex", "I'm allergic to penicillin and take metformin for type 2 diabetes")
consult("alex", "Can I take amoxicillin for my sore throat?")
# Remembers penicillin allergy — amoxicillin is a penicillin-type antibioticImplementation (TypeScript)
import MemoryClient from 'mem0ai';
import OpenAI from 'openai';
const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
const openai = new OpenAI();
async function savePatientInfo(userId: string, info: string) {
await mem0.add(
[{ role: 'user', content: info }],
{ userId: userId, runId: 'healthcare_session', metadata: { type: 'patient_information' } }
);
}
async function consult(userId: string, question: string): Promise<string> {
const memories = await mem0.search(question, {
filters: { user_id: userId },
topK: 5,
threshold: 0.7,
});
const context = memories.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
const response = await openai.chat.completions.create({
model: 'gpt-5-mini',
messages: [
{ role: 'system', content: `You are a health coach. Patient context:\n${context}` },
{ role: 'user', content: question },
],
});
const reply = response.choices[0].message.content!;
await mem0.add(
[{ role: 'user', content: question }, { role: 'assistant', content: reply }],
{ userId: userId, runId: 'healthcare_session' }
);
return reply;
}Key Benefits
- High threshold (0.7) ensures only confident matches for safety-critical retrieval
- Session scoping via
run_idgroups related health interactions - Metadata tagging separates patient info from conversation history
Best for: Telehealth, wellness apps, patient management — persistent health context across visits.
---
4. Content Creation Workflow
Store voice guidelines once and apply them across every draft. Uses run_id and metadata to scope writing preferences per session.
Implementation (Python)
from mem0 import MemoryClient
from openai import OpenAI
mem0 = MemoryClient()
openai_client = OpenAI()
def store_writing_preferences(user_id: str, preferences: str):
mem0.add(
[{"role": "user", "content": preferences}],
user_id=user_id,
run_id="editing_session",
metadata={"type": "preferences", "category": "writing_style"}
)
def draft_content(user_id: str, topic: str) -> str:
# Retrieve writing preferences
prefs = mem0.search(
"writing style preferences",
filters={"AND": [{"user_id": user_id}, {"run_id": "editing_session"}]}
)
style_context = "\n".join([f"- {m['memory']}" for m in prefs.get("results", [])])
response = openai_client.chat.completions.create(
model="gpt-5-mini",
messages=[
{"role": "system", "content": f"Write content matching these style preferences:\n{style_context}"},
{"role": "user", "content": f"Write a blog post about: {topic}"},
]
)
return response.choices[0].message.content
# Usage
store_writing_preferences("writer_01", "I prefer short sentences. Active voice. No jargon. Use analogies.")
draft_content("writer_01", "Why AI memory matters for chatbots")
# Drafts content matching the stored voice guidelinesImplementation (TypeScript)
import MemoryClient from 'mem0ai';
import OpenAI from 'openai';
const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
const openai = new OpenAI();
async function storePreferences(userId: string, preferences: string) {
await mem0.add(
[{ role: 'user', content: preferences }],
{ userId: userId, runId: 'editing_session', metadata: { type: 'preferences' } }
);
}
async function draftContent(userId: string, topic: string): Promise<string> {
const prefs = await mem0.search('writing style preferences', {
filters: { AND: [{ user_id: userId }, { run_id: 'editing_session' }] },
});
const styleContext = prefs.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
const response = await openai.chat.completions.create({
model: 'gpt-5-mini',
messages: [
{ role: 'system', content: `Write content matching these preferences:\n${styleContext}` },
{ role: 'user', content: `Write a blog post about: ${topic}` },
],
});
return response.choices[0].message.content!;
}Key Benefits
- Voice consistency across all content without repeating guidelines
- Scoped sessions let you maintain different style profiles
- Preferences update automatically as you refine them
Best for: Marketing teams, technical writers, agencies — consistent voice across all content.
---
5. Multi-Agent / Multi-Tenant
Keep memories separate using user_id, agent_id, app_id, and run_id scoping. Critical for multi-agent workflows and multi-tenant apps.
Implementation (Python)
from mem0 import MemoryClient
client = MemoryClient()
# Store memories scoped to user + agent + session
def store_scoped_memory(messages: list, user_id: str, agent_id: str, run_id: str, app_id: str):
client.add(
messages,
user_id=user_id,
agent_id=agent_id,
run_id=run_id,
app_id=app_id
)
# Query within a specific scope
def search_user_session(query: str, user_id: str, app_id: str, run_id: str):
"""Search memories for a specific user within a specific session."""
return client.search(
query,
filters={
"AND": [
{"user_id": user_id},
{"app_id": app_id},
{"run_id": run_id}
]
}
)
def search_agent_knowledge(query: str, agent_id: str, app_id: str):
"""Search all memories an agent has across all users."""
return client.search(
query,
filters={
"AND": [
{"agent_id": agent_id},
{"app_id": app_id}
]
}
)
# Usage: Travel concierge app with multiple agents
store_scoped_memory(
[{"role": "user", "content": "I'm vegetarian and prefer window seats"}],
user_id="traveler_cam",
agent_id="travel_planner",
run_id="tokyo-2025",
app_id="concierge_app"
)
# User-scoped query: "What does Cam prefer?"
user_mems = search_user_session("dietary restrictions?", "traveler_cam", "concierge_app", "tokyo-2025")
# Agent-scoped query: "What do all travelers prefer?" (across users)
agent_mems = search_agent_knowledge("common dietary restrictions?", "travel_planner", "concierge_app")Implementation (TypeScript)
import MemoryClient from 'mem0ai';
const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
async function storeScopedMemory(
messages: Array<{ role: string; content: string }>,
userId: string, agentId: string, runId: string, appId: string
) {
await client.add(messages, {
userId: userId,
agentId: agentId,
runId: runId,
appId: appId,
});
}
async function searchUserSession(query: string, userId: string, appId: string, runId: string) {
return client.search(query, {
filters: { AND: [{ user_id: userId }, { app_id: appId }, { run_id: runId }] },
});
}
async function searchAgentKnowledge(query: string, agentId: string, appId: string) {
return client.search(query, {
filters: { AND: [{ agent_id: agentId }, { app_id: appId }] },
});
}Key Benefits
- Full isolation between users, agents, sessions, and apps
- Query at any scope level — user, agent, session, or app-wide
- No memory leakage between tenants
Best for: Multi-agent workflows, multi-tenant SaaS — proper isolation at every level.
---
6. Personalized Search
Blend real-time search results with personal context. Uses custom_instructions to infer preferences from queries.
Implementation (Python)
from mem0 import MemoryClient
from openai import OpenAI
mem0 = MemoryClient()
openai_client = OpenAI()
# One-time setup: configure Mem0 to infer from queries
mem0.project.update(
custom_instructions="""Infer user preferences and facts from their search queries.
Extract dietary preferences, location, interests, and purchase history."""
)
def personalized_search(user_id: str, query: str, search_results: list) -> str:
# Get user context from memory
memories = mem0.search(query, user_id=user_id, top_k=5)
user_context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])])
response = openai_client.chat.completions.create(
model="gpt-5-mini",
messages=[
{"role": "system", "content": f"Personalize search results using user context:\n{user_context}"},
{"role": "user", "content": f"Query: {query}\n\nSearch results:\n{search_results}"},
]
)
reply = response.choices[0].message.content
# Store the query to learn preferences over time
mem0.add(
[{"role": "user", "content": query}],
user_id=user_id
)
return reply
# Usage
personalized_search("user_42", "best restaurants nearby", ["Restaurant A", "Restaurant B"])
# Over time, Mem0 learns: "user prefers vegetarian, lives in Austin"
# Future searches are automatically personalizedImplementation (TypeScript)
import MemoryClient from 'mem0ai';
import OpenAI from 'openai';
const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
const openai = new OpenAI();
async function personalizedSearch(userId: string, query: string, searchResults: string[]): Promise<string> {
const memories = await mem0.search(query, { filters: { user_id: userId }, topK: 5 });
const context = memories.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
const response = await openai.chat.completions.create({
model: 'gpt-5-mini',
messages: [
{ role: 'system', content: `Personalize results using user context:\n${context}` },
{ role: 'user', content: `Query: ${query}\nResults: ${searchResults.join(', ')}` },
],
});
const reply = response.choices[0].message.content!;
await mem0.add([{ role: 'user', content: query }], { userId: userId });
return reply;
}Key Benefits
- Learns preferences from queries automatically via
custom_instructions - Personalizes any search provider (Tavily, Google, Bing)
- Zero manual preference setup — improves over time
Best for: Personalized search engines, recommendation systems — search results tailored to individual users.
---
7. Email Intelligence
Capture, categorize, and recall inbox threads using persistent memories with rich metadata.
Implementation (Python)
from mem0 import MemoryClient
client = MemoryClient()
def store_email(user_id: str, sender: str, subject: str, body: str, date: str):
client.add(
[{"role": "user", "content": f"Email from {sender}: {subject}\n\n{body}"}],
user_id=user_id,
metadata={"email_type": "incoming", "sender": sender, "subject": subject, "date": date}
)
def search_emails(user_id: str, query: str):
return client.search(
query,
filters={"AND": [{"user_id": user_id}, {"categories": {"contains": "email"}}]},
top_k=10
)
def get_emails_from_sender(user_id: str, sender: str):
return client.get_all(
filters={
"AND": [
{"user_id": user_id},
{"metadata": {"contains": sender}}
]
}
)
# Usage
store_email("alice", "bob@acme.com", "Q3 Budget Review", "Attached is the Q3 budget...", "2025-01-15")
store_email("alice", "carol@acme.com", "Sprint Planning", "Here are the priorities...", "2025-01-16")
results = search_emails("alice", "budget discussions")
sender_emails = get_emails_from_sender("alice", "bob@acme.com")Implementation (TypeScript)
import MemoryClient from 'mem0ai';
const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
async function storeEmail(userId: string, sender: string, subject: string, body: string, date: string) {
await client.add(
[{ role: 'user', content: `Email from ${sender}: ${subject}\n\n${body}` }],
{ userId: userId, metadata: { email_type: 'incoming', sender, subject, date } }
);
}
async function searchEmails(userId: string, query: string) {
return client.search(query, {
filters: { AND: [{ user_id: userId }, { categories: { contains: 'email' } }] },
topK: 10,
});
}Key Benefits
- Rich metadata enables multi-dimensional queries (sender, date, subject)
- Category filtering separates emails from other memory types
- Semantic search across all email content
Best for: Inbox management, email automation — searchable email memories with metadata filtering.
---
Common Patterns Across Use Cases
Pattern 1: Retrieve → Generate → Store
Every use case follows the same 3-step loop:
# 1. Retrieve relevant context
memories = mem0.search(user_input, user_id=user_id)
context = "\n".join([m["memory"] for m in memories.get("results", [])])
# 2. Generate with context
response = llm.generate(system_prompt=f"Context:\n{context}", user_input=user_input)
# 3. Store the interaction
mem0.add(
[{"role": "user", "content": user_input}, {"role": "assistant", "content": response}],
user_id=user_id
)Pattern 2: Scope with Entity Identifiers
Use user_id, agent_id, app_id, and run_id to isolate memories:
# User-level: personal preferences
client.add(messages, user_id="alice")
# Session-level: conversation within one session
client.add(messages, user_id="alice", run_id="session_123")
# Agent-level: agent-specific knowledge
client.add(messages, agent_id="support_bot", app_id="helpdesk")Pattern 3: Rich Metadata for Filtering
Attach structured metadata for multi-dimensional queries:
# Store with metadata
client.add(messages, user_id="alice", metadata={"priority": "high", "source": "phone_call"})
# Filter by category + metadata
client.search("billing issues", filters={
"AND": [{"user_id": "alice"}, {"categories": {"contains": "billing"}}]
})Pattern 4: Custom Instructions for Domain-Specific Extraction
Control what Mem0 extracts from conversations:
client.project.update(
custom_instructions="Extract medical conditions, medications, and allergies. Exclude billing info."
)---
More Examples
For 30+ cookbooks with complete working code: docs.mem0.ai/cookbooks
Related skills
How it compares
Choose Mem0 over in-prompt context stuffing when agents need durable, retrievable memory across many separate coding sessions.
FAQ
What does mem0 do?
Mem0 Platform SDK for adding persistent memory to AI applications. TRIGGER when: user mentions "mem0", "MemoryClient", "memory layer", "remember user preferences", "persistent context", "personalizati
When should I invoke mem0?
Mem0 Platform SDK for adding persistent memory to AI applications. TRIGGER when: user mentions "mem0", "MemoryClient", "memory layer", "remember user preferences", "persistent context", "personalizati
What are key capabilities?
**Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_id` matches exactly (case-sensitive) and use `filters={"user_
Is Mem0 safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.