# Mem0 — User Guide

Mem0 (pronounced "mem-zero") is a **memory layer for AI agents and applications**. It lets your LLM apps remember facts about users, agents, and conversations across sessions, so they stop forgetting everything the moment a chat ends.

You give Mem0 conversation messages; it uses an LLM to extract the durable facts ("User is allergic to peanuts", "User switched from almond to oat milk"), stores them as searchable memories, and returns the most relevant ones whenever you ask. The result is personalization that persists — without you stuffing an ever-growing transcript into every prompt.

This guide shows you how to install Mem0, store and search memories, scope them to users and agents, and wire Mem0 into real applications using Python, TypeScript, the REST API, or the command line. Configuration reference, deployment, and internals live in the companion **Admin Guide**.

---

## Table of Contents

1. [Quick Start](#1-quick-start)
2. [Choosing Your Path: Platform vs Open Source](#2-choosing-your-path-platform-vs-open-source)
3. [Installation](#3-installation)
4. [Core Concepts](#4-core-concepts)
5. [Everyday Usage: The Memory Operations](#5-everyday-usage-the-memory-operations)
6. [Scoping Memories: Users, Agents, Runs](#6-scoping-memories-users-agents-runs)
7. [Searching and Filtering](#7-searching-and-filtering)
8. [The Open Source Library in Depth](#8-the-open-source-library-in-depth)
9. [The Platform Client in Depth](#9-the-platform-client-in-depth)
10. [The Mem0 CLI](#10-the-mem0-cli)
11. [The LLM Proxy: Memory-Aware Chat in One Call](#11-the-llm-proxy-memory-aware-chat-in-one-call)
12. [The REST API](#12-the-rest-api)
13. [OpenMemory: Your Private Memory Server](#13-openmemory-your-private-memory-server)
14. [Integrations](#14-integrations)
15. [Common Workflows (Recipes)](#15-common-workflows-recipes)
16. [How Mem0 Works (Concepts)](#16-how-mem0-works-concepts)
17. [Troubleshooting](#17-troubleshooting)
18. [Frequently Asked Questions](#18-frequently-asked-questions)
19. [Reference](#19-reference)

---

## 1. Quick Start

The fastest way to see Mem0 work is the managed **Platform**: get an API key, add a memory, search it back.

=== "Python"

    ```bash
    pip install mem0ai
    export MEM0_API_KEY="m0-your-api-key"
    ```

    ```python
    from mem0 import MemoryClient

    client = MemoryClient()  # reads MEM0_API_KEY from the environment

    # Store a conversation — Mem0 extracts the durable facts
    client.add(
        [
            {"role": "user", "content": "I'm vegetarian and allergic to nuts."},
            {"role": "assistant", "content": "Got it — I'll keep that in mind."},
        ],
        user_id="alex",
    )

    # Later, in a different session, recall what matters
    results = client.search("What can I cook for Alex?", filters={"user_id": "alex"})
    for m in results["results"]:
        print(m["memory"])
    ```

    ```text
    Is vegetarian
    Is allergic to nuts
    ```

=== "TypeScript"

    ```bash
    npm install mem0ai
    export MEM0_API_KEY="m0-your-api-key"
    ```

    ```typescript
    import MemoryClient from "mem0ai";

    const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY });

    await client.add(
      [
        { role: "user", content: "I'm vegetarian and allergic to nuts." },
        { role: "assistant", content: "Got it — I'll keep that in mind." },
      ],
      { user_id: "alex" }
    );

    const results = await client.search("What can I cook for Alex?", {
      filters: { user_id: "alex" },
    });
    console.log(results);
    ```

=== "cURL"

    ```bash
    curl -X POST https://api.mem0.ai/v3/memories/add/ \
      -H "Authorization: Token m0-your-api-key" \
      -H "Content-Type: application/json" \
      -d '{
        "messages": [
          {"role": "user", "content": "I am vegetarian and allergic to nuts."}
        ],
        "user_id": "alex"
      }'
    ```

> [!TIP]
> Get a Platform API key from the [Mem0 dashboard](https://app.mem0.ai/dashboard/api-keys). Platform keys start with `m0-`. No infrastructure to run — Mem0 hosts the LLM, embeddings, and vector store for you.

> [!NOTE]
> Prefer to run everything yourself with no external service? Skip to the [Open Source Library](#8-the-open-source-library-in-depth). You only need an OpenAI (or other provider) key and a vector store — Mem0 handles the rest locally.

---

## 2. Choosing Your Path: Platform vs Open Source

Mem0 ships as **one package** with two ways to use it. Pick the one that fits your situation.

| | **Platform** (`MemoryClient`) | **Open Source** (`Memory`) |
|---|---|---|
| Where memories live | Mem0's managed cloud (`api.mem0.ai`) | Your own vector store + database |
| What you provide | A Mem0 API key | LLM key + a vector store |
| Infrastructure to run | None | Vector store (Qdrant, pgvector, etc.) |
| Best for | Shipping fast, scaling without ops | Full data control, on-prem, air-gapped |
| Extra features | Webhooks, exports, projects, feedback, graph memory | Pluggable providers, local-first |
| Import (Python) | `from mem0 import MemoryClient` | `from mem0 import Memory` |
| Import (TS) | `import MemoryClient from "mem0ai"` | `import { Memory } from "mem0ai/oss"` |

> [!IMPORTANT]
> The two share the **same core verbs** — `add`, `search`, `get`, `get_all`, `update`, `delete`, `history` — but their method signatures differ slightly (the Platform client accepts more options like `app_id`, webhooks, and exports). Examples in this guide are labelled so you always know which one you're looking at.

You can start on the Platform and move to self-hosted later (or vice versa); your application code barely changes because the verbs are the same.

---

## 3. Installation

### Requirements

| Requirement | Platform | Open Source |
|---|---|---|
| Python | 3.10+ | 3.10+ |
| Node.js (for TS/JS or CLI) | 18+ | 18+ |
| Mem0 API key | Required | — |
| LLM provider key (e.g. `OPENAI_API_KEY`) | — | Required |
| Vector store | — | Required (Qdrant by default) |

### Python

=== "Platform only"

    ```bash
    pip install mem0ai
    ```

=== "Open Source (with NLP extras)"

    ```bash
    pip install "mem0ai[nlp]"
    python -m spacy download en_core_web_sm
    ```

> [!NOTE]
> The open-source library uses **spaCy** for keyword lemmatization and entity extraction (part of its hybrid search). Installing the `[nlp]` extra and the `en_core_web_sm` model unlocks the full retrieval quality. If spaCy is missing, Mem0 still works — it falls back to semantic-only search.

### TypeScript / JavaScript

```bash
npm install mem0ai
# or
pnpm add mem0ai
# or
yarn add mem0ai
```

The npm package `mem0ai` exposes the Platform client at the root and the open-source implementation under the `mem0ai/oss` subpath:

```typescript
import MemoryClient from "mem0ai";        // Platform
import { Memory } from "mem0ai/oss";        // Open Source
```

### Command Line

```bash
npm install -g mem0ai   # installs the `mem0` command (via @mem0/cli)
```

See [The Mem0 CLI](#10-the-mem0-cli) for usage.

### Setting your keys

=== "macOS / Linux"

    ```bash
    export MEM0_API_KEY="m0-your-api-key"     # Platform
    export OPENAI_API_KEY="sk-..."            # Open Source default LLM/embedder
    ```

=== "Windows (PowerShell)"

    ```powershell
    setx MEM0_API_KEY "m0-your-api-key"
    setx OPENAI_API_KEY "sk-..."
    ```

=== "Python (.env)"

    ```python
    from dotenv import load_dotenv
    load_dotenv()  # loads MEM0_API_KEY / OPENAI_API_KEY from a .env file
    ```

---

## 4. Core Concepts

A handful of ideas appear everywhere in Mem0. Learn them once.

**Memory**
: A single durable fact extracted from conversation, e.g. `"User is allergic to nuts"`. Each memory has an `id`, the `memory` text, a `hash`, timestamps, and any metadata you attached. Memories are stored as vectors so they can be searched by meaning.

**Messages**
: The input you feed `add()`. Either a plain string (`"I love hiking"`) or a list of chat messages (`[{"role": "user", "content": "..."}]`). Mem0 reads these and decides what's worth remembering.

**Inference**
: By default (`infer=True`), Mem0 sends your messages to an LLM that extracts only the memorable facts — not the whole transcript. Set `infer=False` to store messages verbatim with no LLM processing.

**Scope (entity IDs)**
: Every memory belongs to at least one of `user_id`, `agent_id`, or `run_id` (the Platform also supports `app_id`). These keep one user's memories separate from another's. You **must** provide at least one when adding or searching.

**Search**
: A meaning-based lookup. You give a query like `"What does Alex eat?"` and Mem0 returns the most relevant memories, ranked by a hybrid of semantic similarity, keyword matching, and entity overlap.

> [!TIP]
> Think of `add()` as "tell Mem0 what happened" and `search()` as "ask Mem0 what it knows." You typically call `add()` after each conversation turn and `search()` before composing your next LLM prompt.

---

## 5. Everyday Usage: The Memory Operations

Every Mem0 surface — library, client, REST, CLI — exposes the same set of operations. Here they are with the Platform Python client; later sections show the open-source and other variants.

### Add a memory

```python
from mem0 import MemoryClient
client = MemoryClient()

# From a conversation
client.add(
    [
        {"role": "user", "content": "Book me a window seat when I fly."},
        {"role": "assistant", "content": "Noted — window seats going forward."},
    ],
    user_id="alex",
)

# From a single string
client.add("Alex prefers morning meetings", user_id="alex")
```

```text
{'results': [{'id': '0b3f...', 'memory': 'Prefers window seats on flights', 'event': 'ADD'},
             {'id': '7a21...', 'memory': 'Prefers morning meetings', 'event': 'ADD'}]}
```

Each result carries an `event` describing what happened: `ADD` (new memory created), and on the Platform `UPDATE`/`DELETE`/`NONE` when an incoming fact revises or duplicates an existing one.

### Search memories

```python
results = client.search("travel preferences", filters={"user_id": "alex"})
for m in results["results"]:
    print(m["memory"], "→ score", round(m["score"], 3))
```

```text
Prefers window seats on flights → score 0.71
```

### Get all memories for a scope

```python
all_mem = client.get_all(filters={"user_id": "alex"}, page=1, page_size=50)
print(all_mem["results"])
```

### Get one memory by ID

```python
mem = client.get("0b3f...")
print(mem["memory"])
```

### Update a memory

```python
client.update("0b3f...", text="Prefers aisle seats on long flights")
```

```text
{'message': 'Memory updated successfully!'}
```

### Delete a memory

```python
client.delete("0b3f...")
```

```text
{'message': 'Memory deleted successfully!'}
```

### Delete all memories for a scope

```python
client.delete_all(user_id="alex")
```

> [!CAUTION]
> `delete_all()` removes **every** memory matching the filter you pass. There is no undo. To wipe everything for the whole account/instance, use `reset()` instead — and be equally careful.

### View a memory's history

```python
for change in client.history("0b3f..."):
    print(change["event"], change.get("old_memory"), "→", change.get("new_memory"))
```

```text
ADD None → Prefers window seats on flights
UPDATE Prefers window seats on flights → Prefers aisle seats on long flights
```

> [!NOTE]
> History is an audit trail of how a memory changed over time — when it was added, updated, or deleted. It's invaluable for debugging "why does the agent think X?"

---

## 6. Scoping Memories: Users, Agents, Runs

Scope is how Mem0 keeps memories from leaking between people, agents, and sessions. You must always supply at least one scope identifier.

| Scope ID | Meaning | Typical use |
|---|---|---|
| `user_id` | An end user / person | "What does this customer like?" |
| `agent_id` | An AI agent identity | An agent's own learned behaviors and config |
| `run_id` | A single session / conversation run | Short-lived, per-conversation memory |
| `app_id` | An application (Platform only) | Group memory by product or app |

### Per-user memory (most common)

```python
client.add(messages, user_id="alex")
client.search("preferences", filters={"user_id": "alex"})
```

### Agent memory

When you add messages that include **assistant** turns and pass an `agent_id`, Mem0 can extract facts about the agent itself (its recommendations, configured behaviors, learned style):

```python
client.add(
    [
        {"role": "user", "content": "Be concise from now on."},
        {"role": "assistant", "content": "Understood — I'll keep answers short."},
    ],
    agent_id="support-bot",
)
```

### Combining scopes

You can scope to several IDs at once to narrow precisely:

```python
client.add(messages, user_id="alex", agent_id="support-bot", run_id="ticket-8842")
client.search("open issues", filters={"user_id": "alex", "run_id": "ticket-8842"})
```

> [!IMPORTANT]
> In **`search()` and `get_all()`**, entity IDs must go *inside* `filters={...}`, not as top-level arguments. `client.search(query, user_id="alex")` raises an error in current versions; use `client.search(query, filters={"user_id": "alex"})`. In **`add()`** and **`delete_all()`**, they remain top-level arguments (`user_id="alex"`). This split is deliberate — it keeps "where to store" separate from "what to query."

---

## 7. Searching and Filtering

Search is where Mem0 earns its keep. Beyond a plain query, you can filter on metadata, use comparison operators, and combine conditions with boolean logic.

### Basic search

```python
client.search("dietary restrictions", filters={"user_id": "alex"})
```

### Limit results and set a threshold

```python
client.search(
    "favorite foods",
    filters={"user_id": "alex"},
    top_k=5,           # return at most 5 memories
    threshold=0.3,     # drop matches below this similarity score (0–1)
)
```

### Metadata filters with operators

When you store memories with custom metadata, you can filter on it using rich operators. Pass the operator as a nested dict:

```python
# Memories tagged with a category, created this year, excluding archived ones
client.search(
    "project notes",
    filters={
        "user_id": "alex",
        "category": {"in": ["work", "planning"]},
        "year": {"gte": 2026},
        "status": {"ne": "archived"},
    },
)
```

Supported operators (open-source and Platform):

| Operator | Meaning | Example |
|---|---|---|
| `eq` | equals | `{"tier": {"eq": "pro"}}` |
| `ne` | not equals | `{"status": {"ne": "archived"}}` |
| `gt` / `gte` | greater than / or equal | `{"year": {"gte": 2026}}` |
| `lt` / `lte` | less than / or equal | `{"score": {"lte": 5}}` |
| `in` | value in list | `{"tag": {"in": ["a", "b"]}}` |
| `nin` | value not in list | `{"tag": {"nin": ["spam"]}}` |
| `contains` | substring match | `{"note": {"contains": "urgent"}}` |
| `icontains` | case-insensitive substring | `{"note": {"icontains": "Urgent"}}` |
| `"*"` | wildcard (any value present) | `{"category": "*"}` |

### Boolean logic: AND / OR / NOT

```python
client.search(
    "travel",
    filters={
        "user_id": "alex",
        "OR": [
            {"category": "flights"},
            {"category": "hotels"},
        ],
        "NOT": [{"status": "cancelled"}],
    },
)
```

> [!TIP]
> Keep `user_id`/`agent_id`/`run_id` at the top level of `filters` even when you use `AND`/`OR`/`NOT` — those entity IDs always scope the search, while the boolean blocks refine within that scope.

### Reranking for higher precision

Set `rerank=True` to re-score the top candidates with a dedicated reranker model for sharper ordering (slower, but more accurate):

```python
client.search("what to pack for the trip", filters={"user_id": "alex"}, rerank=True)
```

> [!NOTE]
> On the open-source library, reranking requires you to configure a reranker provider (Cohere, a sentence-transformer model, etc.) — see the Admin Guide. On the Platform, `rerank=True` just works.

---

## 8. The Open Source Library in Depth

The open-source `Memory` class runs entirely on your own infrastructure. You bring an LLM, an embedder, and a vector store; Mem0 orchestrates extraction, storage, and hybrid retrieval locally.

### Zero-config start (Python)

With just `OPENAI_API_KEY` set, the defaults give you OpenAI for extraction and embeddings plus a local Qdrant store:

```python
from mem0 import Memory

m = Memory()  # uses default config

m.add(
    [{"role": "user", "content": "I run every morning before work."}],
    user_id="alex",
)

print(m.search("exercise habits", filters={"user_id": "alex"}))
```

```text
{'results': [{'id': '...', 'memory': 'Runs every morning before work',
              'score': 0.62, 'created_at': '2026-06-03T...', 'updated_at': '...'}]}
```

### The full open-source API

| Method | Signature | Returns |
|---|---|---|
| `add` | `add(messages, *, user_id=None, agent_id=None, run_id=None, metadata=None, infer=True, memory_type=None, prompt=None)` | `{"results": [...]}` |
| `search` | `search(query, *, top_k=20, filters=None, threshold=0.1, rerank=False)` | `{"results": [...]}` |
| `get` | `get(memory_id)` | memory dict or `None` |
| `get_all` | `get_all(*, filters=None, top_k=20)` | `{"results": [...]}` |
| `update` | `update(memory_id, data, metadata=None)` | `{"message": "..."}` |
| `delete` | `delete(memory_id)` | `{"message": "..."}` |
| `delete_all` | `delete_all(user_id=None, agent_id=None, run_id=None)` | `{"message": "..."}` |
| `history` | `history(memory_id)` | list of change records |
| `reset` | `reset()` | `None` (wipes the store) |
| `close` | `close()` | releases DB connections |

> [!IMPORTANT]
> In the open-source `search()` and `get_all()`, the entity IDs go inside `filters`, and at least one of `user_id`/`agent_id`/`run_id` is **required**. Passing `user_id="alex"` as a top-level keyword to `search()` raises a `ValueError` telling you to use `filters={"user_id": "alex"}` instead.

### Storing raw messages without inference

```python
m.add(
    [{"role": "user", "content": "Order #4471 shipped on 2026-06-01"}],
    user_id="alex",
    infer=False,   # store the message text directly, skip LLM extraction
)
```

> [!TIP]
> Use `infer=False` for structured records you want stored verbatim (order numbers, logs, IDs) where you don't want an LLM paraphrasing them. Use the default `infer=True` for natural conversation where you want clean, deduplicated facts.

### Async usage

Every method has an async twin via `AsyncMemory`:

```python
import asyncio
from mem0 import AsyncMemory

async def main():
    m = await asyncio.to_thread(AsyncMemory)
    await m.add([{"role": "user", "content": "I prefer dark mode"}], user_id="alex")
    print(await m.search("ui preferences", filters={"user_id": "alex"}))

asyncio.run(main())
```

### Configuring providers

`Memory.from_config()` takes a plain dict that selects your LLM, embedder, and vector store:

```python
from mem0 import Memory

config = {
    "llm": {"provider": "anthropic", "config": {"model": "claude-sonnet-4-5", "temperature": 0.1}},
    "embedder": {"provider": "openai", "config": {"model": "text-embedding-3-small"}},
    "vector_store": {"provider": "qdrant", "config": {"host": "localhost", "port": 6333}},
}
m = Memory.from_config(config)
```

The library supports a broad provider matrix out of the box:

- **LLMs:** OpenAI, Anthropic, Gemini, Groq, Together, AWS Bedrock, Azure OpenAI, DeepSeek, MiniMax, xAI, Sarvam, Ollama, LM Studio, vLLM, LiteLLM, LangChain.
- **Embedders:** OpenAI, Ollama, Hugging Face, Azure OpenAI, Gemini, Vertex AI, Together, LM Studio, AWS Bedrock, FastEmbed, LangChain.
- **Vector stores:** Qdrant, Chroma, pgvector, Milvus, Pinecone, Redis, Valkey, Weaviate, FAISS, Elasticsearch, OpenSearch, MongoDB, Supabase, Azure AI Search, Databricks, Vertex AI Vector Search, Upstash, S3 Vectors, Cassandra, Baidu, Neptune Analytics, Turbopuffer, plus Azure MySQL.

> [!NOTE]
> The exact config keys for each provider (hosts, models, API-base overrides, environment variables) are catalogued in the **Admin Guide → Configuration Reference**. As a user, you mainly need to know that switching providers is a one-line change in the config dict.

### TypeScript open-source

```typescript
import { Memory } from "mem0ai/oss";

const memory = new Memory({
  embedder: { provider: "openai", config: { apiKey: process.env.OPENAI_API_KEY } },
  llm: { provider: "openai", config: { apiKey: process.env.OPENAI_API_KEY, model: "gpt-4o" } },
  vectorStore: { provider: "memory", config: { collectionName: "memories" } },
});

await memory.add("The sky is blue", "alex");
const results = await memory.search("What color is the sky?", "alex");
```

> [!NOTE]
> The TypeScript open-source build ships with sensible defaults (OpenAI embeddings + GPT-4 + an in-memory vector store + SQLite history), so a `new Memory()` with just an API key works for quick experiments. Production deployments should pick a persistent vector store (pgvector, Qdrant, Redis).

---

## 9. The Platform Client in Depth

The Platform client (`MemoryClient` / `AsyncMemoryClient`) talks to Mem0's hosted API. Beyond the core verbs, it unlocks features that need server-side infrastructure.

### Initialization

```python
from mem0 import MemoryClient

client = MemoryClient(api_key="m0-...")        # or rely on MEM0_API_KEY env var
# Custom host (e.g. EU region or self-hosted Platform):
client = MemoryClient(api_key="m0-...", host="https://api.mem0.ai")
```

```typescript
import MemoryClient from "mem0ai";
const client = new MemoryClient({ apiKey: "m0-..." });
```

### Platform-only capabilities

**Batch operations** — update or delete many memories in one call:

```python
client.batch_update([
    {"memory_id": "id-1", "text": "Updated fact one"},
    {"memory_id": "id-2", "metadata": {"reviewed": True}},
])
client.batch_delete([{"memory_id": "id-1"}, {"memory_id": "id-2"}])
```

**Entities (users/agents/runs)** — list and manage every entity that has memories:

```python
client.users()                       # all users, agents, runs with memories
client.delete_users(user_id="alex")  # delete a specific entity's footprint
```

**Memory exports** — request a structured export defined by a JSON schema:

```python
client.create_memory_export(schema=my_json_schema, user_id="alex")
export = client.get_memory_export(user_id="alex")
```

**Summaries** — get a narrative summary of a user's memories:

```python
client.get_summary(filters={"user_id": "alex"})
```

**Feedback** — tell Mem0 a retrieved memory was good or bad to improve future results:

```python
client.feedback(memory_id="id-1", feedback="POSITIVE")
client.feedback(memory_id="id-2", feedback="NEGATIVE", feedback_reason="outdated")
```

Valid feedback values: `POSITIVE`, `NEGATIVE`, `VERY_NEGATIVE`.

**Webhooks** — get notified when memories change:

```python
client.create_webhook(
    url="https://example.com/hooks/mem0",
    name="memory-events",
    project_id="proj_123",
    event_types=["memory.add", "memory.update"],
)
client.get_webhooks(project_id="proj_123")
```

**Projects** — manage project-wide settings like custom instructions and categories:

```python
client.project.update(
    custom_instructions="Focus on travel preferences and dietary restrictions.",
    custom_categories=["travel", "food", "work"],
)
```

> [!TIP]
> **Custom instructions** steer what the extraction LLM remembers. If your app only cares about, say, support-ticket context, set instructions accordingly and Mem0 will stop storing irrelevant chit-chat — improving precision and lowering noise.

**Deleting superseded memories** — when a newer memory supersedes an older one, delete the whole chain at once:

```python
client.delete("id-current", delete_linked=True)
```

### Async Platform client

```python
import asyncio
from mem0 import AsyncMemoryClient

async def main():
    async with AsyncMemoryClient() as client:
        await client.add("I love jazz", user_id="alex")
        print(await client.search("music taste", filters={"user_id": "alex"}))

asyncio.run(main())
```

---

## 10. The Mem0 CLI

The `mem0` command brings memory to your terminal and to coding agents. It talks to the Mem0 Platform.

### Setup

```bash
npm install -g mem0ai
mem0 init            # interactive: paste your API key or log in via email
```

`init` writes config to `~/.mem0/config.json` (permissions `0600`). You can also pass flags:

```bash
mem0 init --api-key m0-... --user-id alex
mem0 init --email [email removed]   # login via emailed verification code
```

### Core commands

```bash
# Add memory (string or piped messages)
mem0 add "I prefer TypeScript over JavaScript" --user-id alex
mem0 add --file conversation.json --user-id alex

# Search
mem0 search "language preferences" --user-id alex
mem0 search "preferences" --user-id alex --output table

# Retrieve / list
mem0 get <memoryId>
mem0 list --user-id alex --page 1

# Update / delete
mem0 update <memoryId> "Now prefers Rust"
mem0 delete <memoryId>
mem0 delete --all --user-id alex --confirm   # wipe a user's memories
mem0 delete --all --user-id alex --dry-run   # preview what would be deleted

# Import a JSON export
mem0 import memories.json --user-id alex

# Status & config
mem0 status
mem0 whoami
mem0 config show
mem0 config get platform.base_url
mem0 config set defaults.user_id alex
```

### Add options worth knowing

| Flag | Effect |
|---|---|
| `--user-id`, `--agent-id`, `--app-id`, `--run-id` | Scope the memory |
| `--metadata <json>` | Attach custom metadata |
| `--immutable` | Prevent the memory from being updated later |
| `--no-infer` | Store raw, skip LLM extraction |
| `--expires <YYYY-MM-DD>` | Auto-expire the memory |
| `--categories <list>` | Tag with categories (JSON array or comma-separated) |
| `--output <format>` | `text`, `json`, or `quiet` |

### Search options

| Flag | Effect |
|---|---|
| `--rerank` | Enable reranking (Platform) |
| `--keyword` | Use keyword search |
| `--filter <json>` | Advanced filter expression |
| `--fields <list>` | Return only specific fields |
| `--output <format>` | `text`, `json`, or `table` |

### Agent / scripting mode

Every command accepts a global `--json` flag that emits a machine-readable envelope, ideal for use inside AI coding agents and scripts:

```bash
mem0 search "preferences" --user-id alex --json
```

```text
{"status":"ok","command":"search","data":{"results":[ ... ]}}
```

> [!TIP]
> The CLI auto-detects when it's running inside an AI coding assistant (Claude Code, Cursor, Codex, Cline, Continue, Aider, Goose, Windsurf) and switches to a quiet, JSON-friendly "agent mode" so its output is easy to parse. Set `NO_COLOR=1` to disable ANSI colors anywhere.

### CLI environment variables

| Variable | Purpose |
|---|---|
| `MEM0_API_KEY` | API key (overrides config file) |
| `MEM0_BASE_URL` | API base URL |
| `MEM0_USER_ID` / `MEM0_AGENT_ID` / `MEM0_APP_ID` / `MEM0_RUN_ID` | Default scope IDs |
| `NO_COLOR` | Disable colored output |

---

## 11. The LLM Proxy: Memory-Aware Chat in One Call

The Mem0 **proxy** wraps an OpenAI-compatible chat completion so memory retrieval and storage happen automatically — you make a normal chat call, and Mem0 injects relevant memories into the prompt and saves new ones in the background.

```python
from mem0.proxy.main import Mem0

# Use the Platform...
mem0_chat = Mem0(api_key="m0-...")
# ...or the open-source library:
# mem0_chat = Mem0(config={"vector_store": {...}, "llm": {...}})

response = mem0_chat.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "What restaurant should I book tonight?"}],
    user_id="alex",
)
print(response.choices[0].message.content)
```

What happens under the hood:

1. Mem0 searches the user's memories using the last few messages as the query.
2. It injects the relevant memories into a system prompt.
3. It calls the model (via LiteLLM, so any supported model works).
4. In a background thread, it stores the new turn as memory.

> [!NOTE]
> The proxy requires a model that supports function calling and at least one of `user_id`, `agent_id`, or `run_id`. It installs `litellm` on first use if it isn't already present.

> [!TIP]
> The proxy is the lowest-effort way to add memory to an existing chatbot: replace your `openai.chat.completions.create(...)` with `mem0.chat.completions.create(..., user_id=...)` and you instantly get personalization across sessions.

---

## 12. The REST API

If you self-host the Mem0 **REST server** (see [Admin Guide → Deployment]), or want to call the Platform over HTTP directly, the memory operations are available as plain HTTP endpoints.

### Self-hosted server endpoints

| Method | Path | Purpose |
|---|---|---|
| `POST` | `/memories` | Create memories |
| `GET` | `/memories` | List memories (optionally filtered by `user_id`/`agent_id`/`run_id`) |
| `GET` | `/memories/{memory_id}` | Get one memory |
| `POST` | `/search` | Search memories |
| `PUT` | `/memories/{memory_id}` | Update a memory |
| `GET` | `/memories/{memory_id}/history` | Memory change history |
| `DELETE` | `/memories/{memory_id}` | Delete a memory |
| `DELETE` | `/memories` | Delete all for a scope |
| `POST` | `/reset` | Reset all memories |
| `GET`/`POST` | `/configure` | View / set the runtime config |

### Example: add and search over HTTP

```bash
# Add
curl -X POST http://localhost:8000/memories \
  -H "X-API-Key: $MEM0_KEY" \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"I love spicy food"}],"user_id":"alex"}'
```

```bash
# Search
curl -X POST http://localhost:8000/search \
  -H "X-API-Key: $MEM0_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"food preferences","filters":{"user_id":"alex"}}'
```

> [!IMPORTANT]
> On `/search`, pass entity IDs inside `filters` (e.g. `"filters": {"user_id": "alex"}`). Passing `user_id` at the top level still works but is deprecated and logs a warning. The self-hosted server's interactive API docs live at `/docs` (Swagger UI) once it's running.

### Platform HTTP API

The Platform exposes versioned endpoints under `https://api.mem0.ai` (e.g. `POST /v3/memories/add/`, `POST /v3/memories/search/`, `GET /v1/memories/{id}/`). Authenticate with `Authorization: Token m0-your-api-key`. Most users reach these through the SDKs rather than raw HTTP.

---

## 13. OpenMemory: Your Private Memory Server

**OpenMemory** is a self-hosted, Dockerized memory server with a web dashboard and a built-in **MCP (Model Context Protocol) server**, so MCP-aware clients (Claude Desktop, Cursor, etc.) can read and write your memories. Everything stays on your machine.

### One-line install

```bash
curl -sL https://raw.githubusercontent.com/mem0ai/mem0/main/openmemory/run.sh \
  | OPENAI_API_KEY=your_api_key bash
```

This script:

- Verifies Docker and Docker Compose are installed.
- Picks a vector store (default **Qdrant**; override with `VECTOR_STORE=...` — `qdrant`, `chroma`, `pgvector`, `redis`, `weaviate`, `milvus`, `elasticsearch`, `faiss`).
- Starts the backend API on **`http://localhost:8765`** and the dashboard UI on **`http://localhost:3000`** (next free port up to 3010).

```bash
# Choose a different vector store
curl -sL .../openmemory/run.sh | OPENAI_API_KEY=sk-... VECTOR_STORE=pgvector bash
```

### What you get

- A web UI to browse, search, create, and delete your memories and connected apps.
- An MCP endpoint (`/{client}/sse/{user_id}`) you can register in any MCP client to give it long-term memory.
- Your memories stored locally in the vector store of your choice.

> [!TIP]
> OpenMemory is the best fit if you want a *personal* memory layer shared across all your AI tools, fully under your control, without sending data to a managed service. The only external dependency is the LLM/embedding provider key you supply (OpenAI by default).

---

## 14. Integrations

Mem0 plugs into the popular AI app frameworks. The pattern is always the same: search memories before the model call, add memories after.

| Integration | Package / entry point | Notes |
|---|---|---|
| **Vercel AI SDK** | `@mem0/vercel-ai-provider` | Drop-in provider that adds memory to AI SDK apps |
| **OpenAI Agents / tools** | `mem0ai` + OpenAI SDK | Use Mem0 as a tool the agent can call |
| **LangChain / LangGraph** | `@mem0/community` (`mem0ai/community/langchain`) | Memory-backed chains and graphs |
| **CrewAI, LlamaIndex, AutoGen** | `mem0ai` | Search/add around agent steps |
| **OpenClaw** | `@mem0/openclaw-mem0` | Mem0 memory backend for OpenClaw, platform or self-hosted |
| **Claude Code** | Mem0 plugin (`/plugin install mem0@mem0-plugins`) | Skills that add, search, and manage memory from Claude |

### Vercel AI SDK example

```typescript
import { createMem0 } from "@mem0/vercel-ai-provider";
import { generateText } from "ai";

const mem0 = createMem0({ apiKey: process.env.MEM0_API_KEY });

const { text } = await generateText({
  model: mem0("gpt-4o", { user_id: "alex" }),
  prompt: "Recommend a dinner spot for me.",
});
```

### Mem0 as an OpenAI tool

Expose `search`/`add` as tools your agent can call, then let the model decide when to remember or recall. The `examples/openai-inbuilt-tools` directory in the repo shows a complete pattern.

> [!NOTE]
> Each integration ships runnable examples in the `examples/` directory of the repository (multimodal chat, Vercel chat app, graph-DB demo, YouTube assistant Chrome extension, healthcare assistant, and more). They're the quickest way to see an end-to-end app.

---

## 15. Common Workflows (Recipes)

### Recipe: Personalized chatbot

```python
from mem0 import MemoryClient
client = MemoryClient()

def chat(user_id, user_message, llm_call):
    # 1. Recall
    memories = client.search(user_message, filters={"user_id": user_id}, top_k=5)
    context = "\n".join(m["memory"] for m in memories["results"])

    # 2. Compose prompt with memory context
    system = f"You are a helpful assistant. What you know about the user:\n{context}"
    reply = llm_call(system=system, user=user_message)

    # 3. Remember this turn
    client.add(
        [{"role": "user", "content": user_message},
         {"role": "assistant", "content": reply}],
        user_id=user_id,
    )
    return reply
```

### Recipe: Long-running agent that learns

```python
# Store agent-level lessons that persist across runs
client.add(
    [{"role": "assistant", "content": "When the user asks for code, default to Python."}],
    agent_id="dev-helper",
)
# Recall them at the start of each run
lessons = client.search("coding defaults", filters={"agent_id": "dev-helper"})
```

### Recipe: Per-session scratch memory that you clean up

```python
run_id = "session-2026-06-03-001"
client.add(messages, user_id="alex", run_id=run_id)
# ...use it during the session...
client.delete_all(user_id="alex", run_id=run_id)  # tidy up when done
```

### Recipe: Tagging and filtered recall

```python
client.add("Prefers Delta for transatlantic flights", user_id="alex",
           metadata={"category": "travel", "confidence": "high"})

client.search("airline preference", filters={
    "user_id": "alex",
    "category": "travel",
    "confidence": {"in": ["high", "verified"]},
})
```

### Recipe: Bulk import existing user data

```python
# infer=False stores facts verbatim — good for migrating known facts
for fact in known_user_facts:
    client.add(fact, user_id="alex", infer=False)
```

> [!TIP]
> A reliable pattern for production chatbots: **search before every model call**, **add after every model call**, and keep `top_k` modest (3–7). This keeps prompts small while still surfacing the facts that matter.

---

## 16. How Mem0 Works (Concepts)

You don't need this section to use Mem0, but understanding the pipeline helps you debug and tune it.

### What happens on `add()`

When you add a conversation with inference enabled, Mem0 runs a multi-phase pipeline:

1. **Context gathering** — pulls the recent messages for this scope to resolve pronouns and references.
2. **Existing-memory retrieval** — embeds your messages and finds related memories already stored.
3. **LLM extraction** — a single LLM call extracts self-contained, contextually rich facts from both user *and* assistant messages, deduplicating against what's already known and linking related memories.
4. **Embedding & dedup** — each extracted fact is embedded; exact duplicates (by content hash) are skipped.
5. **Storage** — new memories are written to the vector store, with a history record for each.
6. **Entity linking** — named entities (people, places, titles) are extracted and linked so future searches can boost memories about the same entity.

The extraction model is careful: it preserves proper nouns, exact numbers, and dates; grounds relative time references ("last week") to absolute dates; never fabricates; and captures emotional and motivational context, not just bare facts.

### What happens on `search()`

The open-source library uses **hybrid retrieval** that blends three signals:

1. **Semantic search** — vector similarity between your query and stored memories.
2. **Keyword (BM25) search** — lexical matching using lemmatized text, so "running" matches "ran".
3. **Entity boosting** — memories linked to entities mentioned in your query get a relevance boost.

These signals are combined into a single normalized score, filtered by your `threshold`, and ranked. Optionally a **reranker** model re-orders the top results for maximum precision.

> [!NOTE]
> This is why installing the spaCy NLP extras matters for the open-source library: keyword matching and entity boosting both rely on spaCy. Without it, you still get semantic search, just not the full hybrid quality.

### Memory types

| Type | How to create | Use |
|---|---|---|
| Factual / conversational (default) | `add(messages, user_id=...)` | Everyday user/agent facts |
| Procedural | `add(messages, agent_id=..., memory_type="procedural_memory")` | A detailed summary of an agent's step-by-step execution history |

### Where data lives (open source)

- **Memories (vectors):** your chosen vector store.
- **History (audit trail):** a local SQLite database at `~/.mem0/history.db` by default.
- **Working directory:** `~/.mem0/` (override with the `MEM0_DIR` environment variable).

---

## 17. Troubleshooting

### Error: `Mem0 API Key not provided. Please provide an API Key.`

**Cause:** The Platform client couldn't find an API key.
**Solution:** Set `MEM0_API_KEY` in your environment or pass `MemoryClient(api_key="m0-...")`.
**Prevention:** Keep the key in a `.env` file loaded at startup; never hard-code it in source.

### Error: `filters must contain at least one of: user_id, agent_id, run_id.`

**Cause:** You called `search()` or `get_all()` without a scope inside `filters`.
**Solution:** Add a scope, e.g. `search(query, filters={"user_id": "alex"})`.
**Prevention:** Always decide a memory's scope up front; treat scope as required.

### Error: `Top-level entity parameters {...} are not supported in search()/get_all(). Use filters={'user_id': '...'} instead.`

**Cause:** You passed `user_id`/`agent_id`/`run_id`/`app_id` as a top-level keyword to `search()` or `get_all()`.
**Solution:** Move them inside `filters={...}`.
**Prevention:** Remember the rule — top-level on `add()`/`delete_all()`, inside `filters` on `search()`/`get_all()`.

### Error: `Invalid threshold: ... Must be between 0 and 1`

**Cause:** `threshold` was outside the `[0, 1]` range, or `top_k` was negative.
**Solution:** Use a `threshold` between 0 and 1 (default `0.1`) and a non-negative integer `top_k`.

### Error: `Invalid 'memory_type'. Please pass procedural_memory ...`

**Cause:** You passed a `memory_type` other than `"procedural_memory"`.
**Solution:** Only `"procedural_memory"` is supported; omit `memory_type` for normal memories.

### Search returns nothing even though you added memories

**Cause:** Usually a scope mismatch (added under one `user_id`, searched under another), or the `threshold` is too high.
**Solution:** Confirm you're searching the same scope you added to; lower `threshold` (try `0.1` or `0`); call `get_all(filters={"user_id": ...})` to confirm the memories exist.
**Prevention:** Standardize your scope IDs across add and search.

### Open-source search quality feels weak / "spaCy is not installed"

**Cause:** The spaCy NLP model isn't installed, so keyword and entity signals are disabled.
**Solution:** `pip install "mem0ai[nlp]"` then `python -m spacy download en_core_web_sm`.
**Prevention:** Install the NLP extras as part of your environment setup.

### `add()` returns an empty `results` list

**Cause:** The extraction LLM found nothing worth remembering (e.g. pure greetings), or all extracted facts were duplicates of existing memories.
**Solution:** This is expected for non-informational messages. Verify with content that contains real facts; check `get_all()` to see what's already stored.

### Self-hosted server returns `401 Authentication required`

**Cause:** The server has auth enabled but no credentials were supplied.
**Solution:** Pass a valid `X-API-Key` or Bearer token; for local development only, the operator can set `AUTH_DISABLED=true`. See the Admin Guide for auth setup.

### Self-hosted server: `LLM provider 'X' is not bundled in this image`

**Cause:** You configured a provider whose Python package isn't included in the prebuilt server image.
**Solution:** The default server image bundles OpenAI, Anthropic, and Gemini (LLM) and OpenAI/Gemini (embedder). To use another, the operator must install its package and rebuild — see the Admin Guide.

### Rate limit / provider errors (`provider_rate_limited`, `provider_timeout`)

**Cause:** The upstream LLM/embedding provider throttled or timed out.
**Solution:** Retry with backoff; on the Platform, catch `RateLimitError` and wait. Reduce request volume or upgrade your provider tier.

---

## 18. Frequently Asked Questions

**Q: Do I need to choose Platform or Open Source forever?**
No. They share the same verbs, so you can prototype on the Platform and self-host later (or run both). Your `add`/`search` calls barely change.

**Q: What does Mem0 actually store — the whole conversation?**
By default, no. With `infer=True` it stores only the extracted facts (e.g. "Is vegetarian"), not the raw transcript. Use `infer=False` if you want messages stored verbatim.

**Q: Which LLM and embedder does the open-source library use by default?**
OpenAI for both — a chat model for extraction and `text-embedding-3-small` for embeddings — with a local Qdrant vector store. You only need `OPENAI_API_KEY` set. Swap any of them via config.

**Q: Can I run Mem0 fully offline / air-gapped?**
Yes — use the open-source library with local providers like **Ollama** (LLM + embeddings) and a local vector store (Qdrant, FAISS, pgvector). No data leaves your machine.

**Q: How is a memory different from just logging the chat?**
A memory is a deduplicated, self-contained fact that's been reconciled against what's already known (added, updated, or skipped as a duplicate) and made searchable by meaning. Raw logs aren't searchable by meaning and grow without bound.

**Q: How do I keep one user's memories from leaking to another?**
Always scope with `user_id` (and/or `agent_id`/`run_id`). Searches only return memories matching the scope in `filters`. Two users with different `user_id`s never see each other's memories.

**Q: What's the difference between `delete_all()` and `reset()`?**
`delete_all()` removes memories for a specific scope (a user, agent, or run). `reset()` wipes the *entire* store and recreates it. Both are irreversible.

**Q: Can I attach my own metadata and filter on it?**
Yes. Pass `metadata={...}` on `add()`, then filter with operators (`eq`, `in`, `gte`, `contains`, etc.) and boolean logic (`AND`/`OR`/`NOT`) on `search()`.

**Q: Does search use embeddings only?**
The open-source library uses **hybrid** retrieval: semantic similarity + BM25 keyword matching + entity boosting, combined into one score. Optionally a reranker sharpens the top results.

**Q: What is "procedural memory"?**
A special memory type for agents: a detailed, verbatim-preserving summary of an agent's step-by-step execution history. Create it with `memory_type="procedural_memory"` and an `agent_id`.

**Q: Can I use Mem0 from the command line or inside a coding agent?**
Yes. The `mem0` CLI provides every operation, auto-detects coding-agent environments, and offers a `--json` mode for scripting.

**Q: Is there a way to add memory to my chatbot without rewriting it?**
Use the **LLM proxy** (`mem0.proxy.main.Mem0`). Swap your `chat.completions.create(...)` call for the proxy's and pass a `user_id` — memory retrieval and storage become automatic.

**Q: How do I see why the agent "knows" something?**
Call `history(memory_id)` to see the full add/update/delete trail of any memory.

**Q: Does Mem0 collect telemetry?**
The open-source library and self-hosted server send anonymous usage telemetry by default. Opt out by setting `MEM0_TELEMETRY=false`.

---

## 19. Reference

### Memory operations (at a glance)

| Operation | Open Source (`Memory`) | Platform (`MemoryClient`) |
|---|---|---|
| Add | `add(messages, user_id=...)` | `add(messages, user_id=...)` |
| Search | `search(q, filters={...})` | `search(q, filters={...})` |
| Get one | `get(memory_id)` | `get(memory_id)` |
| Get all | `get_all(filters={...})` | `get_all(filters={...})` |
| Update | `update(memory_id, data)` | `update(memory_id, text=...)` |
| Delete | `delete(memory_id)` | `delete(memory_id, delete_linked=...)` |
| Delete all | `delete_all(user_id=...)` | `delete_all(user_id=...)` |
| History | `history(memory_id)` | `history(memory_id)` |
| Reset | `reset()` | `reset()` |
| Batch update/delete | — | `batch_update([...])`, `batch_delete([...])` |
| Entities | — | `users()`, `delete_users(...)` |
| Exports / summary | — | `create_memory_export(...)`, `get_summary(...)` |
| Feedback | — | `feedback(memory_id, "POSITIVE")` |

### Key environment variables (user-facing)

| Variable | Used by | Purpose |
|---|---|---|
| `MEM0_API_KEY` | Platform client, CLI | Authenticate with the Mem0 Platform |
| `OPENAI_API_KEY` | Open source (default) | Default LLM + embeddings |
| `MEM0_DIR` | Open source | Working dir for history DB (default `~/.mem0`) |
| `MEM0_TELEMETRY` | Open source, server | Set `false` to opt out of anonymous telemetry |
| `MEM0_BASE_URL` | CLI | Override the API base URL |
| `MEM0_USER_ID` / `MEM0_AGENT_ID` / `MEM0_APP_ID` / `MEM0_RUN_ID` | CLI | Default scope IDs |
| `NO_COLOR` | CLI | Disable colored output |

### Packages

| Package | Ecosystem | What it is |
|---|---|---|
| `mem0ai` | PyPI | Python library (Platform + Open Source) |
| `mem0ai` | npm | TypeScript SDK (`mem0ai` = Platform, `mem0ai/oss` = Open Source) |
| `@mem0/cli` | npm | The `mem0` command-line tool |
| `@mem0/vercel-ai-provider` | npm | Vercel AI SDK provider |
| `@mem0/community` | npm | Community integrations (LangChain) |
| `@mem0/openclaw-mem0` | npm | OpenClaw memory backend |

### Supported providers (open source)

- **LLMs:** OpenAI, Anthropic, Gemini, Groq, Together, AWS Bedrock, Azure OpenAI, DeepSeek, MiniMax, xAI, Sarvam, Ollama, LM Studio, vLLM, LiteLLM, LangChain.
- **Embedders:** OpenAI, Ollama, Hugging Face, Azure OpenAI, Gemini, Vertex AI, Together, LM Studio, AWS Bedrock, FastEmbed, LangChain.
- **Vector stores:** Qdrant, Chroma, pgvector, Milvus, Pinecone, Redis, Valkey, Weaviate, FAISS, Elasticsearch, OpenSearch, MongoDB, Supabase, Azure AI Search, Databricks, Vertex AI Vector Search, Upstash, S3 Vectors, Cassandra, Baidu, Neptune Analytics, Turbopuffer, Azure MySQL.
- **Rerankers:** Cohere, sentence-transformer, ZeroEntropy, LLM-based, Hugging Face.

### Where to go next

- **Configuration reference, deployment, security, internals** → the companion **Mem0 Admin Guide**.
- **Runnable examples** → the `examples/` directory in the repository.
- **Official documentation** → [docs.mem0.ai](https://docs.mem0.ai).

---

_Generated June 2026 from mem0ai/mem0 at 74771b4. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
