# Mem0 — Admin & Developer Guide

This guide is for the people who **run, deploy, extend, and operate** Mem0: platform engineers, backend developers, SREs, and architects. It covers the system architecture, the full configuration reference, deployment of the self-hosted REST server and OpenMemory, security, operations, and the internals you'd need to extend Mem0 or reason about its behavior under load.

If you're looking for "how do I store and search a memory," start with the companion **Mem0 User Guide**. This document assumes you already know the verbs and focuses on everything around them.

Mem0 is a memory layer for AI agents and applications. It is distributed as one package (`mem0ai`) that operates in two modes — a managed **Platform** (`MemoryClient`, hosted at `api.mem0.ai`) and a self-managed **Open Source** engine (`Memory`) you wire to your own LLM, embedder, and vector store. Around that core sit a self-hostable REST server, the OpenMemory MCP server, a CLI, and framework integrations.

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [System Architecture](#2-system-architecture)
3. [Repository Structure](#3-repository-structure)
4. [The Memory Engine: Design & Data Flow](#4-the-memory-engine-design--data-flow)
5. [Requirements](#5-requirements)
6. [Configuration Reference](#6-configuration-reference)
7. [Provider Catalog](#7-provider-catalog)
8. [Deploying the Self-Hosted REST Server](#8-deploying-the-self-hosted-rest-server)
9. [Deploying OpenMemory](#9-deploying-openmemory)
10. [Security](#10-security)
11. [Operations](#11-operations)
12. [Observability & Telemetry](#12-observability--telemetry)
13. [Performance & Scaling](#13-performance--scaling)
14. [Module Reference](#14-module-reference)
15. [Extending Mem0](#15-extending-mem0)
16. [Testing & Quality](#16-testing--quality)
17. [Known Issues & Improvement Opportunities](#17-known-issues--improvement-opportunities)
18. [Troubleshooting (Operator)](#18-troubleshooting-operator)
19. [Quick Reference](#19-quick-reference)

---

## 1. Executive Summary

**What it is.** Mem0 gives AI applications long-term memory: it extracts durable facts from conversations with an LLM, stores them as searchable vectors, and retrieves the relevant ones on demand. It replaces the anti-pattern of stuffing entire transcripts into every prompt.

**How it's deployed.** Three operating models, chosen per deployment:

| Model | Component | Where memory + compute live | Operator burden |
|---|---|---|---|
| Managed | `MemoryClient` → `api.mem0.ai` | Mem0 cloud | None |
| Library (embedded) | `Memory` in your process | Your vector store + your LLM keys | You own the vector store |
| Self-hosted service | `server/` FastAPI + dashboard | Your Postgres/pgvector + your LLM keys | You own the full stack |
| Personal server | `openmemory/` Docker stack + MCP | Your machine (Dockerized) | Docker host |

**Key architectural properties.**

- **Pluggable everything.** LLM, embedder, vector store, and reranker are all selected by a `provider` string and instantiated through factories. Swapping Qdrant for pgvector or OpenAI for Ollama is a config change, not a code change.
- **Anti-hallucination extraction.** A carefully engineered extraction prompt (the "additive extraction" prompt) governs what becomes a memory: preserve proper nouns/numbers/dates, ground relative time to absolute, never fabricate, deduplicate against existing memories.
- **Hybrid retrieval.** Search blends semantic similarity, BM25 keyword matching (spaCy-lemmatized), and entity-overlap boosting into a single normalized score, with optional reranking.
- **Filesystem/SQLite-light footprint for OSS.** The embedded library needs only a vector store and a small SQLite history DB (`~/.mem0/history.db`).

**Primary risks to manage.** LLM/provider availability and cost (every `add` is an LLM call), vector-store sizing, secret handling for the many provider keys, and — for the self-hosted server — authentication configuration (it ships auth-on by default and will 401 everything until an admin or key is configured).

---

## 2. System Architecture

### 2.1 The two faces of the engine

```
┌──────────────────────────────────────────────────────────────────────┐
│                          Your Application                              │
│                                                                        │
│   from mem0 import Memory          from mem0 import MemoryClient        │
│        (Open Source)                      (Platform)                   │
└───────────────┬───────────────────────────────┬───────────────────────┘
                │                                │
                │ in-process                     │ HTTPS  Authorization: Token m0-…
                ▼                                ▼
┌───────────────────────────────┐   ┌────────────────────────────────────┐
│        Memory engine          │   │        api.mem0.ai (managed)        │
│                               │   │   /v3/memories/add, /search, …       │
│  ┌─────────┐  ┌────────────┐  │   │   graph memory, exports, webhooks,   │
│  │  LLM    │  │  Embedder  │  │   │   projects, feedback, summaries      │
│  └─────────┘  └────────────┘  │   └────────────────────────────────────┘
│  ┌─────────────────────────┐  │
│  │   Vector store          │  │
│  │  (Qdrant / pgvector /…) │  │
│  └─────────────────────────┘  │
│  ┌─────────┐  ┌────────────┐  │
│  │ History │  │  Entity    │  │
│  │ SQLite  │  │  store     │  │
│  └─────────┘  └────────────┘  │
└───────────────────────────────┘
```

### 2.2 Self-hosted REST service

```
                 ┌─────────────────────────────────────────────┐
   HTTP clients  │            server/ (FastAPI)                 │
   ──────────────▶  Auth: JWT / X-API-Key / ADMIN_API_KEY       │
   X-API-Key /    │  Routers: /auth /api-keys /entities /requests│
   Bearer JWT     │  Memory: /memories /search /configure ...    │
                 │                                              │
                 │   uses  ──►  mem0.Memory (one shared instance)│
                 └───────┬───────────────────────┬───────────────┘
                         │                       │
                  ┌──────▼──────┐         ┌──────▼───────────┐
                  │  Postgres   │         │  pgvector (mem)  │
                  │ (app: users,│         │  + SQLite history│
                  │  api keys)  │         │                  │
                  └─────────────┘         └──────────────────┘
                         ▲
                  ┌──────┴───────┐
                  │  Dashboard   │  Next.js admin UI (server/dashboard)
                  └──────────────┘
```

The REST server holds **one shared `Memory` instance** (guarded by a reentrant lock) configured from a default config plus DB-persisted overrides. App-level data (users, API keys, request logs) lives in a separate Postgres database (`mem0_app`); memories live in pgvector; history lives in SQLite.

### 2.3 OpenMemory

```
   MCP client (Claude Desktop / Cursor)        Browser
        │  SSE: /{client}/sse/{user_id}            │  http://localhost:3000
        ▼                                          ▼
   ┌────────────────────────────┐         ┌──────────────────┐
   │ openmemory/api  (FastAPI)  │◀────────│ openmemory/ui     │
   │  MCP server + REST + MCP   │         │  (Next.js)        │
   │  uses mem0ai library       │         └──────────────────┘
   └──────────┬─────────────────┘
              ▼
     Vector store (Qdrant default) + SQLite app DB
```

OpenMemory is a fully self-contained Docker stack: a FastAPI backend exposing both REST and an **MCP (Model Context Protocol)** SSE endpoint, plus a Next.js dashboard. It uses the `mem0ai` library internally.

---

## 3. Repository Structure

The repo is a monorepo containing the library plus every surface built on it.

| Path | Component | Language | Published as |
|---|---|---|---|
| `mem0/` | Core Python library (engine + Platform client) | Python | `mem0ai` (PyPI) |
| `mem0-ts/` | TypeScript SDK (Platform + OSS impl) | TypeScript | `mem0ai` (npm) |
| `mem0-ts/src/community/` | LangChain integration | TypeScript | `@mem0/community` |
| `server/` | Self-hosted REST API (FastAPI) | Python | Docker image |
| `server/dashboard/` | Admin dashboard for the REST server | Next.js | — |
| `openmemory/api/` | OpenMemory backend (REST + MCP) | Python | `mem0/openmemory-mcp` |
| `openmemory/ui/` | OpenMemory dashboard | Next.js | `mem0/openmemory-ui` |
| `cli/node/` | Official CLI (`mem0` command) | TypeScript | `@mem0/cli` |
| `cli/python/` | Python CLI | Python | — |
| `vercel-ai-sdk/` | Vercel AI SDK provider | TypeScript | `@mem0/vercel-ai-provider` |
| `openclaw/` | OpenClaw memory plugin | TypeScript | `@mem0/openclaw-mem0` |
| `mem0-plugin/` | Claude Code plugin + skills | Python/MD | — |
| `skills/` | Claude Agent skills | Markdown | — |
| `evaluation/` | Benchmark/eval harness | Python | — |
| `examples/` | Runnable demos across frameworks | mixed | — |
| `cookbooks/` | Worked recipes | Python | — |
| `docs/` | Documentation site (Mintlify source) | MDX | docs.mem0.ai |
| `tests/` | Python test suite | Python | — |

### Core Python package (`mem0/`)

```
mem0/
  __init__.py          exports Memory, AsyncMemory, MemoryClient, AsyncMemoryClient
  memory/main.py       Memory & AsyncMemory — the engine
  memory/storage.py    SQLiteManager (history DB)
  memory/setup.py      ~/.mem0 dir, anon IDs, config setup
  memory/telemetry.py  PostHog anonymous telemetry
  client/main.py       MemoryClient & AsyncMemoryClient (Platform HTTP client)
  client/project.py    Project manager (instructions, categories)
  configs/             Pydantic config models (base, prompts, enums, per-provider)
  llms/                18 LLM provider implementations
  embeddings/          11 embedder implementations
  vector_stores/       24 vector-store implementations
  reranker/            5 reranker implementations
  utils/factory.py     Provider factories (the plug-in registry)
  utils/entity_extraction.py / scoring.py / lemmatization.py  hybrid-search internals
  exceptions.py        Structured exception hierarchy
  proxy/main.py        Mem0 OpenAI-compatible LLM proxy
```

---

## 4. The Memory Engine: Design & Data Flow

### 4.1 `Memory` construction

`Memory(config: MemoryConfig)` instantiates four collaborators via factories:

- `embedding_model` — `EmbedderFactory.create(provider, config, vector_config)`
- `vector_store` — `VectorStoreFactory.create(provider, config)`
- `llm` — `LlmFactory.create(provider, config)`
- `db` — `SQLiteManager(history_db_path)` for the change-history audit trail
- `reranker` — optional, `RerankerFactory.create(...)` when `config.reranker` is set
- `entity_store` — a lazily-initialized second vector collection (`{collection}_entities`) for entity-boost retrieval

`Memory.from_config(config_dict)` validates a plain dict against the `MemoryConfig` Pydantic model and returns a constructed instance — this is the entry point the REST server and most integrations use.

### 4.2 The `add()` pipeline (inference path)

When `infer=True`, `add()` runs a **phased batch pipeline** (V3):

1. **Phase 0 — context.** Pull the last ~10 messages for the session scope from SQLite to resolve references.
2. **Phase 1 — retrieve existing.** Embed the incoming messages, search the vector store (top 10) for related memories, and map their UUIDs to small integer IDs (an anti-hallucination trick — the LLM sees `"0","1",…` not raw UUIDs).
3. **Phase 2 — extract.** A single LLM call with the **additive extraction** system prompt produces self-contained facts. If the scope is agent-only, an agent-context suffix re-frames extraction from the agent's perspective.
4. **Phase 3 — embed.** Batch-embed all extracted fact texts.
5. **Phases 4–5 — dedup.** Skip facts whose MD5 content hash already exists (against both stored memories and within the batch).
6. **Phase 6 — persist.** Batch-insert vectors + payloads; write batch history records (`ADD`).
7. **Phase 7 — entity linking.** Extract named entities (spaCy), globally dedup them, batch-embed, search the entity store, then update existing entity records' `linked_memory_ids` or insert new ones.
8. **Phase 8 — save + telemetry.** Persist the raw messages for future context and emit an anonymous telemetry event.

When `infer=False`, the pipeline is skipped: each non-system message is embedded and stored verbatim as its own memory.

> The extraction prompt is the engine's "core IP." It is exhaustive about *what* to extract (every distinct topic, incidental facts, shared reference material, multi-speaker attribution) and strict about *integrity* (no fabrication, no echo extraction, no detail contamination, preserve exact proper nouns/numbers/dates, ground relative time to the observation date). This is what keeps generated memories faithful to source.

### 4.3 The `search()` pipeline (hybrid retrieval)

1. **Preprocess.** Lemmatize the query (spaCy) and extract query entities.
2. **Embed** the query.
3. **Semantic search** the vector store, over-fetching (`max(top_k*4, 60)`) for a scoring pool.
4. **Keyword search** (BM25) over lemmatized text, if the store supports it.
5. **BM25 normalization.** Raw BM25 scores are squashed to `[0,1]` via a query-length-adaptive logistic sigmoid.
6. **Entity boosts.** Query entities are matched against the entity store; linked memories get a boost (attenuated when an entity links to many memories).
7. **Score & rank.** `combined = (semantic + bm25 + entity_boost) / max_possible`, with the semantic score gated by `threshold` *before* combining. `max_possible` adapts to which signals are present (1.0 → 2.5).
8. **Format & (optional) rerank.** Build `MemoryItem` results; if `rerank=True` and a reranker is configured, re-order the top results.

### 4.4 Data model

A stored memory's vector-store **payload** carries: `data` (the memory text), `hash`, `created_at`, `updated_at`, `text_lemmatized`, the session IDs (`user_id`/`agent_id`/`run_id`), optional `actor_id`/`role`/`attributed_to`, and any user metadata. Results are shaped into a `MemoryItem` (`id`, `memory`, `hash`, `metadata`, `score`, `created_at`, `updated_at`) with the session IDs promoted to top-level fields.

The **history** SQLite table records every `ADD`/`UPDATE`/`DELETE` with old/new text, timestamps, actor/role, and an `is_deleted` flag.

---

## 5. Requirements

### Library (embedded)

| Component | Requirement |
|---|---|
| Python | 3.10+ |
| LLM provider | An API key for at least one supported LLM (default: OpenAI) |
| Embedder | An API key/endpoint for an embedder (default: OpenAI) |
| Vector store | One supported store reachable from the process (default: local Qdrant) |
| NLP (recommended) | `pip install "mem0ai[nlp]"` + `en_core_web_sm` spaCy model for full hybrid search |

### Self-hosted REST server (`server/`)

| Component | Requirement |
|---|---|
| Python | 3.10+ (see `server/requirements.txt`) |
| Postgres | With `pgvector` extension for memory storage; a separate `mem0_app` DB for app data |
| Secrets | `JWT_SECRET` (required unless `AUTH_DISABLED`), an LLM key (`OPENAI_API_KEY` by default) |
| Bundled providers | LLM: OpenAI, Anthropic, Gemini · Embedder: OpenAI, Gemini |

Key server dependencies (pinned): `fastapi==0.115.8`, `uvicorn==0.34.0`, `pydantic[email]==2.10.4`, `mem0ai>=0.1.48`, `psycopg>=3.2.8`, `sqlalchemy>=2.0`, `alembic`, `passlib[bcrypt]`, `python-jose[cryptography]`, `slowapi`, `posthog`.

### OpenMemory (`openmemory/`)

| Component | Requirement |
|---|---|
| Docker + Docker Compose V2 | Required |
| `OPENAI_API_KEY` | Required |
| Vector store | Selectable; Qdrant default (containerized) |

OpenMemory API deps include `fastapi`, `uvicorn`, `sqlalchemy`, `alembic`, `mem0ai>=0.1.92`, `mcp[cli]>=1.25.4`.

---

## 6. Configuration Reference

### 6.1 `MemoryConfig` (top-level)

`Memory.from_config()` accepts a dict matching this Pydantic model:

| Field | Type | Default | Purpose |
|---|---|---|---|
| `vector_store` | `{provider, config}` | Qdrant | Where vectors are stored |
| `llm` | `{provider, config}` | OpenAI | Fact extraction model |
| `embedder` | `{provider, config}` | OpenAI | Embedding model |
| `reranker` | `{provider, config}` or `null` | `null` | Optional reranker |
| `history_db_path` | str | `~/.mem0/history.db` | SQLite audit DB path |
| `version` | str | `"v1.1"` | API behavior version |
| `custom_instructions` | str or `null` | `null` | Steer fact extraction |

### 6.2 Config shape

Every component follows the same `{ "provider": "...", "config": { ... } }` shape:

```python
config = {
    "version": "v1.1",
    "llm": {
        "provider": "openai",
        "config": {"model": "gpt-4o-mini", "temperature": 0.1, "api_key": "sk-..."},
    },
    "embedder": {
        "provider": "openai",
        "config": {"model": "text-embedding-3-small"},
    },
    "vector_store": {
        "provider": "qdrant",
        "config": {"collection_name": "memories", "host": "localhost", "port": 6333},
    },
    "reranker": {
        "provider": "cohere",
        "config": {"model": "rerank-english-v3.0"},
    },
    "custom_instructions": "Prioritize travel and dietary facts.",
}
```

### 6.3 Common LLM config keys

The base LLM config exposes: `model`, `temperature`, `api_key`, `max_tokens`, `top_p`, `top_k`, `enable_vision`, `vision_details`, plus provider-specific keys (Azure deployment/endpoint/version, API-base overrides, etc.).

> [!TIP]
> `enable_vision: true` on the LLM config turns on multimodal message parsing in `add()`, so image content in messages is described and remembered. Pair it with a vision-capable model.

### 6.4 Provider credentials via environment variables

Most providers read their key from the environment if not passed in config. A non-exhaustive map (from source):

| Provider area | Environment variables |
|---|---|
| OpenAI | `OPENAI_API_KEY`, `OPENAI_BASE_URL`, `OPENAI_API_BASE` |
| OpenRouter | `OPENROUTER_API_KEY`, `OPENROUTER_API_BASE` |
| Anthropic | `ANTHROPIC_API_KEY` |
| Gemini / Google | `GOOGLE_API_KEY`, `GOOGLE_CLOUD_PROJECT`, `GOOGLE_APPLICATION_CREDENTIALS` |
| Azure OpenAI (LLM) | `LLM_AZURE_OPENAI_API_KEY`, `LLM_AZURE_DEPLOYMENT`, `LLM_AZURE_ENDPOINT`, `LLM_AZURE_API_VERSION` |
| Azure OpenAI (embed) | `EMBEDDING_AZURE_OPENAI_API_KEY`, `EMBEDDING_AZURE_DEPLOYMENT`, `EMBEDDING_AZURE_ENDPOINT`, `EMBEDDING_AZURE_API_VERSION` |
| DeepSeek | `DEEPSEEK_API_KEY`, `DEEPSEEK_API_BASE` |
| Together | `TOGETHER_API_KEY` |
| Groq | `GROQ_API_KEY` |
| xAI | `XAI_API_KEY`, `XAI_API_BASE` |
| MiniMax | `MINIMAX_API_KEY`, `MINIMAX_API_BASE` |
| Sarvam | `SARVAM_API_KEY`, `SARVAM_API_BASE` |
| vLLM | `VLLM_API_KEY`, `VLLM_BASE_URL` |
| AWS Bedrock | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN` |
| Cohere reranker | `COHERE_API_KEY` |
| ZeroEntropy reranker | `ZERO_ENTROPY_API_KEY` |
| Pinecone | `PINECONE_API_KEY` |
| Turbopuffer | `TURBOPUFFER_API_KEY` |
| Engine | `MEM0_DIR`, `MEM0_API_KEY`, `MEM0_TELEMETRY` |

> [!IMPORTANT]
> Mem0's telemetry/redaction logic treats any config field named `api_key`, `*_secret`, `*_token`, `*_password`, `credentials`, etc. as sensitive and redacts it before any telemetry capture, while preserving runtime auth objects (`http_auth`, `connection_class`, `ssl_context`). Don't rename secret-bearing fields away from these conventions or they may leak into telemetry payloads.

---

## 7. Provider Catalog

These lists come directly from the factory registries in `mem0/utils/factory.py` — the authoritative source of "what's supported."

### LLM providers (`LlmFactory`)

`openai`, `openai_structured`, `azure_openai`, `azure_openai_structured`, `anthropic`, `gemini`, `groq`, `together`, `aws_bedrock`, `litellm`, `deepseek`, `minimax`, `xai`, `sarvam`, `ollama`, `lmstudio`, `vllm`, `langchain`.

### Embedder providers (`EmbedderFactory`)

`openai`, `azure_openai`, `ollama`, `huggingface`, `gemini`, `vertexai`, `together`, `lmstudio`, `aws_bedrock`, `fastembed`, `langchain`. (Plus a `MockEmbeddings` used automatically when the Upstash vector store provides its own embeddings.)

### Vector store providers (`VectorStoreFactory`)

`qdrant`, `chroma`, `pgvector`, `milvus`, `pinecone`, `redis`, `valkey`, `weaviate`, `faiss`, `elasticsearch`, `opensearch`, `mongodb`, `supabase`, `azure_ai_search`, `azure_mysql`, `databricks`, `vertex_ai_vector_search`, `upstash_vector`, `s3_vectors`, `cassandra`, `baidu`, `neptune` (Neptune Analytics), `turbopuffer`.

### Reranker providers (`RerankerFactory`)

`cohere`, `sentence_transformer`, `zero_entropy`, `llm_reranker`, `huggingface`.

> [!NOTE]
> Providers are imported lazily via `load_class()`. A provider's heavy client library (e.g. `qdrant-client`, `pymilvus`, `weaviate-client`) is only imported when you actually select it, so installing `mem0ai` doesn't pull every vector-store SDK. Install the extra you need for your chosen store.

---

## 8. Deploying the Self-Hosted REST Server

The `server/` directory is a FastAPI app titled **"Mem0 REST APIs"** that wraps a single shared `Memory` instance and adds auth, a dashboard, and per-user API keys.

### 8.1 Default runtime config

On boot the server constructs this `DEFAULT_CONFIG` (overridable via the `/configure` endpoint, persisted to the `settings` table):

```python
{
  "version": "v1.1",
  "vector_store": {"provider": "pgvector",
                   "config": {"host": POSTGRES_HOST, "port": POSTGRES_PORT,
                              "dbname": POSTGRES_DB, "user": POSTGRES_USER,
                              "password": POSTGRES_PASSWORD,
                              "collection_name": POSTGRES_COLLECTION_NAME}},
  "llm": {"provider": "openai",
          "config": {"api_key": OPENAI_API_KEY, "temperature": 0.2,
                     "model": MEM0_DEFAULT_LLM_MODEL}},      # default gpt-4.1-nano-2025-04-14
  "embedder": {"provider": "openai",
               "config": {"api_key": OPENAI_API_KEY,
                          "model": MEM0_DEFAULT_EMBEDDER_MODEL}},  # text-embedding-3-small
  "history_db_path": HISTORY_DB_PATH,                         # default /app/history/history.db
}
```

### 8.2 Environment variables

| Variable | Default | Purpose |
|---|---|---|
| `JWT_SECRET` | — (**required** unless `AUTH_DISABLED`) | Signs access/refresh JWTs (`openssl rand -base64 48`) |
| `ADMIN_API_KEY` | — | Legacy single admin key; sent as `X-API-Key` |
| `AUTH_DISABLED` | `false` | Open all endpoints — **local dev only** |
| `OPENAI_API_KEY` | — | Default LLM + embedder key |
| `POSTGRES_HOST` / `PORT` / `USER` / `PASSWORD` | `postgres`/`5432`/`postgres`/`postgres` | pgvector connection |
| `POSTGRES_DB` | `postgres` | DB holding the memory collection |
| `APP_DB_NAME` | `mem0_app` | DB holding users/api-keys/logs |
| `POSTGRES_COLLECTION_NAME` | `memories` | pgvector collection name |
| `HISTORY_DB_PATH` | `/app/history/history.db` | SQLite history DB |
| `MEM0_DEFAULT_LLM_MODEL` | `gpt-4.1-nano-2025-04-14` | Default extraction model |
| `MEM0_DEFAULT_EMBEDDER_MODEL` | `text-embedding-3-small` | Default embedder |
| `DASHBOARD_URL` | `http://localhost:3000` | CORS allow-origin |
| `MEM0_TELEMETRY` | `true` | Anonymous telemetry toggle |
| `MEM0_TELEMETRY_STATE_PATH` | `/app/history/telemetry.json` | Telemetry state file |

### 8.3 Endpoints

**Memory** (all require auth unless `AUTH_DISABLED`):

| Method | Path | Handler | Notes |
|---|---|---|---|
| GET | `/configure` | `get_config` | Returns current config (secrets redacted) |
| GET | `/configure/providers` | `list_bundled_providers` | Lists bundled LLM/embedder providers |
| POST | `/configure` | `set_config` | Update config (validates bundled providers) |
| POST | `/generate-instructions` | `generate_instructions` | LLM-generates custom instructions from a use case |
| POST | `/memories` | `add_memory` | Requires one of user/agent/run id |
| GET | `/memories` | `get_all_memories` | Lists all if no id supplied |
| GET | `/memories/{id}` | `get_memory` | |
| POST | `/search` | `search_memories` | Pass ids inside `filters` (top-level deprecated) |
| PUT | `/memories/{id}` | `update_memory` | |
| GET | `/memories/{id}/history` | `memory_history` | |
| DELETE | `/memories/{id}` | `delete_memory` | |
| DELETE | `/memories` | `delete_all_memories` | Requires an id |
| POST | `/reset` | `reset_memory` | Wipes everything |
| GET | `/` | `home` | Redirects to `/docs` |

**Auth & admin routers** (`server/routers/`):

| Method | Path | Purpose |
|---|---|---|
| GET | `/setup-status` | Whether an admin exists |
| POST | `/register` | Create admin/user |
| POST | `/login` | Obtain JWT pair |
| POST | `/refresh` | Rotate refresh token |
| GET/PATCH | `/me` | Current user / update |
| POST | `/change-password` | Change password |
| POST | `/onboarding-complete` | Mark wizard complete |
| GET/POST/DELETE | `/api-keys`, `/api-keys/{id}` | List / create / revoke per-user API keys |
| GET/DELETE | `/entities`, `/entities/{type}/{id}` | List / delete memory entities |
| GET | `/requests` | Request log |

### 8.4 Deploy flow

1. Provision Postgres with the `pgvector` extension. Run `server/init-db.sh` to create the `mem0_app` database (memories use the default `postgres` DB).
2. Set secrets in `.env`: `JWT_SECRET`, `OPENAI_API_KEY`, and `POSTGRES_*`.
3. Build/run the API container (uvicorn serving `server/main.py`) and the `server/dashboard` Next.js app.
4. Run Alembic migrations (`server/alembic/`) to create the app tables.
5. Either register an admin at `http://<host>:3000/setup`, or set `ADMIN_API_KEY` for header-based access.

> [!WARNING]
> The server enables auth by default. If you upgrade an older deployment that had no auth, **every protected endpoint returns 401** until you either (1) set `ADMIN_API_KEY`, (2) register an admin via `/setup`, or (3) set `AUTH_DISABLED=true` (dev only). The server logs a prominent warning on startup when it detects this unconfigured state.

> [!CAUTION]
> The prebuilt server image only bundles **OpenAI, Anthropic, Gemini** (LLM) and **OpenAI, Gemini** (embedder). Configuring any other provider via `/configure` returns HTTP 400. To add one, install its Python package, extend `BUNDLED_LLM_PROVIDERS` / `BUNDLED_EMBEDDER_PROVIDERS` in `server/main.py`, and rebuild the image.

---

## 9. Deploying OpenMemory

OpenMemory is the turnkey personal deployment. The installer (`openmemory/run.sh`):

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

What it does:

1. Validates Docker + Docker Compose V2.
2. Generates a `docker-compose.yml` from `compose/<vector_store>.yml` merged with the `openmemory-mcp` service.
3. Selects a vector store (`VECTOR_STORE` env or `--vector-store` flag): `qdrant` (default), `chroma`, `pgvector`, `redis`, `weaviate`, `milvus`, `elasticsearch`, `faiss`.
4. Installs the matching vector-store client into the running container and seeds the backend config via `PUT /api/v1/config/mem0/vector_store`.
5. Starts the backend on **`:8765`** and the UI container (`mem0/openmemory-ui:latest`) on the first free port **3000–3010**.

Images used: `mem0/openmemory-mcp:latest` (backend) and `mem0/openmemory-ui:latest` (frontend).

### MCP integration

The backend exposes an SSE MCP transport:

| Method | Path | Purpose |
|---|---|---|
| GET | `/{client_name}/sse/{user_id}` | Open an MCP SSE channel |
| POST | `/{client_name}/sse/{user_id}/messages/` | MCP message channel |

Register that endpoint in any MCP-aware client to give it persistent memory backed by your local store.

> [!NOTE]
> OpenMemory stores everything locally (vector store + a SQLite app DB at `openmemory.db`). The only outbound dependency is the LLM/embedding provider key you supply.

---

## 10. Security

### 10.1 REST server authentication

The server (`server/auth.py`) supports three mechanisms, checked in order by `verify_auth`:

1. **Bearer JWT** — short-lived access tokens (30 min) + rotating refresh tokens (30 days). Refresh tokens are single-use: their `jti` is recorded and atomically consumed via a conditional `UPDATE`, closing the replay race.
2. **Per-user API keys** — format `m0sk_<urlsafe>`; only a 12-char prefix and a **bcrypt hash** are stored. Lookups match by prefix then bcrypt-verify; keys can be revoked (`revoked_at`).
3. **Legacy `ADMIN_API_KEY`** — compared with `secrets.compare_digest` (constant-time); maps to the default admin user.

`AUTH_DISABLED=true` bypasses all of this for local development and logs a warning.

### 10.2 Hardening details (from source)

- **Password hashing:** bcrypt via passlib. Login burns equivalent bcrypt cycles for unknown emails (`dummy_verify`) to avoid timing-based user enumeration.
- **JWT:** HS256 signed with `JWT_SECRET`; server refuses to start (in auth mode) if `JWT_SECRET` is unset.
- **Rate limiting:** `slowapi` per-IP limiter on auth endpoints.
- **CORS:** restricted to `DASHBOARD_URL`.
- **Config redaction:** `/configure` redacts `api_key`, `password`, `secret`, `token`, `jwt_secret`, etc. before returning.
- **Upstream error masking:** provider/database/vector errors are classified into safe, generic codes (`provider_auth_failed`, `provider_rate_limited`, `vector_store_unavailable`, …) with a request ID — internal details aren't leaked to callers.
- **Request IDs:** every request gets an 8-char ID, attached to logs and the `X-Request-ID` response header.

### 10.3 Library-side secret handling

The engine's config-cloning logic (`_safe_deepcopy_config`) redacts sensitive fields and preserves runtime auth objects. Secret detection is layered: an allowlist of runtime fields, an exact deny list, and a suffix deny list (`_password`, `_secret`, `_token`, `_credential(s)`).

### 10.4 Platform client auth

`MemoryClient` sends `Authorization: Token <api_key>` and a derived `Mem0-User-ID` (MD5 of the key) header to `api.mem0.ai`, validating the key against `/v1/ping/` on init. Keys are read from `MEM0_API_KEY` if not passed explicitly.

### 10.5 Recommendations

- Generate `JWT_SECRET` with `openssl rand -base64 48`; rotate on suspected compromise (invalidates all sessions).
- Use per-user API keys over the legacy `ADMIN_API_KEY` in multi-user deployments; revoke rather than rotate.
- Keep provider keys in a secret manager; never commit them. Note the GitHub-issue-tracked CVEs in transitive JS deps — keep the SDKs patched.
- Terminate TLS in front of the server (it speaks plain HTTP); restrict network access to Postgres and the vector store.

---

## 11. Operations

### 11.1 Lifecycle commands (library)

```python
m = Memory.from_config(config)
m.add(...) ; m.search(...)        # normal operation
m.close()                          # release SQLite connections cleanly
m.reset()                          # DROP history + recreate vector collection (destructive)
```

### 11.2 Backup & restore

- **Memories:** back up your vector store using its native tooling (Qdrant snapshots, `pg_dump` for pgvector, etc.). This is the source of truth for stored memories.
- **History:** back up the SQLite file at `history_db_path` (`~/.mem0/history.db`, or `/app/history/history.db` in the server image).
- **App data (server):** `pg_dump` the `mem0_app` database (users, API keys, request logs, config overrides).

### 11.3 Config changes at runtime (server)

`POST /configure` merges and persists overrides into the `settings` table (`config_overrides` key) and rebuilds the shared `Memory` instance atomically under a lock. Overrides survive restarts (re-merged over `DEFAULT_CONFIG` on boot).

### 11.4 Resetting / migrating

- To change vector store or embedder dimensions, you generally must re-index: existing vectors aren't portable across stores or embedding models. Plan a migration that re-`add`s source data, or export/import via the Platform's export API.
- The `version` field (`v1.1`) governs result shaping; keep it stable across a deployment.

### 11.5 Cost control

Every `add()` with `infer=True` is at least one LLM call (plus embeddings); every `search()` is at least one embedding call. To control spend:

- Use a small, cheap extraction model (the server defaults to `gpt-4.1-nano`).
- Batch conversation turns before calling `add()` rather than per-message.
- Use `infer=False` for facts you already have structured.
- Set `custom_instructions` to narrow extraction and avoid storing noise.

---

## 12. Observability & Telemetry

### 12.1 Anonymous telemetry

Both the library and the server send **anonymous** telemetry to PostHog by default (opt out with `MEM0_TELEMETRY=false`).

- **Library:** captures events like `mem0.init`, `mem0.add`, `mem0.search` with non-identifying properties; entity IDs are processed through `process_telemetry_filters` (keys + encoded IDs, not raw values).
- **Server:** sends at most two events per install — `admin_registered` and `onboarding_completed` — carrying only email *domain*, server version, and a random install UUID. State is tracked in a local JSON file so events fire once.

> [!IMPORTANT]
> For privacy-sensitive or regulated deployments, set `MEM0_TELEMETRY=false` across all processes (library, server, OpenMemory). The flag is read at import/boot time.

### 12.2 Server logging

- Structured logging with per-request IDs (`%(request_id)s` in the log format).
- A `request_logs` table records method, path, status, latency, and auth type for every non-health, non-docs request (written off the hot path via an executor).
- Provider failures log full stack traces server-side while returning sanitized error codes to clients.

### 12.3 Recommended monitoring

- Vector-store health/latency and disk usage (memory growth is unbounded without lifecycle policies).
- LLM/embedding provider error and rate-limit rates (surfaced as `provider_*` error codes).
- Postgres connection pool health (`pool_pre_ping=True` is enabled).
- `request_logs` latency percentiles per endpoint.

---

## 13. Performance & Scaling

### 13.1 Built-in optimizations

- **Batched everything in `add()`:** batch embedding, batch vector insert, batch history insert, and batch entity linking — with per-item fallbacks if a batch op fails.
- **Over-fetch + rerank locally:** search over-fetches `max(top_k*4, 60)` candidates so the hybrid scorer has a meaningful pool.
- **Shared spaCy models:** entity extraction and lemmatization share a single loaded spaCy instance behind a lock; the lemma model loads with `ner`/`parser` disabled for speed.
- **Async twins:** `AsyncMemory` / `AsyncMemoryClient` offload blocking calls via `asyncio.to_thread`, enabling concurrency in async servers.
- **Shared Qdrant client for entity store** in embedded mode to avoid RocksDB lock contention.

### 13.2 Scaling the self-hosted server

- The server holds **one shared `Memory` instance** behind a reentrant lock. Heavy concurrent write load serializes on config/instance access — scale horizontally (multiple API replicas) behind a load balancer, all pointing at shared Postgres/pgvector.
- pgvector tuning (HNSW vs IVF, `lists`, index maintenance) directly affects search latency at scale; size the Postgres instance for your vector count.
- Memory growth is unbounded by default. Implement retention (TTL via the Platform's `expires`, or periodic `delete_all`/pruning of stale scopes) for long-lived deployments.

### 13.3 Throughput notes

- `add()` latency is dominated by the LLM extraction call. Use a fast model and batch turns.
- `search()` latency is embedding + vector search + (optional) reranking. Reranking adds a model call — enable it only when precision matters.

---

## 14. Module Reference

### `mem0/memory/main.py`
The engine. `Memory` and `AsyncMemory` (sync/async twins of the same logic). Houses the V3 add pipeline, hybrid search, entity store management, and the `MemoryBase` ABC (`get`/`get_all`/`update`/`delete`/`history`).

### `mem0/client/main.py`
`MemoryClient` / `AsyncMemoryClient` — the Platform HTTP client. Wraps `api.mem0.ai` endpoints (`/v3/memories/*`, `/v1/memories/*`, `/v1/entities`, `/v1/exports`, `/v1/feedback`, webhooks, projects). Every method is decorated with `@api_error_handler` which maps HTTP status codes to structured exceptions.

### `mem0/configs/`
Pydantic models. `base.py` (`MemoryConfig`, `MemoryItem`, `AzureConfig`), `enums.py` (`MemoryType`: semantic/episodic/procedural), `prompts.py` (extraction prompts — the engine's IP), plus per-provider config classes under `configs/llms`, `configs/embeddings`, `configs/vector_stores`, `configs/rerankers`.

### `mem0/utils/factory.py`
The plug-in registry: `LlmFactory`, `EmbedderFactory`, `VectorStoreFactory`, `RerankerFactory`. Each maps a provider string to an implementation class (lazy-imported). `register_provider()` allows runtime extension.

### `mem0/utils/entity_extraction.py`, `scoring.py`, `lemmatization.py`, `spacy_models.py`
Hybrid-search internals: spaCy-based entity extraction (proper nouns, quoted text, noun compounds), BM25 sigmoid normalization, additive scoring (`score_and_rank`), and the shared spaCy model loader.

### `mem0/exceptions.py`
Structured exception hierarchy rooted at `MemoryError` (with `error_code`, `details`, `suggestion`, `debug_info`): `AuthenticationError`, `RateLimitError`, `ValidationError`, `MemoryNotFoundError`, `NetworkError`, `ConfigurationError`, `MemoryQuotaExceededError`, plus OSS-specific `VectorStoreError`, `EmbeddingError`, `LLMError`, `DatabaseError`, `DependencyError`. `create_exception_from_response()` maps HTTP status → exception.

### `mem0/proxy/main.py`
`Mem0` — an OpenAI-compatible chat proxy. `.chat.completions.create(...)` searches memory, injects it into the prompt, calls the model via LiteLLM, and stores the turn in a background thread.

### `server/`
The FastAPI service: `main.py` (app + memory endpoints), `auth.py` (JWT/API-key/admin auth), `db.py` + `models.py` (SQLAlchemy: `User`, `APIKey`, `RequestLog`, `RefreshTokenJti`, `Settings`), `server_state.py` (shared `Memory` instance + config persistence), `errors.py` (upstream error classification), `telemetry.py`, `rate_limit.py`, and routers.

### `openmemory/`
Self-hosted MCP server (`api/`, with `mcp_server.py` exposing SSE endpoints) + Next.js UI (`ui/`) + Docker compose templates (`compose/*.yml`) + installer (`run.sh`).

---

## 15. Extending Mem0

### 15.1 Register a custom provider

Factories accept runtime registration:

```python
from mem0.utils.factory import LlmFactory
LlmFactory.register_provider(
    name="my_llm",
    class_path="my_package.my_llm.MyCustomLLM",
    config_class=None,  # defaults to BaseLlmConfig
)
```

Implement the provider class to match the existing interface (e.g. an LLM exposes `generate_response(messages, response_format=...)`; an embedder exposes `embed(text, memory_action)` and `embed_batch(texts, memory_action)`; a vector store exposes `insert`/`search`/`list`/`get`/`update`/`delete`/`keyword_search`/`reset`).

### 15.2 Custom extraction behavior

- Pass `custom_instructions` in `MemoryConfig` (or `prompt=` per `add()`) to steer what's extracted without touching code.
- For deep changes, the prompts live in `mem0/configs/prompts.py` (`ADDITIVE_EXTRACTION_PROMPT`, `generate_additive_extraction_prompt`).

### 15.3 Procedural memory for agents

```python
m.add(messages, agent_id="my-agent", memory_type="procedural_memory")
```

Produces a single, verbatim-preserving summary of an agent's execution history (driven by `PROCEDURAL_MEMORY_SYSTEM_PROMPT`). Only `"procedural_memory"` is accepted as a non-default `memory_type`.

### 15.4 Self-host server: add a bundled provider

Install the provider's package into the image, then extend `BUNDLED_LLM_PROVIDERS` / `BUNDLED_EMBEDDER_PROVIDERS` in `server/main.py` and rebuild — otherwise `/configure` rejects it with HTTP 400.

---

## 16. Testing & Quality

The Python suite under `tests/` mirrors the package layout: `tests/llms`, `tests/embeddings`, `tests/vector_stores`, `tests/rerankers`, `tests/memory`, `tests/utils`, `tests/configs`. Vector-store tests are gated on external services via env vars (e.g. `ES_URL`, `WEAVIATE_CLUSTER_URL`, `RUN_TEST_NEPTUNE_ANALYTICS`) so they can run against real backends in CI.

TypeScript packages use Jest/Vitest (`mem0-ts`, `cli/node`, `vercel-ai-sdk`, `openclaw`), with separate unit/integration/edge/node configs. Run JS tests with each package's `test` script; Python tests with `pytest`.

> [!TIP]
> When validating a provider change, target the matching test directory (e.g. `pytest tests/vector_stores/test_qdrant.py`) and set the required env vars for that backend. Many vector-store tests are skipped silently if their service env vars are unset.

---

## 17. Known Issues & Improvement Opportunities

Surfaced from the issue tracker and source review:

- **Security CVEs in transitive JS deps** (closed, fix-pinned via pnpm overrides): `langsmith`, `@langchain/core`, `nanoid`, `axios`, `immutable`, `follow-redirects`. The TS packages pin overrides — keep them current and re-audit on dependency bumps.
- **Silent memory loss on partial batch-embedding failure** (open, #5245): if batch embedding partially fails in the V3 add pipeline, some extracted facts may be dropped. The code falls back to per-item embedding, but monitor add results when embedding providers are flaky.
- **Platform v3 `add()` and entity IDs** (open, #5224): a reported case where `user_id`/`agent_id` are accepted but `get_all` returns empty — validate scope round-trips after upgrades.
- **Memory poisoning / security scanning** (feature requests, #5331/#5349): no built-in defense against adversarial memory injection. If you accept untrusted conversation, consider sanitizing inputs and reviewing `custom_instructions`.
- **Unbounded memory growth:** no default retention. Implement TTL/expiry (Platform `expires`) or scheduled pruning.
- **Pluggable OSS storage** (proposal, #5354): backend storage is provider-bound; cloud-native pluggability is requested but not yet first-class.
- **`deploy`/image provider bundling:** the server's bundled-provider allowlist is a deliberate guardrail but a friction point — document clearly which image supports which providers for your team.

---

## 18. Troubleshooting (Operator)

### Server returns 401 on every endpoint after upgrade
Auth is on by default with no admin configured. Set `ADMIN_API_KEY`, register an admin at `/setup`, or set `AUTH_DISABLED=true` (dev). Watch for the startup warning.

### Server won't start: "JWT_SECRET is required"
Set `JWT_SECRET` (`openssl rand -base64 48`) or `AUTH_DISABLED=true` for local dev only.

### `/configure` rejects a provider (HTTP 400)
The image only bundles OpenAI/Anthropic/Gemini (LLM) and OpenAI/Gemini (embedder). Install the package, extend the `BUNDLED_*` lists in `server/main.py`, rebuild.

### `vector_store_unavailable` / `datastore_unavailable` errors
The classifier mapped a Qdrant/pgvector/Postgres failure. Check connectivity, credentials, and that pgvector is installed in the target Postgres DB. Use the `X-Request-ID` to correlate with server logs.

### Memories added but search returns nothing (server)
Confirm scope: `/search` should pass IDs in `filters`. Check the embedder/LLM keys are valid (a failed extraction returns empty results). Lower `threshold`.

### High LLM cost
Lower the extraction model tier (`MEM0_DEFAULT_LLM_MODEL`), batch turns before `add()`, set `custom_instructions` to reduce noise, and use `infer=False` for pre-structured data.

### spaCy errors / weak OSS search quality
Install `mem0ai[nlp]` and `en_core_web_sm`. Without spaCy, keyword + entity signals are disabled and search falls back to semantic-only.

### Telemetry must be disabled for compliance
Set `MEM0_TELEMETRY=false` in every process (library, server, OpenMemory). It's read at import/boot.

---

## 19. Quick Reference

### Service endpoints (self-hosted server)

```
POST   /memories                 GET  /memories            GET /memories/{id}
POST   /search                   PUT  /memories/{id}       GET /memories/{id}/history
DELETE /memories/{id}            DELETE /memories          POST /reset
GET/POST /configure              GET  /configure/providers POST /generate-instructions
POST /register /login /refresh   GET/PATCH /me             POST /change-password
GET/POST/DELETE /api-keys        GET/DELETE /entities      GET /requests
GET / (→ /docs Swagger UI)
```

### Default server config values

| Setting | Default |
|---|---|
| Vector store | pgvector (`postgres` DB, `memories` collection) |
| LLM | OpenAI `gpt-4.1-nano-2025-04-14`, temp `0.2` |
| Embedder | OpenAI `text-embedding-3-small` |
| History DB | `/app/history/history.db` |
| Access token TTL | 30 min |
| Refresh token TTL | 30 days |
| App DB | `mem0_app` |

### Critical environment variables

| Variable | Required? | Notes |
|---|---|---|
| `JWT_SECRET` | Server (unless `AUTH_DISABLED`) | JWT signing |
| `OPENAI_API_KEY` | Server default / OSS default | LLM + embedder |
| `POSTGRES_*` | Server | pgvector + app DB |
| `MEM0_API_KEY` | Platform client / CLI | `api.mem0.ai` auth |
| `MEM0_DIR` | OSS | History dir (`~/.mem0`) |
| `MEM0_TELEMETRY` | All | `false` to opt out |
| `ADMIN_API_KEY` / `AUTH_DISABLED` | Server | Auth shortcuts |

### Factories (extension points)

| Factory | Selects | Register method |
|---|---|---|
| `LlmFactory` | LLM provider | `register_provider(name, class_path, config_class)` |
| `EmbedderFactory` | Embedder | (edit `provider_to_class`) |
| `VectorStoreFactory` | Vector store | (edit `provider_to_class`) |
| `RerankerFactory` | Reranker | (edit `provider_to_class`) |

### Exception hierarchy (library)

`MemoryError` → `AuthenticationError`, `RateLimitError`, `ValidationError`, `MemoryNotFoundError`, `NetworkError`, `ConfigurationError`, `MemoryQuotaExceededError`, `MemoryCorruptionError`, `VectorSearchError`, `CacheError`, `VectorStoreError`, `EmbeddingError`, `LLMError`, `DatabaseError`, `DependencyError`.

---

_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._
