Compare commits
57
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e00815589 | ||
|
|
e2fd8dc7a8 | ||
|
|
d19cde4a15 | ||
|
|
565a76960b | ||
|
|
d987243584 | ||
|
|
4ca67801c0 | ||
|
|
739402946c | ||
|
|
240168aefe | ||
|
|
07b9ad519d | ||
|
|
6ba334ef94 | ||
|
|
8bd7b913c6 | ||
|
|
367512b525 | ||
|
|
79e04c56f6 | ||
|
|
7b109d90de | ||
|
|
f687951b1a | ||
|
|
70bc9e51d5 | ||
|
|
0107fd53b8 | ||
|
|
54a03cc721 | ||
|
|
e95de4ca50 | ||
|
|
a623cfaf76 | ||
|
|
92491c00c2 | ||
|
|
9043fbf61e | ||
|
|
c90cbc75a2 | ||
|
|
58304fc939 | ||
|
|
397f3414ee | ||
|
|
a734e057cf | ||
|
|
0fdaa29b4a | ||
|
|
6d3486ca56 | ||
|
|
ebb9bb2b15 | ||
|
|
594b4e65d6 | ||
|
|
1b95c99db4 | ||
|
|
b66cf0f272 | ||
|
|
72dca1cdf5 | ||
|
|
ece7ff6b84 | ||
|
|
30ce028a71 | ||
|
|
bd9d27ff50 | ||
|
|
08b746c9be | ||
|
|
693e709389 | ||
|
|
553e275112 | ||
|
|
43dde3b186 | ||
|
|
cca7551192 | ||
|
|
5be2630f5b | ||
|
|
2549a84e5c | ||
|
|
34ed122ef3 | ||
|
|
db8ac61713 | ||
|
|
15feaa8ac4 | ||
|
|
282feaebf2 | ||
|
|
f5dc825d47 | ||
|
|
32b74e18b7 | ||
|
|
daa4495583 | ||
|
|
cfb5f1776e | ||
|
|
573e5212a4 | ||
|
|
8ba225cec8 | ||
|
|
4b09943092 | ||
|
|
4e611e8dba | ||
|
|
5520226b5b | ||
|
|
00695e3113 |
@@ -12,7 +12,7 @@
|
||||
"name": "mem0",
|
||||
"source": "./mem0-plugin",
|
||||
"description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search to Claude workflows.",
|
||||
"version": "0.1.0"
|
||||
"version": "0.1.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"name": "mem0",
|
||||
"source": "./mem0-plugin",
|
||||
"description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search.",
|
||||
"version": "0.1.0"
|
||||
"version": "0.1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -14,8 +14,48 @@ on:
|
||||
- 'mem0/**'
|
||||
- 'tests/**'
|
||||
- 'embedchain/**'
|
||||
- 'pyproject.toml'
|
||||
|
||||
jobs:
|
||||
changelog_check:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Require CHANGELOG entry when Python SDK version changes
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
extract_version() {
|
||||
python3 -c "import sys, re; m = re.search(r'^\s*version\s*=\s*\"([^\"]+)\"', sys.stdin.read(), re.M); print(m.group(1) if m else '')"
|
||||
}
|
||||
|
||||
base_version=$(git show "$BASE_SHA:pyproject.toml" 2>/dev/null | extract_version || echo "")
|
||||
head_version=$(extract_version < pyproject.toml)
|
||||
|
||||
echo "Base version: ${base_version:-<unknown>}"
|
||||
echo "Head version: $head_version"
|
||||
|
||||
if [ -z "$base_version" ] || [ "$base_version" = "$head_version" ]; then
|
||||
echo "pyproject.toml version unchanged — no CHANGELOG entry required."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Detected version bump ${base_version} -> ${head_version}. Checking docs/changelog/sdk.mdx…"
|
||||
|
||||
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- docs/changelog/sdk.mdx | grep -q .; then
|
||||
echo "Changelog update present in docs/changelog/sdk.mdx ✅"
|
||||
else
|
||||
echo "::error file=pyproject.toml::pyproject.toml version changed from ${base_version} to ${head_version} but docs/changelog/sdk.mdx was not updated in this PR. Add a new <Update> entry under the Python tab for v${head_version}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
check_changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
|
||||
@@ -24,6 +24,42 @@ jobs:
|
||||
ts_sdk:
|
||||
- 'mem0-ts/**'
|
||||
|
||||
changelog_check:
|
||||
needs: check_changes
|
||||
if: github.event_name == 'pull_request' && needs.check_changes.outputs.ts_sdk_changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Require CHANGELOG entry when SDK version changes
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
base_version=$(git show "$BASE_SHA:mem0-ts/package.json" 2>/dev/null | jq -r .version || echo "")
|
||||
head_version=$(jq -r .version mem0-ts/package.json)
|
||||
|
||||
echo "Base version: ${base_version:-<unknown>}"
|
||||
echo "Head version: $head_version"
|
||||
|
||||
if [ -z "$base_version" ] || [ "$base_version" = "$head_version" ]; then
|
||||
echo "mem0-ts/package.json version unchanged — no CHANGELOG entry required."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Detected version bump ${base_version} -> ${head_version}. Checking docs/changelog/sdk.mdx…"
|
||||
|
||||
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- docs/changelog/sdk.mdx | grep -q .; then
|
||||
echo "Changelog update present in docs/changelog/sdk.mdx ✅"
|
||||
else
|
||||
echo "::error file=mem0-ts/package.json::mem0-ts/package.json version changed from ${base_version} to ${head_version} but docs/changelog/sdk.mdx was not updated in this PR. Add a new <Update> entry under the TypeScript tab for v${head_version}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build_ts_sdk:
|
||||
needs: check_changes
|
||||
if: needs.check_changes.outputs.ts_sdk_changed == 'true'
|
||||
|
||||
+6
-2
@@ -4,6 +4,10 @@ __pycache__/
|
||||
*$py.class
|
||||
**/node_modules/
|
||||
|
||||
# Self-hosted server local runtime state
|
||||
server/history/
|
||||
server/.env
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
@@ -15,8 +19,8 @@ dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
/lib/
|
||||
/lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
|
||||
@@ -27,7 +27,7 @@ This is a **polyglot monorepo** containing Python and TypeScript packages, CLIs,
|
||||
| `server/` | FastAPI REST server for self-hosted Mem0 (Docker: FastAPI + PostgreSQL/pgvector + Neo4j) |
|
||||
| `openmemory/` | Self-hosted memory platform — `api/` (FastAPI + Alembic + MCP server) and `ui/` (Next.js 15 + React 19) |
|
||||
| `mem0-plugin/` | AI editor plugins (Claude Code, Cursor, Codex) — MCP server connection, lifecycle hooks, skills |
|
||||
| `skills/` | Claude Code skill definitions — `mem0/`, `mem0-cli/`, `mem0-vercel-ai-sdk/` |
|
||||
| `skills/` | Claude Code skill definitions. Reference skills (SDK knowledge, always-on): `mem0/`, `mem0-cli/`, `mem0-vercel-ai-sdk/`. Pipeline skills (run on demand): `mem0-integrate/`, `mem0-test-integration/` |
|
||||
| `docs/` | Documentation site (Mintlify) |
|
||||
| `tests/` | Python SDK tests (pytest) |
|
||||
| `evaluation/` | Benchmarking framework — LOCOMO evals, experiment runner, score generation |
|
||||
@@ -387,7 +387,9 @@ Model Context Protocol support in multiple places:
|
||||
### Plugin & Skills System
|
||||
|
||||
- `mem0-plugin/` provides integrations for Claude Code, Cursor, and Codex via MCP server connections and lifecycle hooks for automatic memory capture.
|
||||
- `skills/` contains structured skill definitions for AI agents, covering SDK usage, CLI workflows, and Vercel AI SDK patterns.
|
||||
- `skills/` contains structured skill definitions for AI agents, split into two categories:
|
||||
- **Reference skills** (always-on SDK knowledge): `mem0` (Python + TS SDKs, framework integrations), `mem0-cli` (terminal workflows), `mem0-vercel-ai-sdk` (Vercel AI provider).
|
||||
- **Pipeline skills** (run on demand): `mem0-integrate` wires Mem0 into an existing repo via a TDD pipeline; `mem0-test-integration` verifies what the integrator produced on the same branch. The two are loosely coupled via `.mem0-integration/` artifacts.
|
||||
|
||||
### Adding a New Provider
|
||||
|
||||
|
||||
@@ -1313,7 +1313,7 @@ async def delete_memory(memory_id: str):
|
||||
- **Documentation**: https://docs.mem0.ai
|
||||
- **GitHub Repository**: https://github.com/mem0ai/mem0
|
||||
- **Discord Community**: https://mem0.dev/DiG
|
||||
- **Platform**: https://app.mem0.ai
|
||||
- **Platform**: https://app.mem0.ai?utm_source=oss&utm_medium=llm
|
||||
- **Research Paper**: https://mem0.ai/research
|
||||
- **Examples**: https://github.com/mem0ai/mem0/tree/main/examples
|
||||
|
||||
|
||||
@@ -42,9 +42,6 @@ clean:
|
||||
test:
|
||||
hatch run test
|
||||
|
||||
test-py-3.9:
|
||||
hatch run dev_py_3_9:test
|
||||
|
||||
test-py-3.10:
|
||||
hatch run dev_py_3_10:test
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://mem0.ai/research"><strong>📄 Building Production-Ready AI Agents with Scalable Long-Term Memory →</strong></a>
|
||||
<a href="https://mem0.ai/research"><strong>📄 Benchmarking Mem0's token-efficient memory algorithm →</strong></a>
|
||||
</p>
|
||||
|
||||
## New Memory Algorithm (April 2026)
|
||||
@@ -47,7 +47,7 @@
|
||||
| Benchmark | Old | New | Tokens | Latency p50 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| **LoCoMo** | 71.4 | **91.6** | 7.0K | 0.88s |
|
||||
| **LongMemEval** | 67.8 | **93.4** | 6.8K | 1.09s |
|
||||
| **LongMemEval** | 67.8 | **94.8** | 6.8K | 1.09s |
|
||||
| **BEAM (1M)** | — | **64.1** | 6.7K | 1.00s |
|
||||
| **BEAM (10M)** | — | **48.6** | 6.9K | 1.05s |
|
||||
|
||||
@@ -58,12 +58,13 @@ All benchmarks run on the same production-representative model stack. Single-pas
|
||||
- **Agent-generated facts are first-class** -- when an agent confirms an action, that information is now stored with equal weight.
|
||||
- **Entity linking** -- entities are extracted, embedded, and linked across memories for retrieval boosting.
|
||||
- **Multi-signal retrieval** -- semantic, BM25 keyword, and entity matching scored in parallel and fused.
|
||||
- **Temporal Reasoning** -- time-aware retrieval that ranks the right dated instance for queries about current state, past events, and upcoming plans.
|
||||
|
||||
See the [migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for upgrade instructions. The [evaluation framework](https://github.com/mem0ai/memory-benchmarks) is open-sourced so anyone can reproduce the numbers.
|
||||
|
||||
## Research Highlights
|
||||
- **91.6 on LoCoMo** -- +20 points over the previous algorithm
|
||||
- **93.4 on LongMemEval** -- +26 points, with +53.6 on assistant memory recall
|
||||
- **94.8 on LongMemEval** -- +27 points, with +53.6 on assistant memory recall
|
||||
- **64.1 on BEAM (1M)** -- production-scale memory evaluation at 1M tokens
|
||||
- [Read the full paper](https://mem0.ai/research)
|
||||
|
||||
@@ -85,18 +86,17 @@ See the [migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for upgra
|
||||
|
||||
## 🚀 Quickstart Guide <a name="quickstart"></a>
|
||||
|
||||
Choose between our hosted platform or self-hosted package:
|
||||
| | Library | Self-Hosted Server | Cloud Platform |
|
||||
|---|---------|-------------------|----------------|
|
||||
| **Best for** | Testing, prototyping | Teams running on their own infrastructure | Zero-ops production use |
|
||||
| **Setup** | `pip install mem0ai` | `docker compose up` | Sign up at [app.mem0.ai](https://app.mem0.ai?utm_source=oss&utm_medium=readme) |
|
||||
| **Dashboard** | -- | [Yes](https://docs.mem0.ai/open-source/setup) | Yes |
|
||||
| **Auth & API Keys** | -- | Yes | Yes |
|
||||
| **Advanced Features** | -- | Teasers | All included |
|
||||
|
||||
### Hosted Platform
|
||||
Just testing? Use the library. Building for a team? Self-hosted. Want zero ops? Cloud.
|
||||
|
||||
Get up and running in minutes with automatic updates, analytics, and enterprise security.
|
||||
|
||||
1. Sign up on [Mem0 Platform](https://app.mem0.ai)
|
||||
2. Embed the memory layer via SDK or API keys
|
||||
|
||||
### Self-Hosted (Open Source)
|
||||
|
||||
Install the sdk via pip:
|
||||
### Library (pip / npm)
|
||||
|
||||
```bash
|
||||
pip install mem0ai
|
||||
@@ -110,10 +110,30 @@ python -m spacy download en_core_web_sm
|
||||
```
|
||||
|
||||
Install sdk via npm:
|
||||
|
||||
```bash
|
||||
npm install mem0ai
|
||||
```
|
||||
|
||||
### Self-Hosted Server
|
||||
|
||||
> **Note:** Self-hosted auth is on by default. Upgrading from a pre-auth build? Set `ADMIN_API_KEY`, register an admin through the wizard, or `AUTH_DISABLED=true` for local dev only. See [upgrade notes](https://docs.mem0.ai/open-source/setup#upgrade-notes).
|
||||
|
||||
```bash
|
||||
# Recommended: one command — start the stack, create an admin, issue the first API key.
|
||||
cd server && make bootstrap
|
||||
|
||||
# Manual: start the stack and finish setup via the browser wizard.
|
||||
cd server && docker compose up -d # http://localhost:3000
|
||||
```
|
||||
|
||||
See the [self-hosted docs](https://docs.mem0.ai/open-source/overview) for configuration.
|
||||
|
||||
### Cloud Platform
|
||||
|
||||
1. Sign up on [Mem0 Platform](https://app.mem0.ai?utm_source=oss&utm_medium=readme)
|
||||
2. Embed the memory layer via SDK or API keys
|
||||
|
||||
### CLI
|
||||
|
||||
Manage memories from your terminal:
|
||||
@@ -128,6 +148,27 @@ mem0 search "What does Alice prefer?" --user-id alice
|
||||
|
||||
See the [CLI documentation](https://docs.mem0.ai/platform/cli) for the full command reference.
|
||||
|
||||
### Agent Skills
|
||||
|
||||
Teach your AI coding assistant (Claude Code, Codex, Cursor, Windsurf, OpenCode, OpenClaw, and any tool that supports the skills standard) how to build with Mem0. Two categories:
|
||||
|
||||
**Reference skills — always on** (SDK knowledge loaded into the assistant's context):
|
||||
|
||||
```bash
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-cli
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-vercel-ai-sdk
|
||||
```
|
||||
|
||||
**Pipeline skills — run on demand** (execute an end-to-end workflow in an existing repo):
|
||||
|
||||
```bash
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-integrate
|
||||
npx skills add https://github.com/mem0ai/mem0 --skill mem0-test-integration
|
||||
```
|
||||
|
||||
Use `/mem0-integrate` to wire Mem0 into an existing repo via a test-first pipeline, then `/mem0-test-integration` to verify. See the [skills catalog](./skills/) or [Vibecoding with Mem0](https://docs.mem0.ai/vibecoding) for the full picture.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Mem0 requires an LLM to function, with `gpt-5-mini` from OpenAI as the default. However, it supports a variety of LLMs; for details, refer to our [Supported LLMs documentation](https://docs.mem0.ai/components/llms/overview).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mem0/cli",
|
||||
"version": "0.2.3",
|
||||
"version": "0.2.4",
|
||||
"description": "The official CLI for mem0 — the memory layer for AI agents",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -15,7 +15,6 @@ export interface AddOptions {
|
||||
infer?: boolean;
|
||||
expires?: string;
|
||||
categories?: string[];
|
||||
enableGraph?: boolean;
|
||||
}
|
||||
|
||||
export interface SearchOptions {
|
||||
@@ -29,7 +28,6 @@ export interface SearchOptions {
|
||||
keyword?: boolean;
|
||||
filters?: Record<string, unknown>;
|
||||
fields?: string[];
|
||||
enableGraph?: boolean;
|
||||
}
|
||||
|
||||
export interface ListOptions {
|
||||
@@ -42,7 +40,6 @@ export interface ListOptions {
|
||||
category?: string;
|
||||
after?: string;
|
||||
before?: string;
|
||||
enableGraph?: boolean;
|
||||
}
|
||||
|
||||
export interface DeleteOptions {
|
||||
|
||||
@@ -115,10 +115,9 @@ export class PlatformBackend implements Backend {
|
||||
if (opts.infer === false) payload.infer = false;
|
||||
if (opts.expires) payload.expiration_date = opts.expires;
|
||||
if (opts.categories) payload.categories = opts.categories;
|
||||
if (opts.enableGraph) payload.enable_graph = true;
|
||||
payload.source = "CLI";
|
||||
|
||||
return (await this._request("POST", "/v1/memories/", {
|
||||
return (await this._request("POST", "/v3/memories/add/", {
|
||||
json: payload,
|
||||
})) as Record<string, unknown>;
|
||||
}
|
||||
@@ -176,10 +175,9 @@ export class PlatformBackend implements Backend {
|
||||
if (opts.rerank) payload.rerank = true;
|
||||
if (opts.keyword) payload.keyword_search = true;
|
||||
if (opts.fields) payload.fields = opts.fields;
|
||||
if (opts.enableGraph) payload.enable_graph = true;
|
||||
payload.source = "CLI";
|
||||
|
||||
const result = (await this._request("POST", "/v2/memories/search/", {
|
||||
const result = (await this._request("POST", "/v3/memories/search/", {
|
||||
json: payload,
|
||||
})) as unknown;
|
||||
if (Array.isArray(result)) return result;
|
||||
@@ -227,10 +225,9 @@ export class PlatformBackend implements Backend {
|
||||
extraFilters: Object.keys(extra).length > 0 ? extra : undefined,
|
||||
});
|
||||
if (apiFilters) payload.filters = apiFilters;
|
||||
if (opts.enableGraph) payload.enable_graph = true;
|
||||
payload.source = "CLI";
|
||||
|
||||
const result = (await this._request("POST", "/v2/memories/", {
|
||||
const result = (await this._request("POST", "/v3/memories/", {
|
||||
json: payload,
|
||||
params,
|
||||
})) as unknown;
|
||||
|
||||
@@ -96,7 +96,7 @@ export function printError(message: string, hint?: string): void {
|
||||
const resolvedHint =
|
||||
hint ??
|
||||
(message.includes("Authentication failed")
|
||||
? `Run ${brand("mem0 init")} to reconfigure your API key · https://app.mem0.ai/dashboard/api-keys`
|
||||
? `Run ${brand("mem0 init")} to reconfigure your API key · https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cli-node`
|
||||
: undefined);
|
||||
if (resolvedHint) {
|
||||
console.error(` ${dim(resolvedHint)}`);
|
||||
|
||||
@@ -29,7 +29,6 @@ export function cmdConfigShow(opts: { output?: string } = {}): void {
|
||||
agent_id: config.defaults.agentId || null,
|
||||
app_id: config.defaults.appId || null,
|
||||
run_id: config.defaults.runId || null,
|
||||
enable_graph: config.defaults.enableGraph,
|
||||
},
|
||||
platform: {
|
||||
api_key: redactKey(config.platform.apiKey),
|
||||
@@ -56,7 +55,6 @@ export function cmdConfigShow(opts: { output?: string } = {}): void {
|
||||
]);
|
||||
table.push(["defaults.app_id", config.defaults.appId || dim("(not set)")]);
|
||||
table.push(["defaults.run_id", config.defaults.runId || dim("(not set)")]);
|
||||
table.push(["defaults.enable_graph", String(config.defaults.enableGraph)]);
|
||||
table.push(["", ""]);
|
||||
|
||||
// Platform
|
||||
|
||||
@@ -185,7 +185,7 @@ function promptLine(label: string, defaultValue?: string): Promise<string> {
|
||||
async function setupPlatform(config: Mem0Config): Promise<void> {
|
||||
console.log();
|
||||
console.log(
|
||||
` ${dim("Get your API key at https://app.mem0.ai/dashboard/api-keys")}`,
|
||||
` ${dim("Get your API key at https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cli-node")}`,
|
||||
);
|
||||
console.log();
|
||||
|
||||
@@ -234,7 +234,7 @@ async function validatePlatform(config: Mem0Config): Promise<void> {
|
||||
} else {
|
||||
printError(
|
||||
`Could not connect: ${status.error ?? "Unknown error"}`,
|
||||
"Visit https://app.mem0.ai/dashboard/api-keys to get a new key, or run mem0 init again.",
|
||||
"Visit https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cli-node to get a new key, or run mem0 init again.",
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -49,7 +49,6 @@ export async function cmdAdd(
|
||||
noInfer: boolean;
|
||||
expires?: string;
|
||||
categories?: string;
|
||||
enableGraph: boolean;
|
||||
output: string;
|
||||
},
|
||||
): Promise<void> {
|
||||
@@ -140,7 +139,6 @@ export async function cmdAdd(
|
||||
infer: !opts.noInfer,
|
||||
expires: opts.expires,
|
||||
categories: cats,
|
||||
enableGraph: opts.enableGraph,
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -225,7 +223,6 @@ export async function cmdSearch(
|
||||
keyword: boolean;
|
||||
filterJson?: string;
|
||||
fields?: string;
|
||||
enableGraph: boolean;
|
||||
output: string;
|
||||
},
|
||||
): Promise<void> {
|
||||
@@ -274,7 +271,6 @@ export async function cmdSearch(
|
||||
keyword: opts.keyword,
|
||||
filters,
|
||||
fields: fieldList,
|
||||
enableGraph: opts.enableGraph,
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -368,7 +364,6 @@ export async function cmdList(
|
||||
category?: string;
|
||||
after?: string;
|
||||
before?: string;
|
||||
enableGraph: boolean;
|
||||
output: string;
|
||||
},
|
||||
): Promise<void> {
|
||||
@@ -396,7 +391,6 @@ export async function cmdList(
|
||||
category: opts.category,
|
||||
after: opts.after,
|
||||
before: opts.before,
|
||||
enableGraph: opts.enableGraph,
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
@@ -63,7 +63,7 @@ export async function cmdStatus(
|
||||
` ${dim("Run")} ${brand("mem0 init")} ${dim("to reconfigure your API key")}`,
|
||||
);
|
||||
lines.push(
|
||||
` ${dim("Get a key at")} ${brand("https://app.mem0.ai/dashboard/api-keys")}`,
|
||||
` ${dim("Get a key at")} ${brand("https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cli-node")}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ export interface DefaultsConfig {
|
||||
agentId: string;
|
||||
appId: string;
|
||||
runId: string;
|
||||
enableGraph: boolean;
|
||||
}
|
||||
|
||||
export interface TelemetryConfig {
|
||||
@@ -50,7 +49,6 @@ export function createDefaultConfig(): Mem0Config {
|
||||
agentId: "",
|
||||
appId: "",
|
||||
runId: "",
|
||||
enableGraph: false,
|
||||
},
|
||||
platform: {
|
||||
apiKey: "",
|
||||
@@ -87,8 +85,6 @@ export function loadConfig(): Mem0Config {
|
||||
config.defaults.agentId = defaults.agent_id ?? "";
|
||||
config.defaults.appId = defaults.app_id ?? "";
|
||||
config.defaults.runId = defaults.run_id ?? "";
|
||||
config.defaults.enableGraph = defaults.enable_graph ?? false;
|
||||
|
||||
const telemetry = data.telemetry ?? {};
|
||||
config.telemetry.anonymousId = telemetry.anonymous_id ?? "";
|
||||
}
|
||||
@@ -104,12 +100,6 @@ export function loadConfig(): Mem0Config {
|
||||
config.defaults.agentId = process.env.MEM0_AGENT_ID;
|
||||
if (process.env.MEM0_APP_ID) config.defaults.appId = process.env.MEM0_APP_ID;
|
||||
if (process.env.MEM0_RUN_ID) config.defaults.runId = process.env.MEM0_RUN_ID;
|
||||
if (process.env.MEM0_ENABLE_GRAPH) {
|
||||
config.defaults.enableGraph = ["true", "1", "yes"].includes(
|
||||
process.env.MEM0_ENABLE_GRAPH.toLowerCase(),
|
||||
);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -123,7 +113,6 @@ export function saveConfig(config: Mem0Config): void {
|
||||
agent_id: config.defaults.agentId,
|
||||
app_id: config.defaults.appId,
|
||||
run_id: config.defaults.runId,
|
||||
enable_graph: config.defaults.enableGraph,
|
||||
},
|
||||
platform: {
|
||||
api_key: config.platform.apiKey,
|
||||
@@ -154,7 +143,6 @@ const KEY_MAP: Record<string, [keyof Mem0Config, string]> = {
|
||||
"defaults.agent_id": ["defaults", "agentId"],
|
||||
"defaults.app_id": ["defaults", "appId"],
|
||||
"defaults.run_id": ["defaults", "runId"],
|
||||
"defaults.enable_graph": ["defaults", "enableGraph"],
|
||||
// Short-form aliases
|
||||
api_key: ["platform", "apiKey"],
|
||||
base_url: ["platform", "baseUrl"],
|
||||
@@ -163,7 +151,6 @@ const KEY_MAP: Record<string, [keyof Mem0Config, string]> = {
|
||||
agent_id: ["defaults", "agentId"],
|
||||
app_id: ["defaults", "appId"],
|
||||
run_id: ["defaults", "runId"],
|
||||
enable_graph: ["defaults", "enableGraph"],
|
||||
};
|
||||
|
||||
export function getNestedValue(config: Mem0Config, dottedKey: string): unknown {
|
||||
|
||||
+1
-24
@@ -134,18 +134,6 @@ function resolveIds(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve graph tri-state: --no-graph > --graph > config default.
|
||||
*/
|
||||
function resolveGraph(
|
||||
config: Mem0Config,
|
||||
opts: { graph?: boolean; noGraph?: boolean },
|
||||
): boolean {
|
||||
if (opts.noGraph) return false;
|
||||
if (opts.graph) return true;
|
||||
return config.defaults.enableGraph;
|
||||
}
|
||||
|
||||
// ── Main program ──────────────────────────────────────────────────────────
|
||||
|
||||
program
|
||||
@@ -236,8 +224,6 @@ program
|
||||
.option("--no-infer", "Skip inference, store raw.")
|
||||
.option("--expires <date>", "Expiration date (YYYY-MM-DD).")
|
||||
.option("--categories <value>", "Categories (JSON array or comma-separated).")
|
||||
.option("--graph", "Enable graph memory extraction.", false)
|
||||
.option("--no-graph", "Disable graph memory extraction.")
|
||||
.option("-o, --output <format>", "Output format: text, json, quiet.", "text")
|
||||
.option("--api-key <key>", "Override API key.")
|
||||
.option("--base-url <url>", "Override API base URL.")
|
||||
@@ -253,9 +239,8 @@ program
|
||||
opts.baseUrl,
|
||||
);
|
||||
const ids = resolveIds(config, opts);
|
||||
const enableGraph = resolveGraph(config, opts);
|
||||
const output = isAgent ? "agent" : opts.output;
|
||||
await cmdAdd(backend, text, { ...ids, ...opts, enableGraph, output });
|
||||
await cmdAdd(backend, text, { ...ids, ...opts, output });
|
||||
});
|
||||
|
||||
// ── Memory: search ────────────────────────────────────────────────────────
|
||||
@@ -285,8 +270,6 @@ program
|
||||
.option("--keyword", "Use keyword search.", false)
|
||||
.option("--filter <json>", "Advanced filter expression (JSON).")
|
||||
.option("--fields <list>", "Specific fields to return (comma-separated).")
|
||||
.option("--graph", "Enable graph in search.", false)
|
||||
.option("--no-graph", "Disable graph in search.")
|
||||
.option("-o, --output <format>", "Output: text, json, table.", "text")
|
||||
.option("--api-key <key>", "Override API key.")
|
||||
.option("--base-url <url>", "Override API base URL.")
|
||||
@@ -310,7 +293,6 @@ program
|
||||
opts.baseUrl,
|
||||
);
|
||||
const ids = resolveIds(config, opts);
|
||||
const enableGraph = resolveGraph(config, opts);
|
||||
const output = isAgent ? "agent" : opts.output;
|
||||
await cmdSearch(backend, resolvedQuery, {
|
||||
...ids,
|
||||
@@ -320,7 +302,6 @@ program
|
||||
keyword: opts.keyword,
|
||||
filterJson: opts.filter,
|
||||
fields: opts.fields,
|
||||
enableGraph,
|
||||
output,
|
||||
});
|
||||
});
|
||||
@@ -364,8 +345,6 @@ program
|
||||
.option("--category <name>", "Filter by category.")
|
||||
.option("--after <date>", "Created after (YYYY-MM-DD).")
|
||||
.option("--before <date>", "Created before (YYYY-MM-DD).")
|
||||
.option("--graph", "Enable graph in listing.", false)
|
||||
.option("--no-graph", "Disable graph in listing.")
|
||||
.option("-o, --output <format>", "Output: text, json, table.", "table")
|
||||
.option("--api-key <key>", "Override API key.")
|
||||
.option("--base-url <url>", "Override API base URL.")
|
||||
@@ -381,7 +360,6 @@ program
|
||||
opts.baseUrl,
|
||||
);
|
||||
const ids = resolveIds(config, opts);
|
||||
const enableGraph = resolveGraph(config, opts);
|
||||
const output = isAgent ? "agent" : opts.output;
|
||||
await cmdList(backend, {
|
||||
...ids,
|
||||
@@ -390,7 +368,6 @@ program
|
||||
category: opts.category,
|
||||
after: opts.after,
|
||||
before: opts.before,
|
||||
enableGraph,
|
||||
output,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -107,22 +107,22 @@ describe("CLI Integration — help and version", () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
it("add help has --graph flag", () => {
|
||||
it("add help has --output flag", () => {
|
||||
const result = run(["add", "--help"]);
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.stdout).toContain("--graph");
|
||||
expect(result.stdout).toContain("--output");
|
||||
});
|
||||
|
||||
it("search help has --graph flag", () => {
|
||||
it("search help has --rerank flag", () => {
|
||||
const result = run(["search", "--help"]);
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.stdout).toContain("--graph");
|
||||
expect(result.stdout).toContain("--rerank");
|
||||
});
|
||||
|
||||
it("list help has --graph flag", () => {
|
||||
it("list help has --category flag", () => {
|
||||
const result = run(["list", "--help"]);
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.stdout).toContain("--graph");
|
||||
expect(result.stdout).toContain("--category");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ describe("cmdAdd", () => {
|
||||
userId: "alice",
|
||||
immutable: false,
|
||||
noInfer: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "text",
|
||||
});
|
||||
expect(mockBackend.add).toHaveBeenCalledOnce();
|
||||
@@ -55,7 +55,7 @@ describe("cmdAdd", () => {
|
||||
messages: JSON.stringify([{ role: "user", content: "I love Python" }]),
|
||||
immutable: false,
|
||||
noInfer: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "text",
|
||||
});
|
||||
expect(mockBackend.add).toHaveBeenCalledOnce();
|
||||
@@ -67,7 +67,7 @@ describe("cmdAdd", () => {
|
||||
userId: "alice",
|
||||
immutable: false,
|
||||
noInfer: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "json",
|
||||
});
|
||||
expect(output).toContain("results");
|
||||
@@ -79,7 +79,7 @@ describe("cmdAdd", () => {
|
||||
userId: "alice",
|
||||
immutable: false,
|
||||
noInfer: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "quiet",
|
||||
});
|
||||
expect(output).not.toContain("dark mode");
|
||||
@@ -101,7 +101,7 @@ describe("cmdAdd deduplicates PENDING", () => {
|
||||
userId: "alice",
|
||||
immutable: false,
|
||||
noInfer: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "text",
|
||||
});
|
||||
expect(output.match(/Queued/g)?.length).toBe(1);
|
||||
@@ -114,7 +114,7 @@ describe("cmdAdd deduplicates PENDING", () => {
|
||||
userId: "alice",
|
||||
immutable: false,
|
||||
noInfer: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "json",
|
||||
});
|
||||
const data = JSON.parse(output);
|
||||
@@ -130,7 +130,7 @@ describe("cmdAdd deduplicates PENDING", () => {
|
||||
userId: "alice",
|
||||
immutable: false,
|
||||
noInfer: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "agent",
|
||||
});
|
||||
const data = JSON.parse(output);
|
||||
@@ -148,7 +148,7 @@ describe("cmdSearch", () => {
|
||||
threshold: 0.3,
|
||||
rerank: false,
|
||||
keyword: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "text",
|
||||
});
|
||||
expect(output).toContain("Found 2");
|
||||
@@ -162,7 +162,7 @@ describe("cmdSearch", () => {
|
||||
threshold: 0.3,
|
||||
rerank: false,
|
||||
keyword: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "json",
|
||||
});
|
||||
expect(output).toContain("memory");
|
||||
@@ -177,7 +177,7 @@ describe("cmdSearch", () => {
|
||||
threshold: 0.3,
|
||||
rerank: false,
|
||||
keyword: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "text",
|
||||
});
|
||||
expect(errOutput).toContain("No memories found");
|
||||
@@ -205,7 +205,7 @@ describe("cmdList", () => {
|
||||
userId: "alice",
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
enableGraph: false,
|
||||
|
||||
output: "table",
|
||||
});
|
||||
expect(output).toContain("dark mode");
|
||||
@@ -218,7 +218,7 @@ describe("cmdList", () => {
|
||||
userId: "alice",
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
enableGraph: false,
|
||||
|
||||
output: "text",
|
||||
});
|
||||
expect(errOutput).toContain("No memories found");
|
||||
@@ -316,7 +316,7 @@ describe("agent mode", () => {
|
||||
userId: "alice",
|
||||
immutable: false,
|
||||
noInfer: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "agent",
|
||||
});
|
||||
const parsed = JSON.parse(output.trim());
|
||||
@@ -336,7 +336,7 @@ describe("agent mode", () => {
|
||||
threshold: 0.3,
|
||||
rerank: false,
|
||||
keyword: false,
|
||||
enableGraph: false,
|
||||
|
||||
output: "agent",
|
||||
});
|
||||
const parsed = JSON.parse(output.trim());
|
||||
@@ -361,7 +361,7 @@ describe("agent mode", () => {
|
||||
userId: "alice",
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
enableGraph: false,
|
||||
|
||||
output: "agent",
|
||||
});
|
||||
const parsed = JSON.parse(output.trim());
|
||||
|
||||
@@ -64,7 +64,6 @@ describe("createDefaultConfig", () => {
|
||||
expect(config.platform.baseUrl).toBe("https://api.mem0.ai");
|
||||
expect(config.platform.apiKey).toBe("");
|
||||
expect(config.defaults.userId).toBe("");
|
||||
expect(config.defaults.enableGraph).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -105,9 +104,4 @@ describe("setNestedValue", () => {
|
||||
expect(config.defaults.userId).toBe("bob");
|
||||
});
|
||||
|
||||
it("coerces boolean for enable_graph", () => {
|
||||
const config = createDefaultConfig();
|
||||
expect(setNestedValue(config, "defaults.enable_graph", "true")).toBe(true);
|
||||
expect(config.defaults.enableGraph).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "mem0-cli"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
description = "The official CLI for mem0 — the memory layer for AI agents"
|
||||
readme = "README.md"
|
||||
license = "Apache-2.0"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""mem0 CLI — the command-line interface for the mem0 memory layer."""
|
||||
|
||||
__version__ = "0.2.3"
|
||||
__version__ = "0.2.4"
|
||||
|
||||
@@ -267,8 +267,6 @@ def add(
|
||||
categories: str | None = typer.Option(
|
||||
None, "--categories", help="Categories (JSON array or comma-separated)."
|
||||
),
|
||||
graph: bool = typer.Option(False, "--graph", help="Enable graph memory extraction."),
|
||||
no_graph: bool = typer.Option(False, "--no-graph", help="Disable graph memory extraction."),
|
||||
output: str = typer.Option(
|
||||
"text", "--output", "-o", help="Output format: text, json, quiet.", rich_help_panel="Output"
|
||||
),
|
||||
@@ -295,13 +293,6 @@ def add(
|
||||
backend, config = _get_backend_and_config(api_key, base_url)
|
||||
ids = _resolve_ids(config, user_id=user_id, agent_id=agent_id, app_id=app_id, run_id=run_id)
|
||||
|
||||
if no_graph:
|
||||
graph_enabled = False
|
||||
elif graph:
|
||||
graph_enabled = True
|
||||
else:
|
||||
graph_enabled = config.defaults.enable_graph
|
||||
|
||||
cmd_add(
|
||||
backend,
|
||||
text,
|
||||
@@ -313,7 +304,6 @@ def add(
|
||||
no_infer=no_infer,
|
||||
expires=expires,
|
||||
categories=categories,
|
||||
enable_graph=graph_enabled,
|
||||
output=output,
|
||||
)
|
||||
|
||||
@@ -357,12 +347,6 @@ def search(
|
||||
help="Specific fields to return (comma-separated).",
|
||||
rich_help_panel="Search",
|
||||
),
|
||||
graph: bool = typer.Option(
|
||||
False, "--graph", help="Enable graph in search.", rich_help_panel="Search"
|
||||
),
|
||||
no_graph: bool = typer.Option(
|
||||
False, "--no-graph", help="Disable graph in search.", rich_help_panel="Search"
|
||||
),
|
||||
output: str = typer.Option(
|
||||
"text", "--output", "-o", help="Output: text, json, table.", rich_help_panel="Output"
|
||||
),
|
||||
@@ -396,13 +380,6 @@ def search(
|
||||
backend, config = _get_backend_and_config(api_key, base_url)
|
||||
ids = _resolve_ids(config, user_id=user_id, agent_id=agent_id, app_id=app_id, run_id=run_id)
|
||||
|
||||
if no_graph:
|
||||
graph_enabled = False
|
||||
elif graph:
|
||||
graph_enabled = True
|
||||
else:
|
||||
graph_enabled = config.defaults.enable_graph
|
||||
|
||||
cmd_search(
|
||||
backend,
|
||||
query,
|
||||
@@ -413,7 +390,6 @@ def search(
|
||||
keyword=keyword,
|
||||
filter_json=filter_json,
|
||||
fields=fields,
|
||||
enable_graph=graph_enabled,
|
||||
output=output,
|
||||
)
|
||||
|
||||
@@ -480,12 +456,6 @@ def list_cmd(
|
||||
before: str | None = typer.Option(
|
||||
None, "--before", help="Created before (YYYY-MM-DD).", rich_help_panel="Filters"
|
||||
),
|
||||
graph: bool = typer.Option(
|
||||
False, "--graph", help="Enable graph in listing.", rich_help_panel="Filters"
|
||||
),
|
||||
no_graph: bool = typer.Option(
|
||||
False, "--no-graph", help="Disable graph in listing.", rich_help_panel="Filters"
|
||||
),
|
||||
output: str = typer.Option(
|
||||
"table", "--output", "-o", help="Output: text, json, table.", rich_help_panel="Output"
|
||||
),
|
||||
@@ -511,13 +481,6 @@ def list_cmd(
|
||||
backend, config = _get_backend_and_config(api_key, base_url)
|
||||
ids = _resolve_ids(config, user_id=user_id, agent_id=agent_id, app_id=app_id, run_id=run_id)
|
||||
|
||||
if no_graph:
|
||||
graph_enabled = False
|
||||
elif graph:
|
||||
graph_enabled = True
|
||||
else:
|
||||
graph_enabled = config.defaults.enable_graph
|
||||
|
||||
cmd_list(
|
||||
backend,
|
||||
**ids,
|
||||
@@ -526,7 +489,6 @@ def list_cmd(
|
||||
category=category,
|
||||
after=after,
|
||||
before=before,
|
||||
enable_graph=graph_enabled,
|
||||
output=output,
|
||||
)
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ class Backend(ABC):
|
||||
infer: bool = True,
|
||||
expires: str | None = None,
|
||||
categories: list[str] | None = None,
|
||||
enable_graph: bool = False,
|
||||
) -> dict: ...
|
||||
|
||||
@abstractmethod
|
||||
@@ -44,7 +43,6 @@ class Backend(ABC):
|
||||
keyword: bool = False,
|
||||
filters: dict | None = None,
|
||||
fields: list[str] | None = None,
|
||||
enable_graph: bool = False,
|
||||
) -> list[dict]: ...
|
||||
|
||||
@abstractmethod
|
||||
@@ -63,7 +61,6 @@ class Backend(ABC):
|
||||
category: str | None = None,
|
||||
after: str | None = None,
|
||||
before: str | None = None,
|
||||
enable_graph: bool = False,
|
||||
) -> list[dict]: ...
|
||||
|
||||
@abstractmethod
|
||||
|
||||
@@ -64,7 +64,6 @@ class PlatformBackend(Backend):
|
||||
infer: bool = True,
|
||||
expires: str | None = None,
|
||||
categories: list[str] | None = None,
|
||||
enable_graph: bool = False,
|
||||
) -> dict:
|
||||
payload: dict[str, Any] = {}
|
||||
|
||||
@@ -91,11 +90,9 @@ class PlatformBackend(Backend):
|
||||
payload["expiration_date"] = expires
|
||||
if categories:
|
||||
payload["categories"] = categories
|
||||
if enable_graph:
|
||||
payload["enable_graph"] = True
|
||||
payload["source"] = "CLI"
|
||||
|
||||
return self._request("POST", "/v1/memories/", json=payload)
|
||||
return self._request("POST", "/v3/memories/add/", json=payload)
|
||||
|
||||
def _build_filters(
|
||||
self,
|
||||
@@ -106,7 +103,7 @@ class PlatformBackend(Backend):
|
||||
run_id: str | None = None,
|
||||
extra_filters: dict | None = None,
|
||||
) -> dict | None:
|
||||
"""Build a filters dict for v2 API endpoints.
|
||||
"""Build a filters dict for v3 API endpoints.
|
||||
|
||||
Entity IDs are ANDed (all provided IDs must match).
|
||||
Extra filters (date ranges, categories) are also ANDed.
|
||||
@@ -152,7 +149,6 @@ class PlatformBackend(Backend):
|
||||
keyword: bool = False,
|
||||
filters: dict | None = None,
|
||||
fields: list[str] | None = None,
|
||||
enable_graph: bool = False,
|
||||
) -> list[dict]:
|
||||
payload: dict[str, Any] = {"query": query, "top_k": top_k, "threshold": threshold}
|
||||
|
||||
@@ -171,11 +167,9 @@ class PlatformBackend(Backend):
|
||||
payload["keyword_search"] = True
|
||||
if fields:
|
||||
payload["fields"] = fields
|
||||
if enable_graph:
|
||||
payload["enable_graph"] = True
|
||||
payload["source"] = "CLI"
|
||||
|
||||
result = self._request("POST", "/v2/memories/search/", json=payload)
|
||||
result = self._request("POST", "/v3/memories/search/", json=payload)
|
||||
return (
|
||||
result
|
||||
if isinstance(result, list)
|
||||
@@ -197,12 +191,11 @@ class PlatformBackend(Backend):
|
||||
category: str | None = None,
|
||||
after: str | None = None,
|
||||
before: str | None = None,
|
||||
enable_graph: bool = False,
|
||||
) -> list[dict]:
|
||||
payload: dict[str, Any] = {}
|
||||
params = {"page": str(page), "page_size": str(page_size)}
|
||||
|
||||
# Build filters for v2 API — entity IDs and date filters go inside "filters"
|
||||
# Build filters — entity IDs and date filters go inside "filters"
|
||||
extra: dict[str, Any] = {}
|
||||
if category:
|
||||
extra["categories"] = {"contains": category}
|
||||
@@ -220,11 +213,9 @@ class PlatformBackend(Backend):
|
||||
)
|
||||
if api_filters:
|
||||
payload["filters"] = api_filters
|
||||
if enable_graph:
|
||||
payload["enable_graph"] = True
|
||||
payload["source"] = "CLI"
|
||||
|
||||
result = self._request("POST", "/v2/memories/", json=payload, params=params)
|
||||
result = self._request("POST", "/v3/memories/", json=payload, params=params)
|
||||
return (
|
||||
result
|
||||
if isinstance(result, list)
|
||||
|
||||
@@ -146,7 +146,7 @@ def timed_status(console: Console, message: str):
|
||||
if "Authentication failed" in ctx.error_msg:
|
||||
_err.print(
|
||||
f" [{DIM_COLOR}]Run [bold]mem0 init[/bold] to reconfigure your API key"
|
||||
f" · [bold]https://app.mem0.ai/dashboard/api-keys[/bold][/]"
|
||||
f" · [bold]https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cli-python[/bold][/]"
|
||||
)
|
||||
raise
|
||||
else:
|
||||
|
||||
@@ -39,7 +39,6 @@ def cmd_config_show(*, output: str = "text") -> None:
|
||||
"agent_id": config.defaults.agent_id or None,
|
||||
"app_id": config.defaults.app_id or None,
|
||||
"run_id": config.defaults.run_id or None,
|
||||
"enable_graph": config.defaults.enable_graph,
|
||||
},
|
||||
"platform": {
|
||||
"api_key": redact_key(config.platform.api_key),
|
||||
@@ -73,10 +72,6 @@ def cmd_config_show(*, output: str = "text") -> None:
|
||||
"defaults.run_id",
|
||||
config.defaults.run_id or f"[{DIM_COLOR}](not set)[/]",
|
||||
)
|
||||
table.add_row(
|
||||
"defaults.enable_graph",
|
||||
str(config.defaults.enable_graph).lower(),
|
||||
)
|
||||
table.add_row("", "")
|
||||
|
||||
# Platform
|
||||
|
||||
@@ -19,7 +19,13 @@ from mem0_cli.branding import (
|
||||
print_info,
|
||||
print_success,
|
||||
)
|
||||
from mem0_cli.config import CONFIG_FILE, DEFAULT_BASE_URL, Mem0Config, load_config, save_config
|
||||
from mem0_cli.config import (
|
||||
CONFIG_FILE,
|
||||
DEFAULT_BASE_URL,
|
||||
Mem0Config,
|
||||
load_config,
|
||||
save_config,
|
||||
)
|
||||
|
||||
console = Console()
|
||||
err_console = Console(stderr=True)
|
||||
@@ -352,7 +358,9 @@ def run_init(
|
||||
def _setup_platform(config: Mem0Config) -> None:
|
||||
"""Platform setup flow."""
|
||||
console.print()
|
||||
console.print(f" [{DIM_COLOR}]Get your API key at https://app.mem0.ai/dashboard/api-keys[/]")
|
||||
console.print(
|
||||
f" [{DIM_COLOR}]Get your API key at https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cli-python[/]"
|
||||
)
|
||||
console.print()
|
||||
|
||||
console.print(f" [{BRAND_COLOR}]API Key[/]: ", end="")
|
||||
@@ -404,7 +412,7 @@ def _validate_platform(config: Mem0Config) -> None:
|
||||
print_error(
|
||||
err_console,
|
||||
f"Could not connect: {status.get('error', 'Unknown error')}",
|
||||
hint="Visit https://app.mem0.ai/dashboard/api-keys to get a new key, then run mem0 init again.",
|
||||
hint="Visit https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cli-python to get a new key, then run mem0 init again.",
|
||||
)
|
||||
except Exception as e:
|
||||
print_error(err_console, f"Connection test failed: {e}")
|
||||
|
||||
@@ -62,7 +62,6 @@ def cmd_add(
|
||||
no_infer: bool,
|
||||
expires: str | None,
|
||||
categories: str | None,
|
||||
enable_graph: bool = False,
|
||||
output: str = "text",
|
||||
) -> None:
|
||||
"""Add a memory."""
|
||||
@@ -145,7 +144,6 @@ def cmd_add(
|
||||
infer=not no_infer,
|
||||
expires=expires,
|
||||
categories=cats,
|
||||
enable_graph=enable_graph,
|
||||
)
|
||||
except Exception as e:
|
||||
ts.error_msg = str(e)
|
||||
@@ -226,7 +224,6 @@ def cmd_search(
|
||||
keyword: bool,
|
||||
filter_json: str | None,
|
||||
fields: str | None,
|
||||
enable_graph: bool = False,
|
||||
output: str = "text",
|
||||
) -> None:
|
||||
"""Search memories."""
|
||||
@@ -269,7 +266,6 @@ def cmd_search(
|
||||
keyword=keyword,
|
||||
filters=filters,
|
||||
fields=field_list,
|
||||
enable_graph=enable_graph,
|
||||
)
|
||||
except Exception as e:
|
||||
print_error(err_console, str(e))
|
||||
@@ -356,7 +352,6 @@ def cmd_list(
|
||||
category: str | None,
|
||||
after: str | None,
|
||||
before: str | None,
|
||||
enable_graph: bool = False,
|
||||
output: str = "table",
|
||||
) -> None:
|
||||
"""List memories."""
|
||||
@@ -385,7 +380,6 @@ def cmd_list(
|
||||
category=category,
|
||||
after=after,
|
||||
before=before,
|
||||
enable_graph=enable_graph,
|
||||
)
|
||||
except Exception as e:
|
||||
print_error(err_console, str(e))
|
||||
|
||||
@@ -77,7 +77,7 @@ def cmd_status(
|
||||
f" [{DIM_COLOR}]Run [bold]mem0 init[/bold] to reconfigure your API key[/]"
|
||||
)
|
||||
lines.append(
|
||||
f" [{DIM_COLOR}]Get a key at [bold]https://app.mem0.ai/dashboard/api-keys[/bold][/]"
|
||||
f" [{DIM_COLOR}]Get a key at [bold]https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cli-python[/bold][/]"
|
||||
)
|
||||
lines.append(f" [{DIM_COLOR}]Latency:[/] {_elapsed:.2f}s")
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ class DefaultsConfig:
|
||||
agent_id: str = ""
|
||||
app_id: str = ""
|
||||
run_id: str = ""
|
||||
enable_graph: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -60,7 +59,6 @@ SHORT_KEY_ALIASES: dict[str, str] = {
|
||||
"agent_id": "defaults.agent_id",
|
||||
"app_id": "defaults.app_id",
|
||||
"run_id": "defaults.run_id",
|
||||
"enable_graph": "defaults.enable_graph",
|
||||
}
|
||||
|
||||
|
||||
@@ -91,8 +89,6 @@ def load_config() -> Mem0Config:
|
||||
config.defaults.agent_id = defaults.get("agent_id", "")
|
||||
config.defaults.app_id = defaults.get("app_id", "")
|
||||
config.defaults.run_id = defaults.get("run_id", "")
|
||||
config.defaults.enable_graph = defaults.get("enable_graph", False)
|
||||
|
||||
telemetry = data.get("telemetry", {})
|
||||
config.telemetry.anonymous_id = telemetry.get("anonymous_id", "")
|
||||
|
||||
@@ -121,10 +117,6 @@ def load_config() -> Mem0Config:
|
||||
if env_run_id:
|
||||
config.defaults.run_id = env_run_id
|
||||
|
||||
env_graph = os.environ.get("MEM0_ENABLE_GRAPH")
|
||||
if env_graph:
|
||||
config.defaults.enable_graph = env_graph.lower() in ("true", "1", "yes")
|
||||
|
||||
return config
|
||||
|
||||
|
||||
@@ -139,7 +131,6 @@ def save_config(config: Mem0Config) -> None:
|
||||
"agent_id": config.defaults.agent_id,
|
||||
"app_id": config.defaults.app_id,
|
||||
"run_id": config.defaults.run_id,
|
||||
"enable_graph": config.defaults.enable_graph,
|
||||
},
|
||||
"platform": {
|
||||
"api_key": config.platform.api_key,
|
||||
|
||||
@@ -224,24 +224,13 @@ class TestCLIIsolated:
|
||||
|
||||
|
||||
class TestCLINewFeatures:
|
||||
"""Tests for MCP parity features: --graph, --limit, entities delete."""
|
||||
"""Tests for MCP parity features: --limit, entities delete."""
|
||||
|
||||
def test_add_help_has_graph(self):
|
||||
result = _run(["add", "--help"])
|
||||
assert result.returncode == 0
|
||||
assert "--graph" in result.stdout
|
||||
|
||||
def test_search_help_has_graph_and_limit(self):
|
||||
def test_search_help_has_limit(self):
|
||||
result = _run(["search", "--help"])
|
||||
assert result.returncode == 0
|
||||
assert "--graph" in result.stdout
|
||||
assert "--limit" in result.stdout
|
||||
|
||||
def test_list_help_has_graph(self):
|
||||
result = _run(["list", "--help"])
|
||||
assert result.returncode == 0
|
||||
assert "--graph" in result.stdout
|
||||
|
||||
def test_delete_entity_via_delete_flag(self):
|
||||
"""delete --entity should appear in help output."""
|
||||
result = _run(["delete", "--help"])
|
||||
|
||||
@@ -997,85 +997,6 @@ class TestEntitiesDeleteCommand:
|
||||
mock_backend.delete_entities.assert_not_called()
|
||||
|
||||
|
||||
class TestEnableGraph:
|
||||
def test_add_with_graph(self, mock_backend):
|
||||
console, _buf = _make_console()
|
||||
err_console, _err_buf = _make_err_console()
|
||||
with (
|
||||
patch("mem0_cli.commands.memory.console", console),
|
||||
patch("mem0_cli.commands.memory.err_console", err_console),
|
||||
):
|
||||
cmd_add(
|
||||
mock_backend,
|
||||
"test",
|
||||
user_id="alice",
|
||||
agent_id=None,
|
||||
app_id=None,
|
||||
run_id=None,
|
||||
messages=None,
|
||||
file=None,
|
||||
metadata=None,
|
||||
immutable=False,
|
||||
no_infer=False,
|
||||
expires=None,
|
||||
categories=None,
|
||||
enable_graph=True,
|
||||
output="text",
|
||||
)
|
||||
call_kwargs = mock_backend.add.call_args
|
||||
assert call_kwargs.kwargs.get("enable_graph") is True
|
||||
|
||||
def test_search_with_graph(self, mock_backend):
|
||||
console, _buf = _make_console()
|
||||
err_console, _err_buf = _make_err_console()
|
||||
with (
|
||||
patch("mem0_cli.commands.memory.console", console),
|
||||
patch("mem0_cli.commands.memory.err_console", err_console),
|
||||
):
|
||||
cmd_search(
|
||||
mock_backend,
|
||||
"test",
|
||||
user_id="alice",
|
||||
agent_id=None,
|
||||
app_id=None,
|
||||
run_id=None,
|
||||
top_k=10,
|
||||
threshold=0.3,
|
||||
rerank=False,
|
||||
keyword=False,
|
||||
filter_json=None,
|
||||
fields=None,
|
||||
enable_graph=True,
|
||||
output="text",
|
||||
)
|
||||
call_kwargs = mock_backend.search.call_args
|
||||
assert call_kwargs.kwargs.get("enable_graph") is True
|
||||
|
||||
def test_list_with_graph(self, mock_backend):
|
||||
console, _buf = _make_console()
|
||||
err_console, _err_buf = _make_err_console()
|
||||
with (
|
||||
patch("mem0_cli.commands.memory.console", console),
|
||||
patch("mem0_cli.commands.memory.err_console", err_console),
|
||||
):
|
||||
cmd_list(
|
||||
mock_backend,
|
||||
user_id="alice",
|
||||
agent_id=None,
|
||||
app_id=None,
|
||||
run_id=None,
|
||||
page=1,
|
||||
page_size=100,
|
||||
category=None,
|
||||
after=None,
|
||||
before=None,
|
||||
enable_graph=True,
|
||||
output="table",
|
||||
)
|
||||
call_kwargs = mock_backend.list_memories.call_args
|
||||
assert call_kwargs.kwargs.get("enable_graph") is True
|
||||
|
||||
|
||||
class TestEventCommands:
|
||||
def test_event_list_table(self, mock_backend):
|
||||
console, buf = _make_console()
|
||||
|
||||
@@ -121,46 +121,6 @@ class TestConfig:
|
||||
assert config.defaults.agent_id == ""
|
||||
assert config.defaults.app_id == ""
|
||||
assert config.defaults.run_id == ""
|
||||
assert config.defaults.enable_graph is False
|
||||
|
||||
def test_enable_graph_save_and_load(self, isolate_config):
|
||||
config = Mem0Config()
|
||||
config.defaults.enable_graph = True
|
||||
save_config(config)
|
||||
loaded = load_config()
|
||||
assert loaded.defaults.enable_graph is True
|
||||
|
||||
def test_enable_graph_env_var_true(self, isolate_config, monkeypatch):
|
||||
monkeypatch.setenv("MEM0_ENABLE_GRAPH", "true")
|
||||
loaded = load_config()
|
||||
assert loaded.defaults.enable_graph is True
|
||||
|
||||
def test_enable_graph_env_var_false(self, isolate_config, monkeypatch):
|
||||
config = Mem0Config()
|
||||
config.defaults.enable_graph = True
|
||||
save_config(config)
|
||||
monkeypatch.setenv("MEM0_ENABLE_GRAPH", "false")
|
||||
loaded = load_config()
|
||||
assert loaded.defaults.enable_graph is False
|
||||
|
||||
def test_backward_compat_no_enable_graph_key(self, isolate_config):
|
||||
"""Old config files without 'enable_graph' key should default to False."""
|
||||
import json
|
||||
|
||||
from mem0_cli.config import CONFIG_FILE, ensure_config_dir
|
||||
|
||||
ensure_config_dir()
|
||||
data = {
|
||||
"version": 1,
|
||||
"defaults": {"user_id": "alice"},
|
||||
"platform": {"api_key": "m0-test", "base_url": "https://api.mem0.ai"},
|
||||
}
|
||||
with open(CONFIG_FILE, "w") as f:
|
||||
json.dump(data, f)
|
||||
|
||||
loaded = load_config()
|
||||
assert loaded.defaults.enable_graph is False
|
||||
assert loaded.defaults.user_id == "alice"
|
||||
|
||||
|
||||
class TestNestedAccess:
|
||||
@@ -192,11 +152,6 @@ class TestNestedAccess:
|
||||
assert set_nested_value(config, "defaults.user_id", "bob")
|
||||
assert config.defaults.user_id == "bob"
|
||||
|
||||
def test_set_defaults_enable_graph(self):
|
||||
config = Mem0Config()
|
||||
assert set_nested_value(config, "defaults.enable_graph", "true")
|
||||
assert config.defaults.enable_graph is True
|
||||
|
||||
|
||||
class TestResolveIds:
|
||||
def test_cli_flag_overrides_default(self):
|
||||
|
||||
@@ -10,7 +10,7 @@ description: "REST APIs for memory management, search, and entity operations"
|
||||
Mem0 provides a comprehensive REST API for integrating advanced memory capabilities into your applications. Create, search, update, and manage memories across users, agents, and custom entities with simple HTTP requests.
|
||||
|
||||
<Info>
|
||||
**Quick start:** Get your API key from the <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 Dashboard</a> and make your first memory operation in minutes.
|
||||
**Quick start:** Get your API key from the <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=api-reference" rel="nofollow">Mem0 Dashboard</a> and make your first memory operation in minutes.
|
||||
</Info>
|
||||
|
||||
---
|
||||
@@ -87,7 +87,7 @@ All API requests require authentication using Token-based authentication. Includ
|
||||
Authorization: Token <your-api-key>
|
||||
```
|
||||
|
||||
Get your API key from the <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 Dashboard</a>.
|
||||
Get your API key from the <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=api-reference" rel="nofollow">Mem0 Dashboard</a>.
|
||||
|
||||
<Warning>
|
||||
**Keep your API key secure.** Never expose it in client-side code or public repositories. Use environment variables and server-side requests only.
|
||||
|
||||
@@ -5,3 +5,5 @@ openapi: get /v1/event/{event_id}/
|
||||
---
|
||||
|
||||
Retrieve details about a specific event by passing its `event_id`. This endpoint is particularly helpful for tracking the status, payload, and completion details of asynchronous memory operations.
|
||||
|
||||
For `POST /v3/memories/add/`, the event confirms that the write pipeline completed. Temporal reasoning enrichment runs asynchronously by default, so the event may be `SUCCEEDED` slightly before temporal ranking signals are available to subsequent `search` calls.
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
---
|
||||
title: 'Add Memories'
|
||||
description: "Add facts, messages, or metadata to a user memory store with support for async processing and event tracking."
|
||||
openapi: post /v1/memories/
|
||||
title: Add Memories
|
||||
description: "Add facts, messages, or metadata to a user memory store with async processing and event tracking via the V3 additive pipeline."
|
||||
openapi: post /v3/memories/add/
|
||||
---
|
||||
|
||||
Add new facts, messages, or metadata to a user’s memory store. The Add Memories endpoint accepts either raw text or conversational turns and commits them asynchronously so the memory is ready for later search, retrieval, and graph queries.
|
||||
Extract and store memories from a conversation using the V3 additive pipeline. The endpoint uses single-pass ADD-only extraction — one LLM call, no UPDATE/DELETE. Memories accumulate over time; nothing is overwritten.
|
||||
|
||||
## Endpoint
|
||||
|
||||
- **Method**: `POST`
|
||||
- **URL**: `/v1/memories/`
|
||||
- **URL**: `/v3/memories/add/`
|
||||
- **Content-Type**: `application/json`
|
||||
|
||||
Memories are processed asynchronously by default. The response contains queued events you can track while the platform finalizes enrichment.
|
||||
Processing is asynchronous. The response returns an `event_id` you can poll via `GET /v1/event/{event_id}/`.
|
||||
|
||||
## Required headers
|
||||
|
||||
@@ -23,7 +23,7 @@ Memories are processed asynchronously by default. The response contains queued e
|
||||
|
||||
## Request body
|
||||
|
||||
Provide at least one message or direct memory string. Most callers supply `messages` so Mem0 can infer structured memories as part of ingestion.
|
||||
Provide conversation messages for Mem0 to extract memories from. At least one entity ID (`user_id`, `agent_id`, `app_id`, or `run_id`) is required so the memory is scoped to a session. Entity IDs are accepted at the top level.
|
||||
|
||||
<CodeGroup>
|
||||
```json Basic request
|
||||
@@ -43,12 +43,15 @@ Provide at least one message or direct memory string. Most callers supply `messa
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `user_id` | string | No* | Associates the memory with a user. Provide when you want the memory scoped to a specific identity. |
|
||||
| `messages` | array | No* | Conversation turns for Mem0 to infer memories from. Each object should include `role` and `content`. |
|
||||
| `messages` | array | Yes | Conversation turns for Mem0 to extract memories from. Each object should include `role` and `content`. |
|
||||
| `user_id` | string | No* | Associates the memory with a user. |
|
||||
| `agent_id` | string | No* | Associates the memory with an agent. |
|
||||
| `run_id` | string | No* | Associates the memory with a run. |
|
||||
| `app_id` | string | No* | Associates the memory with an app. |
|
||||
| `metadata` | object | Optional | Custom key/value metadata (e.g., `{"topic": "preferences"}`). |
|
||||
| `infer` | boolean (default `true`) | Optional | Set to `false` to skip inference and store the provided text as-is. |
|
||||
|
||||
> \* Provide at least one `messages` entry to describe what you are storing. For scoped memories, include `user_id`. You can also attach `agent_id`, `app_id`, `run_id`, `project_id`, or `org_id` to refine ownership.
|
||||
> \* At least one entity ID (`user_id`, `agent_id`, `app_id`, or `run_id`) is required.
|
||||
|
||||
<Tip>
|
||||
Need more details? See [all request parameters](#body-messages) below for complete field descriptions, types, and constraints.
|
||||
@@ -56,19 +59,15 @@ Provide at least one message or direct memory string. Most callers supply `messa
|
||||
|
||||
## Response
|
||||
|
||||
Successful requests return an array of events queued for processing. Each event includes the generated memory text and an identifier you can persist for auditing.
|
||||
The request is queued for background processing. The response contains an `event_id` for tracking status.
|
||||
|
||||
<CodeGroup>
|
||||
```json 200 response
|
||||
[
|
||||
{
|
||||
"id": "mem_01JF8ZS4Y0R0SPM13R5R6H32CJ",
|
||||
"event": "ADD",
|
||||
"data": {
|
||||
"memory": "The user moved to Austin in 2025."
|
||||
}
|
||||
}
|
||||
]
|
||||
{
|
||||
"message": "Memory processing has been queued for background execution",
|
||||
"status": "PENDING",
|
||||
"event_id": "evt-uuid"
|
||||
}
|
||||
```
|
||||
|
||||
```json 400 response
|
||||
@@ -81,3 +80,6 @@ Successful requests return an array of events queued for processing. Each event
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Info>
|
||||
Poll the event status via `GET /v1/event/{event_id}/`. Status will be `SUCCEEDED` or `FAILED` once processing completes.
|
||||
</Info>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
---
|
||||
title: "Get Memories"
|
||||
description: "Retrieve memories with advanced filtering using logical operators like AND, OR, NOT, and comparison queries."
|
||||
openapi: post /v2/memories/
|
||||
description: "Retrieve memories with paginated results and advanced filtering using logical operators like AND, OR, NOT, and comparison queries."
|
||||
openapi: post /v3/memories/
|
||||
---
|
||||
|
||||
The v2 get memories API is powerful and flexible, allowing for more precise memory listing without the need for a search query. It supports complex logical operations (AND, OR, NOT) and comparison operators for advanced filtering capabilities. The comparison operators include:
|
||||
List memories scoped by filters with paginated results. Entity IDs (`user_id`, `agent_id`, `app_id`, `run_id`) **must** be passed inside the `filters` object — top-level entity IDs are rejected with 400.
|
||||
|
||||
The `filters` object supports complex logical operations (AND, OR, NOT) and comparison operators:
|
||||
|
||||
- `in`: Matches any of the values specified
|
||||
- `gte`: Greater than or equal to
|
||||
@@ -15,6 +17,8 @@ The v2 get memories API is powerful and flexible, allowing for more precise memo
|
||||
- `icontains`: Case-insensitive containment check
|
||||
- `*`: Wildcard character that matches everything
|
||||
|
||||
Pass `page` and `page_size` as query parameters to paginate through results.
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
memories = client.get_all(
|
||||
@@ -27,12 +31,17 @@ memories = client.get_all(
|
||||
"created_at": {"gte": "2024-07-01", "lte": "2024-07-31"}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
page=1,
|
||||
page_size=50
|
||||
)
|
||||
```
|
||||
|
||||
```python Output
|
||||
{
|
||||
"count": 2,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": "f4cbdb08-7062-4f3e-8eb2-9f5c80dfe64c",
|
||||
@@ -46,10 +55,12 @@ memories = client.get_all(
|
||||
"created_at": "2024-07-05T15:30:00Z",
|
||||
"updated_at": "2024-07-05T15:30:00Z"
|
||||
}
|
||||
],
|
||||
"total": 2
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<Info>
|
||||
The response is a paginated envelope with `count`, `next`, `previous`, and `results`. Use `page` and `page_size` query params to step through results.
|
||||
</Info>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
---
|
||||
title: 'Search Memories'
|
||||
description: "Search memories with semantic queries and advanced filtering using logical and comparison operators."
|
||||
openapi: post /v2/memories/search/
|
||||
description: "Search memories with hybrid retrieval (semantic + BM25 + entity matching) and advanced filtering using logical and comparison operators."
|
||||
openapi: post /v3/memories/search/
|
||||
---
|
||||
|
||||
The v2 search API is powerful and flexible, allowing for more precise memory retrieval. It supports complex logical operations (AND, OR, NOT) and comparison operators for advanced filtering capabilities. The comparison operators include:
|
||||
Relevance-ranked hybrid search across stored memories. V3 uses multi-signal retrieval — semantic, BM25 keyword, and entity matching scored in parallel and fused. The returned `score` is a combined `[0, 1]` value.
|
||||
|
||||
Entity IDs (`user_id`, `agent_id`, `app_id`, `run_id`) **must** be passed inside the `filters` object — top-level entity IDs are rejected with 400. At least one entity ID is required.
|
||||
|
||||
The `filters` object supports complex logical operations (AND, OR, NOT) and comparison operators:
|
||||
- `in`: Matches any of the values specified
|
||||
- `gte`: Greater than or equal to
|
||||
- `lte`: Less than or equal to
|
||||
@@ -14,6 +18,14 @@ The v2 search API is powerful and flexible, allowing for more precise memory ret
|
||||
- `icontains`: Case-insensitive containment check
|
||||
- `*`: Wildcard character that matches everything
|
||||
|
||||
### Search parameter defaults
|
||||
|
||||
| Parameter | V1/V2 | V3 |
|
||||
| --- | --- | --- |
|
||||
| `top_k` | Supported (default 10) | Supported (1-1000, default 10) |
|
||||
| `threshold` | No default | Default `0.1` (pass `0.0` to disable) |
|
||||
| `rerank` | Default `true` | Default `false` (pass `true` to enable) |
|
||||
|
||||
<CodeGroup>
|
||||
```python Platform API Example
|
||||
related_memories = client.search(
|
||||
@@ -33,20 +45,20 @@ related_memories = client.search(
|
||||
|
||||
```json Output
|
||||
{
|
||||
"memories": [
|
||||
"results": [
|
||||
{
|
||||
"id": "ea925981-272f-40dd-b576-be64e4871429",
|
||||
"memory": "Likes to play cricket and plays cricket on weekends.",
|
||||
"user_id": "alice",
|
||||
"metadata": {
|
||||
"category": "hobbies"
|
||||
},
|
||||
"score": 0.32116443111457704,
|
||||
"score": 0.82,
|
||||
"created_at": "2024-07-26T10:29:36.630547-07:00",
|
||||
"updated_at": null,
|
||||
"user_id": "alice",
|
||||
"agent_id": "sports-agent"
|
||||
"categories": ["hobbies"]
|
||||
}
|
||||
],
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -109,6 +109,19 @@ client.project.update(
|
||||
)
|
||||
```
|
||||
|
||||
#### Toggle Memory Decay
|
||||
|
||||
`decay` is a per-project boolean that turns on [Memory Decay](/platform/features/memory-decay) — a search-time ranking bias that reinforces recently-accessed memories and gently dampens stale ones. The flag is `false` by default; set it via the same project-update endpoint:
|
||||
|
||||
```bash cURL
|
||||
curl -X PATCH https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PROJECT_ID/ \
|
||||
-H "Authorization: Token $MEM0_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"decay": true}'
|
||||
```
|
||||
|
||||
The current state is returned on every project read (and supports `?fields=decay` for a minimal response). Toggling has no effect on stored memories, only on how v3 search ranks them.
|
||||
|
||||
### Delete Project
|
||||
|
||||
<Warning>
|
||||
|
||||
@@ -4,6 +4,34 @@ description: "Major product launches, headline features, and milestones for Mem0
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Update label="2026-05-13" description="Temporal Reasoning for Mem0 Platform v3">
|
||||
|
||||
**Temporal Reasoning — Time-Aware Retrieval for Platform v3**
|
||||
|
||||
Mem0 Platform v3 can now interpret time-aware memories and queries so assistants retrieve the right information for questions about the past, upcoming plans, and current state.
|
||||
|
||||
- **Time-aware search intent** — Queries like `last week`, `upcoming`, `right now`, and `as of March 2025` return contextually appropriate results automatically
|
||||
- **Enabled by default** — No per-request toggle required for v3 writes or searches
|
||||
- **Anchored relative queries** — `reference_date` anchors relative search phrases for tests, backfills, and reproducible demos
|
||||
- **Normal response shape** — Temporal reasoning affects ranking while preserving existing client response patterns
|
||||
|
||||
See [Temporal Reasoning](/platform/features/temporal-reasoning) for usage details.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-05-08" description="Memory Decay">
|
||||
|
||||
**Memory Decay — Recently-Used Memories Surface Higher, Automatically**
|
||||
|
||||
Per-project search-time ranking bias that boosts recently-touched memories and gently dampens stale ones. Off by default; opt in per project via the `decay` field on the project endpoint, or via `client.project.update(decay=True)` in the SDKs (Python `v2.0.2` / TypeScript `v3.0.3`).
|
||||
|
||||
- **Soft bias, never a filter.** The scaling factor stays in `0.3×–1.5×`. Decay can reorder candidates but never zeros them out — anything that surfaced before decay can still surface after.
|
||||
- **Reinforcement loop.** Every memory returned in a search has its access history updated, so frequently-used facts naturally float to the top over time.
|
||||
- **Public score still clamped to `[0, 1]`.** Existing API contract preserved; no client-side changes needed.
|
||||
- **v3 search only**, fully reversible. See [Memory Decay docs](/platform/features/memory-decay).
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-14" description="Mem0 SDK v2.0.0 / v3.0.0">
|
||||
|
||||
**New Memory Algorithm — State-of-the-Art Accuracy at ~3-4x Lower Cost**
|
||||
@@ -99,4 +127,4 @@ Major expansion of the provider ecosystem:
|
||||
|
||||
First skill launch — a dedicated Mem0 skill providing platform API reference, quickstart patterns, and integration examples directly inside agent sessions. Available on [skills.sh](https://skills.sh) for any compatible AI coding agent.
|
||||
|
||||
</Update>
|
||||
</Update>
|
||||
|
||||
@@ -4,6 +4,110 @@ description: "Release notes for the OpenClaw plugin and agent harness."
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Update label="2026-04-29" description="v1.0.11">
|
||||
|
||||
**New Features:**
|
||||
- **Skills-mode auto-setup:** `enableSkillsConfig()` now runs automatically after onboarding — enables triage, recall (with reranking + keyword search), and dream consolidation with `tools.profile = "full"` and disables the built-in session-memory hook to avoid conflicts
|
||||
- **Memory runtime capability:** Plugin now exposes `runtime.getMemorySearchManager()` and `resolveMemoryBackendConfig()` on the registered memory capability, enabling OpenClaw gateway to query memory status and backend config directly
|
||||
- **Dimension-aware collections:** OSS wizard detects embedder dimension changes and creates a new collection (`mem0_<dims>d`) automatically, with a warning about old memories being inaccessible under the new embedder
|
||||
- **Tool documentation in skills:** Both `memory-triage` and `memory-dream` SKILL.md files now include full tool reference sections listing all available tools with parameters
|
||||
|
||||
**Improvements:**
|
||||
- **Auto-capture and auto-recall default to enabled:** `autoCapture` and `autoRecall` now default to `true` (was `false`). Manifest descriptions updated accordingly. Ignored in skills mode
|
||||
- **`memory_update` over delete+add:** Skills now prefer `memory_update` for in-place edits — atomic and preserves edit history. Consolidation pattern updated: update best memory, delete redundant ones
|
||||
- **Search threshold lowered:** Default `searchThreshold` reduced from `0.5` to `0.1` for broader recall. Removed hardcoded `0.6` recall-specific override — all searches now use the configured threshold
|
||||
- **Embedder dimension propagation:** Vector store config auto-resolves dimensions from embedder config when not explicitly set. Syncs `dimension` and `embeddingModelDims` fields for Qdrant/PGVector compatibility
|
||||
- **Config file write safety:** `writeFullConfig()` now re-reads and deep-merges the `plugins` section before writing, preserving `installs` and `slots` written by the OpenClaw gateway
|
||||
- **Additional embedder models:** Added `mxbai-embed-large` (1024), `all-minilm` (384), and `snowflake-arctic-embed` (1024) to known embedder dimensions
|
||||
|
||||
**Security:**
|
||||
- Bumped `protobufjs` to `>=7.5.5` via pnpm overrides (GHSA-xq3m-2v4x-88gg) ([#5012](https://github.com/mem0ai/mem0/pull/5012))
|
||||
|
||||
**Fixes:**
|
||||
- Moved `bootstrapTelemetryFlag()` and removed `ensureInstallRecord()` from module-level side effects — both now run inside `register()` to avoid crashes when loaded outside OpenClaw gateway
|
||||
- Fixed OSS history DB path resolution: absolute paths no longer passed through `resolvePath()`, preventing double-prefix bugs
|
||||
- Manifest `providerAuthEnvVars` replaced with spec-compliant `setup.providers` format using `id` + `envVars`
|
||||
|
||||
**Dependencies:**
|
||||
- Bumped `mem0ai` from `3.0.1` to `3.0.2`
|
||||
- Bumped `pluginApi` and `minGatewayVersion` compat to `>=2026.4.24`
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-23" description="v1.0.10">
|
||||
|
||||
**Security:**
|
||||
- Telemetry `distinct_id` now uses SHA-256 instead of MD5 — prevents rainbow-table reversal of API key hashes
|
||||
- User email is now SHA-256 hashed before sending as `distinct_id` — no PII in telemetry payloads
|
||||
- Declared PostHog telemetry endpoint (`us.i.posthog.com`) in `providerEndpoints`
|
||||
|
||||
**Fixes:**
|
||||
- Fixed version-pinned install records preventing plugin updates. `ensureInstallRecord()` now detects semver-pinned specs (e.g. `@mem0/openclaw-mem0@1.0.7`) and rewrites them to `@latest` or `clawhub:` prefix so `openclaw plugins update` resolves to the newest release
|
||||
- Fixed `searchThreshold` default inconsistency: standardized to `0.3` across docs, README, and manifest
|
||||
- `PLUGIN_VERSION` now injected at build time via tsup `define` from `package.json` — no more hardcoded version strings
|
||||
|
||||
**Manifest Compliance:**
|
||||
- Removed non-spec fields: `requiredEnvVars`, `dataLocations`, `privacy`, `setup` (with `externalEndpoints`, `providers`, `requiresRuntime`, `postInstallHint`)
|
||||
- Replaced `setup.externalEndpoints` with spec-compliant `providerEndpoints` using `endpointClass` + `hosts` format
|
||||
- Env var declarations now rely solely on `providerAuthEnvVars` (already spec-compliant)
|
||||
|
||||
**Docs:**
|
||||
- Fixed `openclaw plugins update` command: uses plugin ID (`openclaw-mem0`), not npm package name (`@mem0/openclaw-mem0`)
|
||||
- Added update section to README
|
||||
- Removed redundant "Key Features" and "Conclusion" sections from integration docs
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-22" description="v1.0.9">
|
||||
|
||||
**Security & Compliance:**
|
||||
- Added top-level `requiredEnvVars` to plugin manifest, declaring env vars per mode (platform, OSS OpenAI, OSS Anthropic, OSS Ollama). Fixes ClaHub scanner "required env vars: none" mismatch
|
||||
- Added `sensitive: true` and descriptions to `apiKey` and `userEmail` in `configSchema` — previously only declared in `uiHints`
|
||||
- Added `default: false` with descriptions to `autoCapture` and `autoRecall` in `configSchema` so scanner can confirm opt-in defaults
|
||||
- Added `dataLocations` field to manifest declaring all persistence paths (config, vectorStore, historyDb, dreamState)
|
||||
- Added `privacy` field to manifest documenting data flow for platform vs open-source mode and credential storage guidance
|
||||
- Added `externalEndpoints` to `setup` section declaring api.mem0.ai and app.mem0.ai with purpose and requirement context
|
||||
|
||||
**Tests:**
|
||||
- Replaced direct `process.env` access in `tests/cli-commands.test.ts` and `tests/fs-safe.test.ts` with `vi.stubEnv`/`vi.unstubAllEnvs`. Fixes ClaHub static analysis flag for "environment variable access combined with network send"
|
||||
- 421 tests across 15 test files
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-21" description="v1.0.8">
|
||||
|
||||
**New Features:**
|
||||
- **OSS Onboarding Wizard:** New guided 4-step interactive setup for open-source mode — walks through LLM provider, embedding provider, vector store, and user ID selection with prefilled defaults
|
||||
- **Agent-Friendly CLI:** Added `--json` flag to all 16 CLI commands for machine-readable output. Agents can call `openclaw mem0 help --json` to discover every command and flag
|
||||
- **Non-Interactive OSS Setup:** Added `--mode open-source` with `--oss-llm`, `--oss-embedder`, `--oss-vector` flags for fully automated OSS configuration without prompts
|
||||
- **JSON Helpers Module:** New `cli/json-helpers.ts` with `jsonOut`, `jsonErr`, and `redactSecrets` utilities for consistent structured output
|
||||
|
||||
**Improvements:**
|
||||
- **Init Flow Redesigned:** Replaced 3-option flat menu with 2-level structure: Platform (email login or API key) and Open Source (guided wizard)
|
||||
- **Provider Selection:** LLM providers: OpenAI, Ollama, Anthropic. Embedding providers: OpenAI, Ollama. Vector stores: Qdrant, PGVector
|
||||
- **Input Prefill:** All prompts with defaults (base URL, user ID) now prefill the input field instead of showing defaults in brackets
|
||||
- **Smart Reuse:** When LLM and embedder use the same provider, API key and base URL are automatically reused from the LLM step
|
||||
- **Default Model:** Updated default LLM model to `gpt-5-mini`
|
||||
- **Manifest Compliance:** Removed undocumented fields, aligned env var declarations between SKILL.md and manifest, fixed `configSchema.required` for clean installs
|
||||
|
||||
**Tests:**
|
||||
- 404 tests across 15 test files (+3 new: `json-helpers.test.ts`, `oss-wizard.test.ts`, `cli-commands.test.ts`)
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-20" description="v1.0.7">
|
||||
|
||||
**New Features:**
|
||||
- **Chat-Based Setup:** Added chat-based Platform setup flow — users can now configure the plugin conversationally instead of editing config files manually
|
||||
- **Installation Docs Rewrite:** Rewrote README and integration docs with chat-first setup, numbered manual steps.
|
||||
|
||||
**Improvements:**
|
||||
- **SDK Upgrade:** Bumped `mem0ai` dependency to 3.0.1 for V3 API compatibility
|
||||
- **Config Cleanup:** Dropped deprecated `orgId`, `projectId`, `enableGraph` config options; updated CLI prompts ([#4734](https://github.com/mem0ai/mem0/pull/4734), [#4764](https://github.com/mem0ai/mem0/pull/4764))
|
||||
- **Noise Filtering:** Expanded noise patterns in memory add tool; handle leading text in JSON extraction
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-11" description="v1.0.6">
|
||||
|
||||
**Bug Fixes:**
|
||||
|
||||
@@ -4,6 +4,24 @@ description: "Release notes for the Mem0 hosted platform — backend, dashboard,
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Update label="2026-05-13" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Memory:** Added Temporal Reasoning for Platform v3 to improve ranking for time-aware queries such as `last week`, `upcoming`, `right now`, and `as of ...`
|
||||
- **Search:** Added `reference_date` support to anchor relative temporal queries for tests, backfills, and reproducible demos
|
||||
|
||||
**Improvements:**
|
||||
- **API:** Temporal reasoning preserves the normal client response shape for search and get-all results
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-05-04" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Memory Decay:** Per-project search-time ranking bias that boosts recently-used memories and gently dampens stale ones. Opt-in via `decay` on the project endpoint; off by default. The scaling factor stays in `0.3×–1.5×`, the public `score` remains clamped to `[0, 1]`, and the bias never filters a candidate out. See [Memory Decay docs](/platform/features/memory-decay).
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-16" description="">
|
||||
|
||||
**Improvements:**
|
||||
@@ -294,4 +312,3 @@ mode: "wide"
|
||||
- **Core:** Fixed unicode error in user_id, agent_id, run_id and app_id
|
||||
|
||||
</Update>
|
||||
|
||||
|
||||
+72
-1
@@ -7,6 +7,37 @@ mode: "wide"
|
||||
<Tabs>
|
||||
<Tab title="Python">
|
||||
|
||||
<Update label="2026-05-08" description="v2.0.2">
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Telemetry:** Stitch OSS and platform PostHog identities on `MemoryClient` init so `$identify` events fire and a single user is no longer tracked as two or three disconnected personas ([#5040](https://github.com/mem0ai/mem0/pull/5040))
|
||||
- **Security:** Harden against SQL injection and prompt injection ([#4997](https://github.com/mem0ai/mem0/pull/4997))
|
||||
|
||||
**New Features:**
|
||||
- **SDK:** Expose `decay` on `project.update` ([#5062](https://github.com/mem0ai/mem0/pull/5062))
|
||||
|
||||
**Improvements:**
|
||||
- **Plugin:** Hand `mem0` search decisions to the agent ([#4992](https://github.com/mem0ai/mem0/pull/4992))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-25" description="v2.0.1">
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Client:** Map `user_id`, `agent_id`, `run_id` entity params to filters in `GET /memories` ([#4960](https://github.com/mem0ai/mem0/pull/4960))
|
||||
- **Memory:** Honor `prompt` param in vector store extraction pipeline ([#4914](https://github.com/mem0ai/mem0/pull/4914))
|
||||
- **Memory:** Add missing `text_lemmatized` field in `AsyncMemory._create_memory` ([#4886](https://github.com/mem0ai/mem0/pull/4886))
|
||||
- **Memory:** Merge same-key operator dicts in AND metadata filters ([#4853](https://github.com/mem0ai/mem0/pull/4853))
|
||||
- **LLMs:** Narrow `_is_reasoning_model` check to not match `gpt-5.x` variants ([#4746](https://github.com/mem0ai/mem0/pull/4746))
|
||||
- **Vector Stores:** Add `ca_certs` config option for Elasticsearch vector store ([#3993](https://github.com/mem0ai/mem0/pull/3993))
|
||||
- **Vector Stores:** Add `agent_id` and `run_id` to Elasticsearch/OpenSearch default mappings ([#4906](https://github.com/mem0ai/mem0/pull/4906))
|
||||
- **Embeddings:** Set FastEmbed `embedding_dims` from model metadata at init ([#4711](https://github.com/mem0ai/mem0/pull/4711))
|
||||
|
||||
**Security:**
|
||||
- Bump vulnerable dependencies to patched versions ([#4835](https://github.com/mem0ai/mem0/pull/4835))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-14" description="v2.0.0">
|
||||
|
||||
**Major Release** — Python SDK with V3 memory pipeline, ADD-only extraction, and cleaned-up API surface.
|
||||
@@ -24,7 +55,7 @@ mode: "wide"
|
||||
**Breaking Changes:**
|
||||
- **`add()` returns ADD-only events** — No more `"UPDATE"` or `"DELETE"` events. Memories accumulate; nothing is overwritten ([#4805](https://github.com/mem0ai/mem0/pull/4805))
|
||||
- **`search()` default `threshold` is now `0.1`** — Pass `threshold=0.0` for previous behavior ([#4805](https://github.com/mem0ai/mem0/pull/4805))
|
||||
- **`search()` `score` is now a combined multi-signal score** — The top-level `score` fuses semantic similarity, BM25 keyword match, and entity boost into one value. Absolute numbers shift versus the old raw cosine score; retune any hard thresholds against representative queries. Per-signal scores are not exposed on the response ([#4805](https://github.com/mem0ai/mem0/pull/4805), [#4836](https://github.com/mem0ai/mem0/pull/4836))
|
||||
- **`search()` `score` is now a combined multi-signal score** — The top-level `score` fuses semantic similarity, BM25 keyword match, entity signals, and temporal boosts into one value. Absolute numbers shift versus the old raw cosine score; retune any hard thresholds against representative queries ([#4805](https://github.com/mem0ai/mem0/pull/4805), [#4836](https://github.com/mem0ai/mem0/pull/4836))
|
||||
- **`search()` default `rerank` is now `False`** — Pass `rerank=True` for previous behavior ([#4805](https://github.com/mem0ai/mem0/pull/4805))
|
||||
- **`top_k` default changed 100 → 20** in `Memory.get_all()` and `Memory.search()` (sync + async). Pass `top_k=100` explicitly to restore the old behavior ([#4843](https://github.com/mem0ai/mem0/pull/4843))
|
||||
- **Entity ID validation:** `user_id` / `agent_id` / `run_id` are trimmed; empty-string and whitespace-only values now raise `ValueError` ([#4843](https://github.com/mem0ai/mem0/pull/4843))
|
||||
@@ -893,6 +924,36 @@ See the [OSS v1 to v2 migration guide](https://docs.mem0.ai/migration/oss-v1-to-
|
||||
</Tab>
|
||||
|
||||
<Tab title="TypeScript">
|
||||
<Update label="2026-05-08" description="v3.0.3">
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Telemetry:** Stitch OSS and platform PostHog identities on `MemoryClient` init so `$identify` events fire and a single user is no longer tracked as two or three disconnected personas ([#5040](https://github.com/mem0ai/mem0/pull/5040))
|
||||
- **Vector Stores:** Fix inverted vector distance in PGVector implementation ([#4944](https://github.com/mem0ai/mem0/pull/4944))
|
||||
- **Security:** Harden against SQL injection and prompt injection ([#4997](https://github.com/mem0ai/mem0/pull/4997))
|
||||
|
||||
**New Features:**
|
||||
- **SDK:** Expose `decay` on `project.update` ([#5062](https://github.com/mem0ai/mem0/pull/5062))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-25" description="v3.0.2">
|
||||
|
||||
**Bug Fixes:**
|
||||
- **LLMs:** Forward `timeout` config to OpenAI client in JS OSS LLM providers ([#4770](https://github.com/mem0ai/mem0/pull/4770))
|
||||
|
||||
**Improvements:**
|
||||
- **Telemetry:** Harden TS telemetry version injection and require changelog entry on version bump ([#4900](https://github.com/mem0ai/mem0/pull/4900))
|
||||
- **Docs:** Update memory tool list, CLI usage, and config file reading logic ([#4861](https://github.com/mem0ai/mem0/pull/4861))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-20" description="v3.0.1">
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Telemetry:** SDK version is now injected into telemetry at build time via esbuild's `define`, replacing the two hardcoded version strings in `src/client/telemetry.ts` and `src/oss/src/utils/telemetry.ts`. Previously these were stuck at `2.1.36` and `2.1.34` while the published package was on `3.x`, so every telemetry event was reporting the wrong `client_version`. The placeholder is substituted with a string literal at bundle time — no runtime `require("./package.json")` in the shipped bundle ([#4897](https://github.com/mem0ai/mem0/pull/4897)).
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-14" description="v3.0.0">
|
||||
|
||||
**Major Release** — TypeScript SDK with V3 memory pipeline, camelCase parameters, and cleaned-up API surface.
|
||||
@@ -1262,6 +1323,16 @@ See the [TypeScript SDK migration guide](https://docs.mem0.ai/migration/ts-v2-to
|
||||
|
||||
<Tab title="CLI">
|
||||
|
||||
<Update label="2026-04-22" description="Python v0.2.4 / Node v0.2.4">
|
||||
|
||||
**New Features:**
|
||||
- **V3 API Routes:** Migrated `add`, `search`, and `list` commands from v1/v2 to v3 API endpoints — `POST /v3/memories/add/`, `POST /v3/memories/search/`, `POST /v3/memories/`. Aligns both CLIs with the Python and TypeScript SDKs which already use v3 ([#4916](https://github.com/mem0ai/mem0/pull/4916))
|
||||
|
||||
**Breaking Changes:**
|
||||
- **`--graph` / `--no-graph` removed:** The `enable_graph` config option, `--graph` and `--no-graph` CLI flags, and `MEM0_ENABLE_GRAPH` environment variable have been removed from both CLIs. Graph memory is now a project-level setting on the Platform ([#4916](https://github.com/mem0ai/mem0/pull/4916))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-11" description="Python v0.2.3 / Node v0.2.3">
|
||||
|
||||
**Bug Fixes:**
|
||||
|
||||
@@ -45,7 +45,7 @@ Before you begin, follow these steps to set up the demo application:
|
||||
OPENAI_API_KEY=your_openai_api_key
|
||||
MEM0_API_KEY=your_mem0_api_key
|
||||
```
|
||||
You can obtain your `MEM0_API_KEY` by signing up at <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 API Dashboard</a>.
|
||||
You can obtain your `MEM0_API_KEY` by signing up at <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cookbook-companions-quickstart" rel="nofollow">Mem0 API Dashboard</a>.
|
||||
|
||||
5. Start the development server:
|
||||
```bash
|
||||
|
||||
@@ -54,7 +54,6 @@ config = {
|
||||
"embedding_model_dims": 3072,
|
||||
}
|
||||
},
|
||||
"version": "v1.1",
|
||||
}
|
||||
|
||||
class PersonalTravelAssistant:
|
||||
@@ -154,7 +153,7 @@ class PersonalTravelAssistant:
|
||||
return answer
|
||||
|
||||
def get_memories(self, user_id):
|
||||
memories = self.memory.get_all(user_id=user_id)
|
||||
memories = self.memory.get_all(filters={"user_id": user_id})
|
||||
return [m['memory'] for m in memories.get('results', [])]
|
||||
|
||||
def search_memories(self, query, user_id):
|
||||
|
||||
@@ -38,7 +38,7 @@ client = MemoryClient(api_key="your-api-key")
|
||||
```
|
||||
|
||||
<Note>
|
||||
Replace `your-api-key` with your actual Mem0 API key from the <a href="https://app.mem0.ai" rel="nofollow">dashboard</a>. Without proper API authentication, memory operations will fail.
|
||||
Replace `your-api-key` with your actual Mem0 API key from the <a href="https://app.mem0.ai?utm_source=oss&utm_medium=cookbook-memory-ingestion" rel="nofollow">dashboard</a>. Without proper API authentication, memory operations will fail.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
@@ -17,7 +17,7 @@ from mem0 import MemoryClient
|
||||
client = MemoryClient(api_key="m0-...")
|
||||
```
|
||||
|
||||
Grab an API key from the <a href="https://app.mem0.ai/" rel="nofollow">Mem0 dashboard</a> to get started.
|
||||
Grab an API key from the <a href="https://app.mem0.ai/?utm_source=oss&utm_medium=cookbook-entity-partitioning" rel="nofollow">Mem0 dashboard</a> to get started.
|
||||
|
||||
## Store and Retrieve Scoped Memories
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ client = MemoryClient(api_key="your-api-key")
|
||||
```
|
||||
|
||||
<Note>
|
||||
Your API key needs export permissions to download memory data. Check your project settings on the <a href="https://app.mem0.ai" rel="nofollow">dashboard</a> if export operations fail with authentication errors.
|
||||
Your API key needs export permissions to download memory data. Check your project settings on the <a href="https://app.mem0.ai?utm_source=oss&utm_medium=cookbook-exporting-memories" rel="nofollow">dashboard</a> if export operations fail with authentication errors.
|
||||
</Note>
|
||||
|
||||
Let's add some sample memories to work with:
|
||||
|
||||
@@ -42,7 +42,7 @@ Create a `.env` file in the root of the project and add the following (you can u
|
||||
|
||||
```bash
|
||||
# Mem0 Configuration
|
||||
MEM0_API_KEY= # Mem0 API Key (get from https://app.mem0.ai/dashboard/api-keys)
|
||||
MEM0_API_KEY= # Mem0 API Key (get from https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cookbook-eliza-os)
|
||||
MEM0_USER_ID= # Default: eliza-os-user
|
||||
MEM0_PROVIDER= # Default: openai
|
||||
MEM0_PROVIDER_API_KEY= # API Key for the provider (OpenAI, Anthropic, etc.)
|
||||
|
||||
@@ -55,7 +55,7 @@ GEMINI_API_KEY=your-gemini-api-key-here
|
||||
```
|
||||
|
||||
<Note>
|
||||
Ensure you have your Mem0 API key from the <a href="https://app.mem0.ai" rel="nofollow">Mem0 Dashboard</a> and your Gemini API key from the [Google AI Studio](https://ai.studio/app/api-keys).
|
||||
Ensure you have your Mem0 API key from the <a href="https://app.mem0.ai?utm_source=oss&utm_medium=cookbook-gemini-3" rel="nofollow">Mem0 Dashboard</a> and your Gemini API key from the [Google AI Studio](https://ai.studio/app/api-keys).
|
||||
</Note>
|
||||
|
||||
## Gemini Memory Agent
|
||||
|
||||
@@ -41,7 +41,7 @@ Set up your environment variables:
|
||||
- `MEM0_API_KEY`: Your Mem0 Platform API key
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key
|
||||
|
||||
You can obtain your Mem0 Platform API key from the <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a>.
|
||||
You can obtain your Mem0 Platform API key from the <a href="https://app.mem0.ai?utm_source=oss&utm_medium=cookbook-llamaindex-multiagent" rel="nofollow">Mem0 Platform</a>.
|
||||
|
||||
## Complete Implementation
|
||||
|
||||
@@ -357,7 +357,7 @@ Based on our previous session, I remember we covered Vision Language Models and
|
||||
## Help & Resources
|
||||
|
||||
- [LlamaIndex Agent Workflows](https://docs.llamaindex.ai/en/stable/use_cases/agents/)
|
||||
- <a href="https://app.mem0.ai/" rel="nofollow">Mem0 Platform</a>
|
||||
- <a href="https://app.mem0.ai/?utm_source=oss&utm_medium=cookbook-llamaindex-multiagent" rel="nofollow">Mem0 Platform</a>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ os.environ["OPENAI_API_KEY"] = "<your-openai-api-key>"
|
||||
llm = OpenAI(model="gpt-5-mini")
|
||||
```
|
||||
|
||||
Initialize the Mem0 client. You can find your API key <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">here</a>. Read about Mem0 [Open Source](https://docs.mem0.ai/open-source/overview).
|
||||
Initialize the Mem0 client. You can find your API key <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cookbook-llamaindex-react" rel="nofollow">here</a>. Read about Mem0 [Open Source](https://docs.mem0.ai/open-source/overview).
|
||||
```python
|
||||
os.environ["MEM0_API_KEY"] = "<your-mem0-api-key>"
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ context = Mem0Context(user_id="user123")
|
||||
## Resources
|
||||
|
||||
- [Mem0 Documentation](https://docs.mem0.ai/introduction)
|
||||
- <a href="https://app.mem0.ai/dashboard" rel="nofollow">Mem0 Dashboard</a>
|
||||
- <a href="https://app.mem0.ai/dashboard?utm_source=oss&utm_medium=cookbook-agents-sdk-tool" rel="nofollow">Mem0 Dashboard</a>
|
||||
- [API Reference](https://docs.mem0.ai/api-reference)
|
||||
|
||||
---
|
||||
|
||||
@@ -42,7 +42,7 @@ This sets up Mem0 with:
|
||||
```python
|
||||
import boto3
|
||||
from opensearchpy import RequestsHttpConnection, AWSV4SignerAuth
|
||||
from mem0.memory.main import Memory
|
||||
from mem0 import Memory
|
||||
|
||||
region = 'us-west-2'
|
||||
service = 'aoss'
|
||||
|
||||
@@ -23,7 +23,7 @@ MEM0_API_KEY=your_mem0_api_key
|
||||
OPENAI_API_KEY=your_openai_api_key
|
||||
```
|
||||
|
||||
Get your Mem0 API key from the <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 Dashboard</a>.
|
||||
Get your Mem0 API key from the <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=cookbook-openai-tool-calls" rel="nofollow">Mem0 Dashboard</a>.
|
||||
|
||||
### Configuration
|
||||
|
||||
@@ -303,7 +303,7 @@ run().catch(console.error);
|
||||
## Resources
|
||||
|
||||
- [Mem0 Documentation](https://docs.mem0.ai/introduction)
|
||||
- <a href="https://app.mem0.ai/dashboard" rel="nofollow">Mem0 Dashboard</a>
|
||||
- <a href="https://app.mem0.ai/dashboard?utm_source=oss&utm_medium=cookbook-openai-tool-calls" rel="nofollow">Mem0 Dashboard</a>
|
||||
- [API Reference](https://docs.mem0.ai/api-reference)
|
||||
- [OpenAI Documentation](https://platform.openai.com/docs)
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ memory.delete_all(user_id="alice")
|
||||
## Put it into practice
|
||||
|
||||
- Review the <Link href="/api-reference/memory/delete-memory">Delete Memory API reference</Link>, plus <Link href="/api-reference/memory/batch-delete">Batch Delete</Link> and <Link href="/api-reference/memory/delete-memories">Filtered Delete</Link>.
|
||||
- Pair deletes with <Link href="/platform/features/expiration-date">Expiration Policies</Link> to automate retention.
|
||||
- Pair deletes with <Link href="/platform/features/platform-overview">Expiration Policies</Link> to automate retention.
|
||||
|
||||
## See it live
|
||||
|
||||
@@ -236,6 +236,6 @@ memory.delete_all(user_id="alice")
|
||||
title="Enable Expiration Policies"
|
||||
description="Automate retention with the platform’s expiration feature."
|
||||
icon="clock"
|
||||
href="/platform/features/expiration-date"
|
||||
href="/platform/features/platform-overview"
|
||||
/>
|
||||
</CardGroup>
|
||||
|
||||
@@ -156,6 +156,10 @@ const memories = memory.search("food preferences", {
|
||||
Expect an array of memory documents. Platform responses include vectors, metadata, and timestamps; OSS returns your stored schema.
|
||||
</Info>
|
||||
|
||||
<Note>
|
||||
On Mem0 Platform v3, time-aware queries use Temporal Reasoning internally while preserving the normal search response shape. See <Link href="/platform/features/temporal-reasoning">Temporal Reasoning</Link>.
|
||||
</Note>
|
||||
|
||||
## Filter patterns
|
||||
|
||||
Filters help narrow down search results. Common use cases:
|
||||
@@ -251,4 +255,4 @@ For the full list of filter logic, comparison operators, and optional search par
|
||||
icon="rocket"
|
||||
href="/cookbooks/operations/support-inbox"
|
||||
/>
|
||||
</CardGroup>
|
||||
</CardGroup>
|
||||
|
||||
+8
-5
@@ -72,7 +72,8 @@
|
||||
"platform/features/entity-scoped-memory",
|
||||
"platform/features/async-client",
|
||||
"platform/features/multimodal-support",
|
||||
"platform/features/custom-categories"
|
||||
"platform/features/custom-categories",
|
||||
"platform/features/temporal-reasoning"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -83,7 +84,8 @@
|
||||
"platform/advanced-memory-operations",
|
||||
"platform/features/criteria-retrieval",
|
||||
"platform/features/contextual-add",
|
||||
"platform/features/custom-instructions"
|
||||
"platform/features/custom-instructions",
|
||||
"platform/features/memory-decay"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -153,6 +155,7 @@
|
||||
"icon": "rocket",
|
||||
"pages": [
|
||||
"open-source/overview",
|
||||
"open-source/setup",
|
||||
"vibecoding",
|
||||
"open-source/python-quickstart",
|
||||
"open-source/node-quickstart"
|
||||
@@ -578,7 +581,7 @@
|
||||
"primary": {
|
||||
"type": "button",
|
||||
"label": "Your Dashboard",
|
||||
"href": "https://app.mem0.ai"
|
||||
"href": "https://app.mem0.ai?utm_source=oss&utm_medium=docs-nav"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
@@ -608,7 +611,7 @@
|
||||
"title": "Try in Playground",
|
||||
"description": "Open this example in the interactive Mem0 playground",
|
||||
"icon": "play",
|
||||
"href": "https://app.mem0.ai/playground"
|
||||
"href": "https://app.mem0.ai/playground?utm_source=oss&utm_medium=docs-nav"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -1142,4 +1145,4 @@
|
||||
"destination": "/introduction"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 293 KiB After Width: | Height: | Size: 139 KiB |
@@ -24,7 +24,7 @@ pip install mem0ai agentops python-dotenv
|
||||
2. Valid API keys:
|
||||
- [AgentOps API Key](https://app.agentops.ai/dashboard/api-keys)
|
||||
- OpenAI API Key (for LLM operations)
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 API Key</a> (optional, for cloud operations)
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-agentops" rel="nofollow">Mem0 API Key</a> (optional, for cloud operations)
|
||||
|
||||
## Basic Integration Example
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ pip install agno mem0ai python-dotenv
|
||||
```
|
||||
|
||||
2. Valid API keys:
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 API Key</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-agno" rel="nofollow">Mem0 API Key</a>
|
||||
- OpenAI API Key (for the agent model)
|
||||
|
||||
## Quick Integration (Using `Mem0Tools`)
|
||||
|
||||
@@ -19,7 +19,7 @@ pip install autogen mem0ai openai python-dotenv
|
||||
|
||||
First, we'll import the necessary libraries and set up our configurations.
|
||||
|
||||
<Note>Remember to get the Mem0 API key from <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
<Note>Remember to get the Mem0 API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-autogen" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
|
||||
```python
|
||||
import os
|
||||
@@ -32,7 +32,7 @@ load_dotenv()
|
||||
|
||||
# Configuration
|
||||
# OPENAI_API_KEY = 'sk-xxx' # Replace with your actual OpenAI API key
|
||||
# MEM0_API_KEY = 'your-mem0-key' # Replace with your actual Mem0 API key from https://app.mem0.ai
|
||||
# MEM0_API_KEY = 'your-mem0-key' # Replace with your actual Mem0 API key from https://app.mem0.ai?utm_source=oss&utm_medium=integration-autogen
|
||||
USER_ID = "alice"
|
||||
|
||||
# Set up OpenAI API key
|
||||
|
||||
@@ -49,7 +49,7 @@ Import necessary modules and configure Mem0:
|
||||
```python
|
||||
import boto3
|
||||
from opensearchpy import OpenSearch, RequestsHttpConnection, AWSV4SignerAuth
|
||||
from mem0.memory.main import Memory
|
||||
from mem0 import Memory
|
||||
|
||||
region = 'us-west-2'
|
||||
service = 'aoss'
|
||||
|
||||
@@ -18,7 +18,7 @@ In this guide, you'll:
|
||||
- **Python 3.12+**
|
||||
- **[uv](https://docs.astral.sh/uv/)** — Python package manager
|
||||
- **Node.js 18+** and **npm** — only needed if using the web console
|
||||
- A **Mem0 API key** from <a href="https://app.mem0.ai" rel="nofollow">app.mem0.ai</a>
|
||||
- A **Mem0 API key** from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-chatdev" rel="nofollow">app.mem0.ai</a>
|
||||
- An **OpenAI API key** (or another LLM provider supported by ChatDev)
|
||||
|
||||
## Setup and Configuration
|
||||
@@ -39,7 +39,7 @@ cd frontend && npm install && cd ..
|
||||
|
||||
Set up your environment variables in a `.env` file:
|
||||
|
||||
<Note>Get your Mem0 API key from <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
<Note>Get your Mem0 API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-chatdev" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
|
||||
```bash
|
||||
MEM0_API_KEY=your-mem0-api-key
|
||||
@@ -194,7 +194,7 @@ This means retrieval returns memories from **both** the user's scope and the age
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `api_key` | Yes | Mem0 API key from <a href="https://app.mem0.ai" rel="nofollow">app.mem0.ai</a> |
|
||||
| `api_key` | Yes | Mem0 API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-chatdev" rel="nofollow">app.mem0.ai</a> |
|
||||
| `user_id` | No | Scope memories to a specific user |
|
||||
| `agent_id` | No | Scope memories to a specific agent |
|
||||
|
||||
@@ -216,9 +216,9 @@ This means retrieval returns memories from **both** the user's scope and the age
|
||||
|
||||
- **No memories returned on first run** — This is expected. Memories are stored *after* the agent responds, so the first interaction has no prior context. Memories appear starting from the second interaction onward.
|
||||
- **`mem0ai` not installed** — If you see `ImportError: mem0ai is required for Mem0Memory`, run `uv add mem0ai` or `pip install mem0ai` to add the dependency.
|
||||
- **Invalid API key** — A wrong or expired `MEM0_API_KEY` will log errors like `Mem0 search failed` or `Mem0 add failed` but won't crash the agent. Check your key at <a href="https://app.mem0.ai" rel="nofollow">app.mem0.ai</a>.
|
||||
- **Invalid API key** — A wrong or expired `MEM0_API_KEY` will log errors like `Mem0 search failed` or `Mem0 add failed` but won't crash the agent. Check your key at <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-chatdev" rel="nofollow">app.mem0.ai</a>.
|
||||
- **Pipeline headers in memories** — ChatDev automatically strips internal pipeline headers (e.g., `=== INPUT FROM TASK (user) ===`) before sending text to Mem0, so your memories stay clean.
|
||||
- **Clearing test memories** — To delete memories created during testing, use the Mem0 dashboard at <a href="https://app.mem0.ai" rel="nofollow">app.mem0.ai</a> or the Python SDK: `MemoryClient().delete_all(user_id="your-test-user")`.
|
||||
- **Clearing test memories** — To delete memories created during testing, use the Mem0 dashboard at <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-chatdev" rel="nofollow">app.mem0.ai</a> or the Python SDK: `MemoryClient().delete_all(user_id="your-test-user")`.
|
||||
|
||||
## Key Features
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ Add persistent memory to [**Claude Code**](https://docs.anthropic.com/en/docs/cl
|
||||
Before setting up Mem0 with Claude Code, ensure you have:
|
||||
|
||||
1. A Mem0 Platform account and API key:
|
||||
- <a href="https://app.mem0.ai" rel="nofollow">Sign up at app.mem0.ai</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Get your API key</a> (starts with `m0-`)
|
||||
- <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-claude-code" rel="nofollow">Sign up at app.mem0.ai</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-claude-code" rel="nofollow">Get your API key</a> (starts with `m0-`)
|
||||
|
||||
2. Claude Code CLI or Claude Cowork desktop app installed
|
||||
|
||||
@@ -32,12 +32,19 @@ export MEM0_API_KEY="m0-your-api-key"
|
||||
|
||||
### Option A — Plugin Marketplace (Recommended)
|
||||
|
||||
Install the full plugin including MCP server, lifecycle hooks, and SDK skill:
|
||||
Install the full plugin including MCP server, lifecycle hooks, and SDK skill.
|
||||
|
||||
```
|
||||
/plugin marketplace add mem0ai/mem0
|
||||
/plugin install mem0@mem0-plugins
|
||||
```
|
||||
1. Add the Mem0 marketplace:
|
||||
|
||||
```
|
||||
/plugin marketplace add mem0ai/mem0
|
||||
```
|
||||
|
||||
2. Install the plugin:
|
||||
|
||||
```
|
||||
/plugin install mem0@mem0-plugins
|
||||
```
|
||||
|
||||
**Claude Cowork desktop app:** Open the Cowork tab, click **Customize** in the sidebar, click **Browse plugins**, and install Mem0.
|
||||
|
||||
|
||||
+83
-70
@@ -17,8 +17,8 @@ Add persistent memory to [**OpenAI Codex**](https://openai.com/index/codex/) wit
|
||||
Before setting up Mem0 with Codex, ensure you have:
|
||||
|
||||
1. A Mem0 Platform account and API key:
|
||||
- <a href="https://app.mem0.ai" rel="nofollow">Sign up at app.mem0.ai</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Get your API key</a> (starts with `m0-`)
|
||||
- <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-codex" rel="nofollow">Sign up at app.mem0.ai</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-codex" rel="nofollow">Get your API key</a> (starts with `m0-`)
|
||||
|
||||
2. OpenAI Codex access
|
||||
|
||||
@@ -30,91 +30,100 @@ export MEM0_API_KEY="m0-your-api-key"
|
||||
|
||||
## Installation
|
||||
|
||||
### Option A — Repo Marketplace (Recommended for Teams)
|
||||
### Option A — Direct MCP (Recommended)
|
||||
|
||||
Add a `.agents/plugins/marketplace.json` to your repository root:
|
||||
The fastest way to connect Codex to Mem0 — no downloads, no marketplace. Codex reads MCP servers from `~/.codex/config.toml` as TOML. Add:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "mem0-plugins",
|
||||
"interface": {
|
||||
"displayName": "Mem0 Plugins"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "mem0",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./plugins/mem0"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Productivity"
|
||||
}
|
||||
]
|
||||
}
|
||||
```toml
|
||||
[mcp_servers.mem0]
|
||||
url = "https://mcp.mem0.ai/mcp"
|
||||
bearer_token_env_var = "MEM0_API_KEY"
|
||||
```
|
||||
|
||||
Then in Codex, browse the repo's plugin directory and install Mem0.
|
||||
Make sure `MEM0_API_KEY` is exported in the shell you launch Codex from, then restart Codex.
|
||||
|
||||
### Option B — Personal Marketplace
|
||||
<Info>
|
||||
Codex's `codex mcp add` CLI only supports stdio MCP servers. Because Mem0's MCP is HTTP/streamable, you configure it by editing `config.toml` directly (or via the **Plugins → Connect to a custom MCP → Streamable HTTP** UI in the Codex app).
|
||||
</Info>
|
||||
|
||||
Add to `~/.agents/plugins/marketplace.json`:
|
||||
### Option B — Sideload the Plugin (Advanced)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "mem0-plugins",
|
||||
"interface": {
|
||||
"displayName": "Mem0 Plugins"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "mem0",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "/path/to/mem0-plugin"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Productivity"
|
||||
}
|
||||
]
|
||||
}
|
||||
For the full plugin experience — MCP server **plus** the Mem0 SDK skill, memory protocol skill, and opt-in lifecycle hooks — sideload the plugin from a local clone. The Mem0 repo already ships a marketplace manifest at [`.agents/plugins/marketplace.json`](https://github.com/mem0ai/mem0/blob/main/.agents/plugins/marketplace.json), so there's no JSON to author by hand. This follows the Codex [build-plugins](https://developers.openai.com/codex/plugins/build) local-testing workflow.
|
||||
|
||||
<Info>
|
||||
Don't combine Option B with Option A. The plugin manifest declares its MCP server via [`.codex-mcp.json`](https://github.com/mem0ai/mem0/blob/main/mem0-plugin/.codex-mcp.json), so Codex auto-registers the `mem0` MCP server when the plugin loads. Adding the same `[mcp_servers.mem0]` block to `~/.codex/config.toml` will create a duplicate registration.
|
||||
</Info>
|
||||
|
||||
**Step 1.** Clone the Mem0 repository anywhere on disk:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mem0ai/mem0.git ~/codex-plugins/mem0-source
|
||||
```
|
||||
|
||||
### Option C — Manual MCP Configuration
|
||||
**Step 2.** Register the bundled marketplace with Codex's CLI:
|
||||
|
||||
Add to your Codex MCP config:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"mem0": {
|
||||
"type": "http",
|
||||
"url": "https://mcp.mem0.ai/mcp/",
|
||||
"headers": {
|
||||
"Authorization": "Token ${MEM0_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```bash
|
||||
codex plugin marketplace add ~/codex-plugins/mem0-source
|
||||
```
|
||||
|
||||
This points Codex at the repo's `.agents/plugins/marketplace.json`. The bundled file uses `path: "./mem0-plugin"`, which Codex resolves relative to the clone root.
|
||||
|
||||
<Info>
|
||||
**Why we recommend this over hand-authoring `~/.agents/plugins/marketplace.json`:** Codex requires `source.path` in any marketplace manifest to be **relative** (starting with `./`) and **inside the marketplace root**. The repo's bundled manifest already satisfies this — the marketplace root is the clone directory, and `mem0-plugin/` lives inside it. With a personal `~/.agents/plugins/marketplace.json`, the root is `~/` and the clone has to live under `~/` too. The CLI form sidesteps that constraint.
|
||||
</Info>
|
||||
|
||||
**Step 3.** Restart Codex, run `/plugins`, browse the `Mem0 Plugins` marketplace, and install **Mem0**.
|
||||
|
||||
**Step 4 (optional) — enable lifecycle hooks.** Codex doesn't auto-wire hooks from plugin manifests; it only reads them from `~/.codex/hooks.json` (or `<repo>/.codex/hooks.json`). Run the bundled installer once to merge the Mem0 entries into your global hooks file:
|
||||
|
||||
```bash
|
||||
python3 ~/codex-plugins/mem0-source/mem0-plugin/scripts/install_codex_hooks.py
|
||||
```
|
||||
|
||||
Then enable the hooks feature flag in `~/.codex/config.toml`:
|
||||
|
||||
```toml
|
||||
[features]
|
||||
codex_hooks = true
|
||||
```
|
||||
|
||||
Restart Codex. The installer registers three hooks pointing at scripts inside your clone:
|
||||
|
||||
| Event | Behavior |
|
||||
|-------|----------|
|
||||
| `SessionStart` | Loads prior memories as bootstrap context |
|
||||
| `UserPromptSubmit` | Injects relevant memories before each prompt |
|
||||
| `Stop` | Reminds the agent to persist learnings at turn end |
|
||||
|
||||
Re-running the installer is idempotent. To remove the hooks: `python3 ~/codex-plugins/mem0-source/mem0-plugin/scripts/install_codex_hooks.py --uninstall`.
|
||||
|
||||
<Warning>
|
||||
The hooks file stores absolute paths into your clone (e.g. `~/codex-plugins/mem0-source/mem0-plugin/scripts/...`). If you move or delete the clone, the hooks will break silently — re-run the installer from the new location, or run `--uninstall` first.
|
||||
</Warning>
|
||||
|
||||
### Managing the Plugin
|
||||
|
||||
Codex provides CLI commands for managing marketplaces after install:
|
||||
|
||||
```bash
|
||||
codex plugin marketplace upgrade # pull latest plugin versions
|
||||
codex plugin marketplace remove mem0-plugins # unregister the marketplace
|
||||
```
|
||||
|
||||
To pull updates to the plugin source itself, `git pull` inside your clone (`~/codex-plugins/mem0-source`) and then run `codex plugin marketplace upgrade` to refresh Codex's plugin cache. Plugins are cached at `~/.codex/plugins/cache/<marketplace>/<plugin>/<version>/`.
|
||||
|
||||
<Info icon="check">
|
||||
Start a new Codex task and ask: *"List my mem0 entities"* or *"Search my memories for hello"*. If the `mem0` tools appear and respond, you're all set.
|
||||
After either option, start a new Codex task and ask: *"List my mem0 entities"* or *"Search my memories for hello"*. If the `mem0` tools appear and respond, you're all set.
|
||||
</Info>
|
||||
|
||||
## What's Included
|
||||
|
||||
| Component | Plugin Install | MCP Only |
|
||||
|-----------|:--------------:|:--------:|
|
||||
| Component | Sideloaded Plugin | Direct MCP |
|
||||
|-----------|:-----------------:|:----------:|
|
||||
| MCP Server (9 memory tools) | Yes | Yes |
|
||||
| Memory Protocol Skill | Yes | No |
|
||||
| Mem0 SDK Skill | Yes | No |
|
||||
| Lifecycle Hooks (opt-in) | Yes | No |
|
||||
|
||||
## Available MCP Tools
|
||||
|
||||
@@ -134,7 +143,7 @@ Once installed, the following tools are available in every Codex session:
|
||||
|
||||
## Memory Protocol Skill
|
||||
|
||||
Codex uses a skill-based approach instead of lifecycle hooks. When installed via the plugin marketplace, the memory protocol skill instructs the agent to:
|
||||
When the plugin is sideloaded, the memory protocol skill instructs the agent to:
|
||||
|
||||
### On Every New Task
|
||||
1. Call `search_memories` with a query related to the current task to load relevant context
|
||||
@@ -199,8 +208,12 @@ You: Add WebSocket support for real-time notification delivery.
|
||||
|
||||
- **"Connection failed"** — Verify `MEM0_API_KEY` is set in your shell: `echo $MEM0_API_KEY`
|
||||
- **No tools appearing** — Restart your Codex session after plugin installation
|
||||
- **Plugin not found** — Ensure `.agents/plugins/marketplace.json` is at the repository root and `source.path` points to the correct plugin directory
|
||||
- **Skills not loading** — Verify the `skills` field in `plugin.json` points to a valid directory containing `SKILL.md` files
|
||||
- **Duplicate `mem0` MCP server / "tool collision" errors** — You combined Option A (Direct MCP) with Option B (sideload). The sideloaded plugin auto-registers `mem0` from `.codex-mcp.json`, so remove the `[mcp_servers.mem0]` block from `~/.codex/config.toml`.
|
||||
- **`plugin/read failed in TUI`** — Codex can't find the plugin directory the marketplace points at. If you used `codex plugin marketplace add <path>`, confirm the path is your clone root and that `<clone>/.agents/plugins/marketplace.json` exists. If you hand-authored `~/.agents/plugins/marketplace.json`, `source.path` must be relative (start with `./`), inside the marketplace root (`~/` for personal installs), and end in `mem0-plugin` — e.g. `"./codex-plugins/mem0-source/mem0-plugin"`.
|
||||
- **Plugin not found in `/plugins`** — Run `codex plugin marketplace add ~/path/to/clone` again, or confirm the marketplace was registered with `codex plugin marketplace remove mem0-plugins` then re-add.
|
||||
- **Skills not loading** — Verify the `skills` field in `plugin.json` points to a valid directory containing `SKILL.md` files.
|
||||
- **Hooks not firing** — Confirm `codex_hooks = true` is in `~/.codex/config.toml` under `[features]`, and that `~/.codex/hooks.json` contains the Mem0 entries (re-run the installer if not). Restart Codex after enabling the flag.
|
||||
- **Hooks broke after moving the clone** — The installer bakes absolute paths into `~/.codex/hooks.json` pointing at scripts inside your clone. If you moved or renamed the clone directory, run `python3 <new-clone>/mem0-plugin/scripts/install_codex_hooks.py` from the new location — the installer is idempotent and replaces the old entries.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Mem0 MCP Setup" icon="puzzle-piece" href="/platform/mem0-mcp">
|
||||
|
||||
@@ -22,7 +22,7 @@ pip install crewai crewai-tools mem0ai
|
||||
|
||||
Import required modules and set up configurations:
|
||||
|
||||
<Note>Remember to get your API keys from <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a>, [OpenAI](https://platform.openai.com) and [Serper Dev](https://serper.dev) for search capabilities.</Note>
|
||||
<Note>Remember to get your API keys from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-crewai" rel="nofollow">Mem0 Platform</a>, [OpenAI](https://platform.openai.com) and [Serper Dev](https://serper.dev) for search capabilities.</Note>
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
@@ -17,8 +17,8 @@ Add persistent memory to [**Cursor**](https://cursor.com) with the Mem0 plugin.
|
||||
Before setting up Mem0 with Cursor, ensure you have:
|
||||
|
||||
1. A Mem0 Platform account and API key:
|
||||
- <a href="https://app.mem0.ai" rel="nofollow">Sign up at app.mem0.ai</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Get your API key</a> (starts with `m0-`)
|
||||
- <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-cursor" rel="nofollow">Sign up at app.mem0.ai</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-cursor" rel="nofollow">Get your API key</a> (starts with `m0-`)
|
||||
|
||||
2. Cursor installed ([cursor.com](https://cursor.com))
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ npx flowise start
|
||||
|
||||
### 2. Obtain Your Mem0 API Key
|
||||
|
||||
1. Navigate to the <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 API Key dashboard</a>.
|
||||
1. Navigate to the <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-flowise" rel="nofollow">Mem0 API Key dashboard</a>.
|
||||
2. Generate or copy your existing Mem0 API Key.
|
||||
|
||||

|
||||
@@ -70,7 +70,7 @@ Test your memory configuration:
|
||||
|
||||
1. Save your Flowise configuration
|
||||
2. Run a test chat and store some information
|
||||
3. Verify the stored memories in the <a href="https://app.mem0.ai/dashboard/requests" rel="nofollow">Mem0 Dashboard</a>
|
||||
3. Verify the stored memories in the <a href="https://app.mem0.ai/dashboard/requests?utm_source=oss&utm_medium=integration-flowise" rel="nofollow">Mem0 Dashboard</a>
|
||||
|
||||

|
||||
|
||||
@@ -103,7 +103,7 @@ Available settings include:
|
||||
|
||||
### Platform Configuration
|
||||
|
||||
Additional settings available in <a href="https://app.mem0.ai/dashboard/project-settings" rel="nofollow">Mem0 Project Settings</a>:
|
||||
Additional settings available in <a href="https://app.mem0.ai/dashboard/project-settings?utm_source=oss&utm_medium=integration-flowise" rel="nofollow">Mem0 Project Settings</a>:
|
||||
|
||||
1. **Custom Instructions**: Define memory extraction rules
|
||||
2. **Expiration Date**: Set automatic memory cleanup periods
|
||||
|
||||
@@ -22,7 +22,7 @@ pip install google-adk mem0ai python-dotenv
|
||||
```
|
||||
|
||||
2. Valid API keys:
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 API Key</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-google-ai-adk" rel="nofollow">Mem0 API Key</a>
|
||||
- Google AI Studio API Key
|
||||
|
||||
## Basic Integration Example
|
||||
|
||||
@@ -52,7 +52,7 @@ hermes memory setup
|
||||
|
||||
Select **mem0** as the provider and enter your Mem0 API key when prompted. The wizard writes your config to `~/.hermes/mem0.json`.
|
||||
|
||||
<Note>Get your API key from <a href="https://app.mem0.ai" rel="nofollow">app.mem0.ai</a>.</Note>
|
||||
<Note>Get your API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-hermes" rel="nofollow">app.mem0.ai</a>.</Note>
|
||||
|
||||
### Option 2: Manual Configuration
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ Combining Mem0 with Keywords AI allows you to:
|
||||
4. Optimize token usage and reduce costs
|
||||
|
||||
<Note>
|
||||
You can get your Mem0 API key from the <a href="https://app.mem0.ai/" rel="nofollow">Mem0 dashboard</a>.
|
||||
You can get your Mem0 API key from the <a href="https://app.mem0.ai/?utm_source=oss&utm_medium=integration-keywords" rel="nofollow">Mem0 dashboard</a>.
|
||||
</Note>
|
||||
|
||||
## Setup and Configuration
|
||||
@@ -24,7 +24,7 @@ You can get your Mem0 API key from the <a href="https://app.mem0.ai/" rel="nofol
|
||||
Install the necessary libraries:
|
||||
|
||||
```bash
|
||||
pip install mem0 keywordsai-sdk
|
||||
pip install mem0ai keywordsai-sdk
|
||||
```
|
||||
|
||||
Set up your environment variables:
|
||||
@@ -65,7 +65,7 @@ config = {
|
||||
}
|
||||
|
||||
# Initialize Memory
|
||||
memory = Memory.from_config(config_dict=config)
|
||||
memory = Memory.from_config(config)
|
||||
|
||||
# Add a memory
|
||||
result = memory.add(
|
||||
|
||||
@@ -22,7 +22,7 @@ pip install langchain langchain_openai mem0ai python-dotenv
|
||||
|
||||
Import required modules and set up configurations:
|
||||
|
||||
<Note>Remember to get the Mem0 API key from <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
<Note>Remember to get the Mem0 API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-langchain" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
@@ -23,7 +23,7 @@ pip install langgraph langchain-openai mem0ai python-dotenv
|
||||
|
||||
Import required modules and set up configurations:
|
||||
|
||||
<Note>Remember to get the Mem0 API key from <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
<Note>Remember to get the Mem0 API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-langgraph" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
|
||||
```python
|
||||
from typing import Annotated, TypedDict, List
|
||||
|
||||
@@ -22,7 +22,7 @@ pip install llama-index-core llama-index-memory-mem0 python-dotenv
|
||||
Set your Mem0 Platform API key as an environment variable. You can replace `<your-mem0-api-key>` with your actual API key:
|
||||
|
||||
<Note type="info">
|
||||
You can obtain your Mem0 Platform API key from the <a href="https://app.mem0.ai/login" rel="nofollow">Mem0 Platform</a>.
|
||||
You can obtain your Mem0 Platform API key from the <a href="https://app.mem0.ai/login?utm_source=oss&utm_medium=integration-llama-index" rel="nofollow">Mem0 Platform</a>.
|
||||
</Note>
|
||||
|
||||
```python
|
||||
@@ -92,7 +92,6 @@ config = {
|
||||
"provider": "openai",
|
||||
"config": {"model": "text-embedding-3-small"},
|
||||
},
|
||||
"version": "v1.1",
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ npm install @mastra/core @mastra/mem0 @ai-sdk/openai zod
|
||||
|
||||
Set up your environment variables:
|
||||
|
||||
<Note>Remember to get the Mem0 API key from <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
<Note>Remember to get the Mem0 API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-mastra" rel="nofollow">Mem0 Platform</a>.</Note>
|
||||
|
||||
```bash
|
||||
MEM0_API_KEY=your-mem0-api-key
|
||||
|
||||
@@ -22,7 +22,7 @@ pip install openai-agents mem0ai
|
||||
```
|
||||
|
||||
2. Valid API keys:
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 API Key</a>
|
||||
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-openai-agents-sdk" rel="nofollow">Mem0 API Key</a>
|
||||
- [OpenAI API Key](https://platform.openai.com/api-keys)
|
||||
|
||||
## Basic Integration Example
|
||||
@@ -214,7 +214,7 @@ Customize memory behavior:
|
||||
# Configure memory search
|
||||
memories = mem0.search(
|
||||
query="travel preferences",
|
||||
user_id="alex",
|
||||
filters={"user_id": "alex"},
|
||||
top_k=5 # Number of memories to retrieve
|
||||
)
|
||||
|
||||
|
||||
+371
-57
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: OpenClaw
|
||||
description: "Add long-term memory to OpenClaw agents using the Mem0 plugin with auto-recall and auto-capture support."
|
||||
description: "Add long-term memory to OpenClaw agents using the Mem0 plugin with skills-based memory extraction and recall."
|
||||
---
|
||||
|
||||
Add long-term memory to [OpenClaw](https://github.com/openclaw/openclaw) agents with the `@mem0/openclaw-mem0` plugin. Your agent forgets everything between sessions — this plugin fixes that by automatically watching conversations, extracting what matters, and bringing it back when relevant.
|
||||
@@ -12,17 +12,39 @@ Add long-term memory to [OpenClaw](https://github.com/openclaw/openclaw) agents
|
||||
</Frame>
|
||||
|
||||
The plugin provides:
|
||||
1. **Auto-Recall** — Before the agent responds, memories matching the current message are injected into context
|
||||
2. **Auto-Capture** — After the agent responds, the exchange is sent to Mem0 which decides what's worth keeping
|
||||
3. **Agent Tools** — Five tools for explicit memory operations during conversations
|
||||
1. **Triage** — The agent extracts durable facts from conversations using a structured protocol with importance gates and domain overlays
|
||||
2. **Recall** — Before each turn, relevant memories are retrieved with reranking and injected into context
|
||||
3. **Dream** — Periodic memory consolidation: merges duplicates, resolves conflicts, prunes stale entries
|
||||
4. **Agent Tools** — Eight tools for explicit memory operations during conversations
|
||||
|
||||
Both auto-recall and auto-capture run silently with no manual configuration required.
|
||||
Skills mode, `autoRecall`, and `autoCapture` are all enabled by default during `openclaw mem0 init`.
|
||||
|
||||
## Requirements
|
||||
|
||||
Check your OpenClaw version:
|
||||
|
||||
```bash
|
||||
openclaw --version
|
||||
# OpenClaw 2026.4.25 (aa36ee6)
|
||||
```
|
||||
|
||||
| OpenClaw Version | Plugin Support |
|
||||
|------------------|----------------|
|
||||
| `>= 2026.4.25` | Fully supported |
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
openclaw plugins install @mem0/openclaw-mem0
|
||||
The fastest way is to install directly from your OpenClaw chat, no CLI or config editing needed.
|
||||
|
||||
**Copy and paste this into your OpenClaw chat**; Telegram, WhatsApp, default chat, or any channel where your agent lives:
|
||||
|
||||
```
|
||||
Setup Mem0 from mem0.ai/claw-setup
|
||||
```
|
||||
|
||||
OpenClaw installs the plugin, prompts you for your email, and connects your Mem0 account with OTP verification. See [Chat Setup](#option-1-chat-setup-recommended) below for the full walkthrough.
|
||||
|
||||
If you prefer the OpenClaw CLI, or are setting up self-hosted / open-source mode, see [Manual Config](#option-2-manual-config) and [Open-Source Mode](#open-source-mode-self-hosted) below.
|
||||
|
||||
## Setup and Configuration
|
||||
|
||||
@@ -36,51 +58,225 @@ Pick any stable, unique identifier for the user. Common choices:
|
||||
- A UUID (e.g. `"550e8400-e29b-41d4-a716-446655440000"`)
|
||||
- A simple username (e.g. `"alice"`)
|
||||
|
||||
All memories are scoped to this `userId` — different values create separate memory namespaces. If you don't set it, it defaults to `"default"`, which means all users share the same memory space.
|
||||
All memories are scoped to this `userId` — different values create separate memory namespaces. If you don't set it, it defaults to your OS username.
|
||||
|
||||
<Tip>In a multi-user application, set `userId` dynamically per user (e.g. from your auth system) rather than hardcoding a single value.</Tip>
|
||||
|
||||
### Platform Mode (Mem0 Cloud)
|
||||
|
||||
<Note>Get your API key from <a href="https://app.mem0.ai" rel="nofollow">app.mem0.ai</a>.</Note>
|
||||
There are two ways to set up `@mem0/openclaw-mem0` on the Mem0 platform:
|
||||
|
||||
Add to your `openclaw.json`:
|
||||
- **Chat setup (recommended)** — run the setup inside any OpenClaw chat. No config editing, no API key handling.
|
||||
- **Manual config** — edit `openclaw.json` directly.
|
||||
|
||||
```json5
|
||||
// plugins.entries
|
||||
"openclaw-mem0": {
|
||||
"enabled": true,
|
||||
"config": {
|
||||
"apiKey": "${MEM0_API_KEY}",
|
||||
"userId": "alice" // any unique identifier you choose for this user
|
||||
}
|
||||
}
|
||||
```
|
||||
#### Option 1: Chat Setup (Recommended)
|
||||
|
||||
You no longer need manual config editing to get started. Everything happens inside the OpenClaw chat itself.
|
||||
|
||||
<Steps>
|
||||
<Step title="Send the setup command to your OpenClaw agent">
|
||||
Open any OpenClaw channel — Telegram, WhatsApp, your default chat, wherever your agent lives. Paste and send this command:
|
||||
|
||||
```
|
||||
Setup Mem0 from mem0.ai/claw-setup
|
||||
```
|
||||
|
||||
OpenClaw responds with a Mem0 setup card and immediately asks:
|
||||
|
||||
> "What's your email address? I'll send you a verification code to connect your Mem0 account."
|
||||
</Step>
|
||||
|
||||
<Step title="Enter your email">
|
||||
Type your email address and send it. Mem0 sends back:
|
||||
|
||||
> "Check your email for a 6-digit code and paste it here."
|
||||
</Step>
|
||||
|
||||
<Step title="Paste the OTP">
|
||||
Copy the 6-digit code from your email inbox and paste it into the chat.
|
||||
|
||||
You'll see the confirmation:
|
||||
|
||||
> "Connected to Mem0."
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
That's it. No API key, no config file editing, no environment variables. The plugin is now active with skills-based memory (triage, recall, and dream) running automatically.
|
||||
|
||||
<Note>The chat flow uses the same underlying config as manual setup — it writes `apiKey`, `userId`, and `skills` config into `openclaw.json` for you. You can still open the file to inspect or override values afterward.</Note>
|
||||
|
||||
#### Option 2: Manual Config
|
||||
|
||||
<Steps>
|
||||
<Step title="Install the plugin via the OpenClaw CLI">
|
||||
```bash
|
||||
openclaw plugins install @mem0/openclaw-mem0
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Get your API key">
|
||||
Get your API key from <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-openclaw" rel="nofollow">app.mem0.ai</a>.
|
||||
</Step>
|
||||
|
||||
<Step title="Select the plugin as your memory backend in `openclaw.json`">
|
||||
Add the full config to your `openclaw.json`:
|
||||
|
||||
```json5
|
||||
{
|
||||
"plugins": {
|
||||
"slots": {
|
||||
"memory": "openclaw-mem0"
|
||||
},
|
||||
"entries": {
|
||||
"openclaw-mem0": {
|
||||
"enabled": true,
|
||||
"config": {
|
||||
"apiKey": "${MEM0_API_KEY}",
|
||||
"userId": "alice", // any unique identifier you choose for this user
|
||||
"skills": {
|
||||
"triage": { "enabled": true },
|
||||
"recall": {
|
||||
"enabled": true,
|
||||
"tokenBudget": 1500,
|
||||
"rerank": true,
|
||||
"keywordSearch": true,
|
||||
"identityAlwaysInclude": true
|
||||
},
|
||||
"dream": { "enabled": true },
|
||||
"domain": "companion"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
OpenClaw treats memory plugins as an exclusive slot. Installing the plugin alone does **not** activate it — you must also set `plugins.slots.memory` as shown above.
|
||||
</Warning>
|
||||
|
||||
### Open-Source Mode (Self-hosted)
|
||||
|
||||
No Mem0 key needed. Requires `OPENAI_API_KEY` for default embeddings/LLM.
|
||||
No Mem0 key needed. Defaults use OpenAI (`gpt-5-mini` for LLM, `text-embedding-3-small` for embeddings) — requires `OPENAI_API_KEY`. For a fully local setup, use Ollama for both.
|
||||
|
||||
#### Option 1: Interactive Wizard (Recommended)
|
||||
|
||||
Run the guided 4-step wizard:
|
||||
|
||||
```bash
|
||||
openclaw mem0 init --mode open-source
|
||||
```
|
||||
|
||||
The wizard walks you through:
|
||||
|
||||
<Steps>
|
||||
<Step title="LLM provider">
|
||||
Choose OpenAI (`gpt-5-mini`), Ollama (`llama3.1:8b`, fully local), or Anthropic (`claude-sonnet-4-5-20250514`). Provide an API key or base URL as needed.
|
||||
</Step>
|
||||
<Step title="Embedding provider">
|
||||
Choose OpenAI (`text-embedding-3-small`) or Ollama (`nomic-embed-text`, local). If the same provider was chosen for LLM, the API key and URL are reused automatically.
|
||||
</Step>
|
||||
<Step title="Vector store">
|
||||
Choose Qdrant (`http://localhost:6333`) or PGVector (PostgreSQL). Connectivity is verified before proceeding.
|
||||
</Step>
|
||||
<Step title="User ID">
|
||||
Set your memory namespace identifier.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
#### Option 2: Non-Interactive Setup
|
||||
|
||||
For CI/CD, scripts, or agent-driven setup — pass all options as flags:
|
||||
|
||||
```bash
|
||||
# Fully local with Ollama + Qdrant
|
||||
openclaw mem0 init --mode open-source \
|
||||
--oss-llm ollama --oss-embedder ollama --oss-vector qdrant
|
||||
|
||||
# OpenAI + Qdrant
|
||||
openclaw mem0 init --mode open-source \
|
||||
--oss-llm openai --oss-llm-key <key> \
|
||||
--oss-embedder openai --oss-embedder-key <key> \
|
||||
--oss-vector qdrant
|
||||
|
||||
# Anthropic LLM + OpenAI embeddings + PGVector
|
||||
openclaw mem0 init --mode open-source \
|
||||
--oss-llm anthropic --oss-llm-key <key> \
|
||||
--oss-embedder openai --oss-embedder-key <key> \
|
||||
--oss-vector pgvector --oss-vector-user postgres --oss-vector-password secret
|
||||
```
|
||||
|
||||
Add `--json` for machine-readable output (useful when an LLM agent is driving the setup).
|
||||
|
||||
<Accordion title="All --oss-* flags">
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--oss-llm <provider>` | `openai`, `ollama`, or `anthropic` |
|
||||
| `--oss-llm-key <key>` | API key for LLM provider |
|
||||
| `--oss-llm-model <model>` | Override default LLM model |
|
||||
| `--oss-llm-url <url>` | Base URL (Ollama only) |
|
||||
| `--oss-embedder <provider>` | `openai` or `ollama` |
|
||||
| `--oss-embedder-key <key>` | API key for embedder |
|
||||
| `--oss-embedder-model <model>` | Override default embedder model |
|
||||
| `--oss-embedder-url <url>` | Base URL (Ollama only) |
|
||||
| `--oss-vector <provider>` | `qdrant` or `pgvector` |
|
||||
| `--oss-vector-url <url>` | Qdrant server URL (default: `http://localhost:6333`) |
|
||||
| `--oss-vector-host <host>` | PGVector host |
|
||||
| `--oss-vector-port <port>` | PGVector port |
|
||||
| `--oss-vector-user <user>` | PGVector user |
|
||||
| `--oss-vector-password <pw>` | PGVector password |
|
||||
| `--oss-vector-dbname <db>` | PGVector database name |
|
||||
| `--oss-vector-dims <n>` | Override embedding dimensions |
|
||||
</Accordion>
|
||||
|
||||
#### Option 3: Manual Config
|
||||
|
||||
Minimal config — uses OpenAI defaults:
|
||||
|
||||
```json5
|
||||
"openclaw-mem0": {
|
||||
"enabled": true,
|
||||
"config": {
|
||||
"mode": "open-source",
|
||||
"userId": "alice" // any unique identifier you choose for this user
|
||||
{
|
||||
"plugins": {
|
||||
"slots": {
|
||||
"memory": "openclaw-mem0"
|
||||
},
|
||||
"entries": {
|
||||
"openclaw-mem0": {
|
||||
"enabled": true,
|
||||
"config": {
|
||||
"mode": "open-source",
|
||||
"userId": "alice" // any unique identifier you choose for this user
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Sensible defaults work out of the box. To customize the embedder, vector store, or LLM:
|
||||
To customize providers:
|
||||
|
||||
```json5
|
||||
"config": {
|
||||
"mode": "open-source",
|
||||
"userId": "your-user-id",
|
||||
"oss": {
|
||||
"embedder": { "provider": "openai", "config": { "model": "text-embedding-3-small" } },
|
||||
"vectorStore": { "provider": "qdrant", "config": { "host": "localhost", "port": 6333 } },
|
||||
"llm": { "provider": "openai", "config": { "model": "gpt-4o" } }
|
||||
{
|
||||
"plugins": {
|
||||
"slots": {
|
||||
"memory": "openclaw-mem0"
|
||||
},
|
||||
"entries": {
|
||||
"openclaw-mem0": {
|
||||
"enabled": true,
|
||||
"config": {
|
||||
"mode": "open-source",
|
||||
"userId": "your-user-id",
|
||||
"oss": {
|
||||
"embedder": { "provider": "openai", "config": { "model": "text-embedding-3-small" } },
|
||||
"vectorStore": { "provider": "qdrant", "config": { "url": "http://localhost:6333" } },
|
||||
"llm": { "provider": "openai", "config": { "model": "gpt-5-mini" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -93,26 +289,31 @@ Memories are organized into two scopes:
|
||||
|
||||
- **Session (short-term)** — Auto-capture stores memories scoped to the current session via Mem0's `run_id` / `runId` parameter. These are contextual to the ongoing conversation.
|
||||
|
||||
- **User (long-term)** — The agent can explicitly store long-term memories using the `memory_store` tool (with `longTerm: true`, the default). These persist across all sessions for the user.
|
||||
- **User (long-term)** — The agent can explicitly store long-term memories using the `memory_add` tool (with `longTerm: true`, the default). These persist across all sessions for the user.
|
||||
|
||||
During **auto-recall**, the plugin searches both scopes and presents them separately — long-term memories first, then session memories — so the agent has full context.
|
||||
|
||||
## Agent Tools
|
||||
|
||||
The agent gets five tools it can call during conversations:
|
||||
The agent gets eight tools it can call during conversations:
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `memory_search` | Search memories by natural language |
|
||||
| `memory_list` | List all stored memories for a user |
|
||||
| `memory_store` | Explicitly save a fact |
|
||||
| `memory_get` | Retrieve a memory by ID |
|
||||
| `memory_forget` | Delete by ID or by query |
|
||||
| `memory_search` | Search memories by natural language query. Supports `scope`, `categories`, `filters`. |
|
||||
| `memory_add` | Store facts. Accepts `text` or `facts` array, `category`, `importance`, `metadata`. |
|
||||
| `memory_get` | Retrieve a single memory by ID |
|
||||
| `memory_list` | List all memories. Filter by `userId`, `agentId`, `scope`. |
|
||||
| `memory_update` | Update a memory's text in place. Preserves history. |
|
||||
| `memory_delete` | Delete by `memoryId`, `query` (search-and-delete), or `all: true`. |
|
||||
| `memory_event_list` | List recent background processing events (platform mode only). |
|
||||
| `memory_event_status` | Get status of a specific event by ID (platform mode only). |
|
||||
|
||||
The `memory_search` and `memory_list` tools accept a `scope` parameter (`"session"`, `"long-term"`, or `"all"`) to control which memories are queried. The `memory_store` tool accepts a `longTerm` boolean (default: `true`) to choose where to store.
|
||||
The `memory_search` and `memory_list` tools accept a `scope` parameter (`"session"`, `"long-term"`, or `"all"`) to control which memories are queried.
|
||||
|
||||
## CLI Commands
|
||||
|
||||
All commands support `--json` for machine-readable output — useful when an LLM agent drives the CLI programmatically. Run `openclaw mem0 help --json` to discover every command and flag.
|
||||
|
||||
```bash
|
||||
# Search all memories (long-term + session)
|
||||
openclaw mem0 search "what languages does the user know"
|
||||
@@ -123,8 +324,13 @@ openclaw mem0 search "what languages does the user know" --scope long-term
|
||||
# Search only session/short-term memories
|
||||
openclaw mem0 search "what languages does the user know" --scope session
|
||||
|
||||
# View stats
|
||||
openclaw mem0 stats
|
||||
# List all memories
|
||||
openclaw mem0 list
|
||||
openclaw mem0 list --user-id alice --top-k 20
|
||||
|
||||
# JSON output (any command)
|
||||
openclaw mem0 search "preferences" --json
|
||||
openclaw mem0 status --json
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
@@ -134,9 +340,9 @@ openclaw mem0 stats
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `mode` | `"platform"` \| `"open-source"` | `"platform"` | Which backend to use |
|
||||
| `userId` | `string` | `"default"` | Scope memories per user |
|
||||
| `autoRecall` | `boolean` | `true` | Inject memories before each turn |
|
||||
| `autoCapture` | `boolean` | `true` | Store facts after each turn |
|
||||
| `userId` | `string` | OS username | Scope memories per user |
|
||||
| `autoRecall` | `boolean` | `true` | Inject memories before each turn. Ignored when `skills` is configured. |
|
||||
| `autoCapture` | `boolean` | `true` | Store facts after each turn. Ignored when `skills` is configured. |
|
||||
| `topK` | `number` | `5` | Max memories per recall |
|
||||
| `searchThreshold` | `number` | `0.3` | Min similarity (0–1) |
|
||||
|
||||
@@ -145,8 +351,6 @@ openclaw mem0 stats
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `apiKey` | `string` | — | **Required.** Mem0 API key (supports `${MEM0_API_KEY}`) |
|
||||
| `orgId` | `string` | — | Organization ID |
|
||||
| `projectId` | `string` | — | Project ID |
|
||||
| `customInstructions` | `string` | *(built-in)* | Extraction rules — what to store, how to format |
|
||||
| `customCategories` | `object` | *(12 defaults)* | Category name → description map for tagging |
|
||||
|
||||
@@ -162,19 +366,129 @@ openclaw mem0 stats
|
||||
| `oss.llm.provider` | `string` | `"openai"` | LLM provider (`"openai"`, `"anthropic"`, `"ollama"`, etc.) |
|
||||
| `oss.llm.config` | `object` | — | Provider config: `apiKey`, `model`, `baseURL`, `temperature` |
|
||||
| `oss.historyDbPath` | `string` | — | SQLite path for memory edit history |
|
||||
| `oss.disableHistory` | `boolean` | `false` | Disable memory edit history tracking |
|
||||
|
||||
Everything inside `oss` is optional — defaults use OpenAI embeddings (`text-embedding-3-small`), in-memory vector store, and OpenAI LLM.
|
||||
Everything inside `oss` is optional — defaults use OpenAI embeddings (`text-embedding-3-small`), in-memory vector store, and OpenAI LLM (`gpt-5-mini`).
|
||||
|
||||
## Key Features
|
||||
## Plugin Management
|
||||
|
||||
1. **Zero Configuration** — Auto-recall and auto-capture work out of the box with no prompting required
|
||||
2. **Dual Memory Scopes** — Session-scoped short-term and user-scoped long-term memories
|
||||
3. **Flexible Backend** — Use Mem0 Cloud for managed service or self-host with open-source mode
|
||||
4. **Rich Tool Suite** — Five agent tools for explicit memory operations when needed
|
||||
### Updating the Plugin
|
||||
|
||||
## Conclusion
|
||||
```bash
|
||||
openclaw plugins update openclaw-mem0
|
||||
```
|
||||
|
||||
The `@mem0/openclaw-mem0` plugin gives OpenClaw agents persistent memory with minimal setup. Whether using Mem0 Cloud or self-hosting, your agents can now remember user preferences, facts, and context across sessions automatically.
|
||||
### Checking Plugin Status
|
||||
|
||||
```bash
|
||||
openclaw plugins list
|
||||
openclaw plugins inspect openclaw-mem0
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "plugins.allow excludes mem0" Error
|
||||
|
||||
If you see an error like:
|
||||
|
||||
```
|
||||
[openclaw] Failed to start CLI: Error: The `openclaw mem0` command is unavailable
|
||||
because `plugins.allow` excludes "mem0". Add "mem0" to `plugins.allow` if you want
|
||||
that bundled plugin CLI surface.
|
||||
```
|
||||
|
||||
Add `mem0` to your `plugins.allow` list in `openclaw.json`:
|
||||
|
||||
```json5
|
||||
{
|
||||
"plugins": {
|
||||
"allow": ["mem0"],
|
||||
"slots": {
|
||||
"memory": "openclaw-mem0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Plugin Not Activating
|
||||
|
||||
If the plugin installs but doesn't work:
|
||||
|
||||
1. Verify `plugins.slots.memory` is set to `"openclaw-mem0"` (not the npm package name)
|
||||
2. Check `openclaw plugins list --enabled` to confirm the plugin is loaded
|
||||
3. Run `openclaw mem0 status` to verify configuration
|
||||
|
||||
### Plugin Update Not Working
|
||||
|
||||
If `openclaw plugins update` fails:
|
||||
|
||||
1. Use the plugin ID: `openclaw plugins update openclaw-mem0`
|
||||
2. Update all plugins at once: `openclaw plugins update --all`
|
||||
3. If that fails, uninstall and reinstall:
|
||||
```bash
|
||||
openclaw plugins uninstall openclaw-mem0
|
||||
openclaw plugins install @mem0/openclaw-mem0
|
||||
```
|
||||
|
||||
## Privacy & Security
|
||||
|
||||
### Data Flow
|
||||
|
||||
| Mode | Where data goes | Storage |
|
||||
|------|----------------|---------|
|
||||
| **Platform** | Conversations sent to `api.mem0.ai` for extraction and storage | Mem0 cloud |
|
||||
| **Open-source** | Embeddings generated via configured provider (default: OpenAI API). Vectors stored locally. | `~/.mem0/vector_store.db` (SQLite) |
|
||||
|
||||
### Auto-Capture and Auto-Recall
|
||||
|
||||
Auto-capture and auto-recall are **enabled by default**. When skills mode is configured (the default after `openclaw mem0 init`), these are ignored in favor of the skills-based triage/recall/dream protocol.
|
||||
|
||||
To disable either:
|
||||
|
||||
```json5
|
||||
{
|
||||
"plugins": {
|
||||
"entries": {
|
||||
"openclaw-mem0": {
|
||||
"config": {
|
||||
"autoCapture": false, // disable automatic fact extraction
|
||||
"autoRecall": false // disable automatic memory injection
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The agent can always use memory tools (`memory_add`, `memory_search`, etc.) explicitly regardless of these settings.
|
||||
|
||||
### Credential Protection
|
||||
|
||||
The plugin never stores API keys, tokens, or secrets as memories. Five independent layers enforce this:
|
||||
|
||||
1. **Triage gate** — The extraction prompt rejects values matching known credential patterns (`sk-`, `m0-`, `ghp_`, `AKIA`, `Bearer`, `password=`, `token=`, `secret=`)
|
||||
2. **Dream cleanup** — Periodic memory consolidation deletes any memories that slipped through containing credential patterns
|
||||
3. **Extraction instructions** — Default extraction rules explicitly instruct the model to store only that a credential was configured, never the value
|
||||
4. **Configurable patterns** — Add custom credential patterns via `skills.triage.credentialPatterns`
|
||||
5. **CLI redaction** — `openclaw mem0 config show` redacts sensitive fields (`apiKey`, `oss.*.config.apiKey`)
|
||||
|
||||
### API Key Storage
|
||||
|
||||
Plugin config is stored in `~/.openclaw/openclaw.json` with file permissions `0o600` (owner-read-only). For production deployments, use environment variable references (`${MEM0_API_KEY}`) or SecretRef objects instead of plaintext keys.
|
||||
|
||||
### Telemetry
|
||||
|
||||
Anonymous usage telemetry (PostHog) is enabled by default to help improve the plugin. No conversation content or memory values are included — only event counts (recall, capture, tool usage, CLI commands).
|
||||
|
||||
To opt out, set the environment variable:
|
||||
|
||||
```bash
|
||||
export MEM0_TELEMETRY=false
|
||||
```
|
||||
|
||||
### System Prompt Context
|
||||
|
||||
The plugin injects memory-related instructions into the agent's system context via OpenClaw's `prependSystemContext` mechanism. This includes the memory triage protocol and recalled memories. This is the standard OpenClaw plugin SDK pattern for memory backends — no user-facing prompts are modified.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="OpenAI Agents SDK" icon="robot" href="/integrations/openai-agents-sdk">
|
||||
|
||||
@@ -9,7 +9,7 @@ Mem0 is a self-improving memory layer for LLM applications, enabling personalize
|
||||
|
||||
**Get your API Key**: You'll need a Mem0 API key to use this extension:
|
||||
|
||||
a. Sign up at <a href="https://app.mem0.ai" rel="nofollow">app.mem0.ai</a>
|
||||
a. Sign up at <a href="https://app.mem0.ai?utm_source=oss&utm_medium=integration-raycast" rel="nofollow">app.mem0.ai</a>
|
||||
|
||||
b. Navigate to your API Keys page
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ npm install @mem0/vercel-ai-provider
|
||||
|
||||
### Setting Up Mem0
|
||||
|
||||
1. Get your **Mem0 API Key** from the <a href="https://app.mem0.ai/dashboard/api-keys" rel="nofollow">Mem0 Dashboard</a>.
|
||||
1. Get your **Mem0 API Key** from the <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-vercel-ai-sdk" rel="nofollow">Mem0 Dashboard</a>.
|
||||
|
||||
2. Initialize the Mem0 Client in your application:
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
|
||||
- [Open Source Configuration](https://docs.mem0.ai/open-source/configuration) [OSS]: Use when configuring `Memory` - LLM, embedder, vector store, graph store.
|
||||
- [Open Source Python Quickstart](https://docs.mem0.ai/open-source/python-quickstart) [OSS]: Use for the first self-hosted Python integration.
|
||||
- [Open Source Node.js Quickstart](https://docs.mem0.ai/open-source/node-quickstart) [OSS]: Use for the first self-hosted Node integration.
|
||||
- [Self-Hosted Setup](https://docs.mem0.ai/open-source/setup) [OSS]: Use when standing up the bundled REST server and dashboard via Docker Compose, including auth, API keys, and the setup wizard.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
@@ -184,8 +185,10 @@ If the user is on a pre-current major (Python < 2, TS < 3, or Platform `output_f
|
||||
### Features - Advanced Retrieval
|
||||
- [Advanced Retrieval](https://docs.mem0.ai/platform/features/advanced-retrieval) [Platform]: Use when the user needs keyword search, reranking, or hybrid retrieval.
|
||||
- [Criteria-Based Retrieval](https://docs.mem0.ai/platform/features/criteria-retrieval) [Platform]: Use when targeting memories by custom criteria, not just semantic similarity.
|
||||
- [Temporal Reasoning](https://docs.mem0.ai/platform/features/temporal-reasoning) [Platform]: Use when time-aware searches like last week, upcoming, or right now need better result ordering.
|
||||
- [Contextual Add](https://docs.mem0.ai/platform/features/contextual-add) [Platform]: Use when `add()` should consider the surrounding conversation, not just the latest turn.
|
||||
- [Custom Instructions](https://docs.mem0.ai/platform/features/custom-instructions) [Platform]: Use when tailoring what Mem0 extracts and stores on Platform.
|
||||
- [Memory Decay](https://docs.mem0.ai/platform/features/memory-decay) [Platform]: Use when search results should boost recently-reinforced memories and dampen stale ones — opt-in per project, search-time only, never filters candidates out.
|
||||
- [Advanced Memory Operations](https://docs.mem0.ai/platform/advanced-memory-operations) [Platform]: Use when basic CRUD is not enough - batch ops, complex filters, workflows.
|
||||
|
||||
### Features - Data Management
|
||||
|
||||
@@ -28,7 +28,7 @@ Move your Mem0 implementation to managed infrastructure with enterprise features
|
||||
|
||||
## Plan
|
||||
|
||||
1. **Sign up**: Create an account on <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a>.
|
||||
1. **Sign up**: Create an account on <a href="https://app.mem0.ai?utm_source=oss&utm_medium=migration-oss-to-platform" rel="nofollow">Mem0 Platform</a>.
|
||||
2. **Get API Key**: Navigate to **Settings > API Keys** and generate a new key.
|
||||
3. **Review Usage**: Identify where you instantiate `Memory` and where you call `search` or `get_all`.
|
||||
|
||||
@@ -372,7 +372,7 @@ If you encounter issues, you can revert immediately by switching your import bac
|
||||
|
||||
## Next Steps
|
||||
|
||||
- <a href="https://app.mem0.ai" rel="nofollow">Platform Dashboard</a> - Monitor usage and manage settings.
|
||||
- <a href="https://app.mem0.ai?utm_source=oss&utm_medium=migration-oss-to-platform" rel="nofollow">Platform Dashboard</a> - Monitor usage and manage settings.
|
||||
- [Webhooks Setup](/platform/features/webhooks) - Configure real-time event notifications.
|
||||
- [Organizations & Projects](/api-reference/organizations-projects) - Set up multi-tenancy for your team.
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ Previously, when an agent said something like "I've booked your flight for March
|
||||
|
||||
### Retrieval is hybrid now
|
||||
|
||||
Search now uses hybrid retrieval, which improves ranking quality — especially for queries involving exact keywords, proper nouns, or entities that appear across multiple memories. The response shape is unchanged:
|
||||
Search now uses hybrid retrieval, which improves ranking quality — especially for queries involving exact keywords, proper nouns, entities that appear across multiple memories, and time-aware queries (via Temporal Reasoning). The response shape is unchanged:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -58,7 +58,7 @@ Search now uses hybrid retrieval, which improves ranking quality — especially
|
||||
}
|
||||
```
|
||||
|
||||
The top-level `score` remains a `[0, 1]` value. Relative ranking between results stays comparable to v2, but absolute numbers shift since the scoring method changed — retune any hard thresholds in your app against representative queries.
|
||||
The top-level `score` remains a `[0, 1]` value. Relative ranking between results stays comparable to v2, but absolute numbers shift since the scoring method changed — retune any hard thresholds in your app against representative queries. Temporal signals are applied internally during ranking and are not returned as extra client-facing fields.
|
||||
|
||||
## API Changes
|
||||
|
||||
@@ -289,6 +289,7 @@ If your application previously read graph relations from the API response (`rela
|
||||
- **V1 and V2 endpoints continue to work.** There is no requirement to migrate to V3 endpoints immediately.
|
||||
- **Existing memories are preserved.** The new algorithm does not modify or re-process previously stored memories.
|
||||
- **Search response shape is unchanged.** The top-level `score` and `results[]` array are the same; existing code that reads `score` continues to work. What changed is the scoring method behind the number (multi-signal fusion instead of pure cosine), so the absolute values shift even when ranking stays comparable.
|
||||
- **Search remains backward-compatible at the top level.** Existing code that reads `results[]` and `score` continues to work. Temporal signals are applied internally during retrieval and do not change the client response shape.
|
||||
- **List response shape changed.** `get_all` now returns a paginated envelope (`{count, next, previous, results}`) instead of a bare `{results: [...]}`. Update code that reads `response["results"]` to continue working, or switch to the client SDKs which handle both shapes.
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
@@ -115,17 +115,15 @@ config = {
|
||||
}
|
||||
},
|
||||
"custom_instructions": custom_instructions,
|
||||
"version": "v1.1"
|
||||
}
|
||||
|
||||
m = Memory.from_config(config_dict=config)
|
||||
m = Memory.from_config(config)
|
||||
```
|
||||
|
||||
```ts TypeScript
|
||||
import { Memory } from "mem0ai/oss";
|
||||
|
||||
const config = {
|
||||
version: "v1.1",
|
||||
llm: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
|
||||
@@ -51,8 +51,7 @@ m = Memory()
|
||||
# Search with simple metadata filters
|
||||
results = m.search(
|
||||
"What are my preferences?",
|
||||
user_id="alice",
|
||||
filters={"category": "preferences"}
|
||||
filters={"user_id": "alice", "category": "preferences"}
|
||||
)
|
||||
```
|
||||
|
||||
@@ -68,8 +67,8 @@ Layer greater-than/less-than comparisons to rank results by score, confidence, o
|
||||
# Greater than / Less than
|
||||
results = m.search(
|
||||
"recent activities",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"user_id": "alice",
|
||||
"score": {"gt": 0.8},
|
||||
"priority": {"gte": 5},
|
||||
"confidence": {"lt": 0.9},
|
||||
@@ -80,8 +79,8 @@ results = m.search(
|
||||
# Equality operators
|
||||
results = m.search(
|
||||
"specific content",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"user_id": "alice",
|
||||
"status": {"eq": "active"},
|
||||
"archived": {"ne": True}
|
||||
}
|
||||
@@ -96,8 +95,8 @@ Use `in` and `nin` when you want to pre-approve or exclude specific values witho
|
||||
# In / Not in operators
|
||||
results = m.search(
|
||||
"multi-category search",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"user_id": "alice",
|
||||
"category": {"in": ["food", "travel", "entertainment"]},
|
||||
"status": {"nin": ["deleted", "archived"]}
|
||||
}
|
||||
@@ -116,8 +115,8 @@ results = m.search(
|
||||
# Text matching operators
|
||||
results = m.search(
|
||||
"content search",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"user_id": "alice",
|
||||
"title": {"contains": "meeting"},
|
||||
"description": {"icontains": "important"},
|
||||
"tags": {"contains": "urgent"}
|
||||
@@ -133,8 +132,8 @@ Allow any value for a field while still requiring the field to exist—handy whe
|
||||
# Match any value for a field
|
||||
results = m.search(
|
||||
"all with category",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"user_id": "alice",
|
||||
"category": "*"
|
||||
}
|
||||
)
|
||||
@@ -148,9 +147,9 @@ Combine filters with `AND`, `OR`, and `NOT` to express complex decision trees. N
|
||||
# Logical AND
|
||||
results = m.search(
|
||||
"complex query",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "alice"},
|
||||
{"category": "work"},
|
||||
{"priority": {"gte": 7}},
|
||||
{"status": {"ne": "completed"}}
|
||||
@@ -161,12 +160,16 @@ results = m.search(
|
||||
# Logical OR
|
||||
results = m.search(
|
||||
"flexible query",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"OR": [
|
||||
{"category": "urgent"},
|
||||
{"priority": {"gte": 9}},
|
||||
{"deadline": {"contains": "today"}}
|
||||
"AND": [
|
||||
{"user_id": "alice"},
|
||||
{
|
||||
"OR": [
|
||||
{"category": "urgent"},
|
||||
{"priority": {"gte": 9}},
|
||||
{"deadline": {"contains": "today"}}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
@@ -174,11 +177,15 @@ results = m.search(
|
||||
# Logical NOT
|
||||
results = m.search(
|
||||
"exclusion query",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"NOT": [
|
||||
{"category": "archived"},
|
||||
{"status": "deleted"}
|
||||
"AND": [
|
||||
{"user_id": "alice"},
|
||||
{
|
||||
"NOT": [
|
||||
{"category": "archived"},
|
||||
{"status": "deleted"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
@@ -186,9 +193,9 @@ results = m.search(
|
||||
# Complex nested logic
|
||||
results = m.search(
|
||||
"advanced query",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "alice"},
|
||||
{
|
||||
"OR": [
|
||||
{"category": "work"},
|
||||
@@ -288,16 +295,15 @@ Vector store support varies. Confirm operator coverage before shipping:
|
||||
# Before (v0.x) - simple key-value filtering only
|
||||
results = m.search(
|
||||
"query",
|
||||
user_id="alice",
|
||||
filters={"category": "work", "status": "active"}
|
||||
filters={"user_id": "alice", "category": "work", "status": "active"}
|
||||
)
|
||||
|
||||
# After (v1.0.0) - enhanced filtering with operators
|
||||
results = m.search(
|
||||
"query",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "alice"},
|
||||
{"category": "work"},
|
||||
{"status": {"ne": "archived"}},
|
||||
{"priority": {"gte": 5}}
|
||||
@@ -320,9 +326,9 @@ results = m.search(
|
||||
# Find high-priority active tasks
|
||||
results = m.search(
|
||||
"What tasks need attention?",
|
||||
user_id="project_manager",
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "project_manager"},
|
||||
{"project": {"in": ["alpha", ""]}},
|
||||
{"priority": {"gte": 8}},
|
||||
{"status": {"ne": "completed"}},
|
||||
@@ -347,9 +353,9 @@ results = m.search(
|
||||
# Find recent unresolved tickets
|
||||
results = m.search(
|
||||
"pending support issues",
|
||||
agent_id="support_bot",
|
||||
filters={
|
||||
"AND": [
|
||||
{"agent_id": "support_bot"},
|
||||
{"ticket_status": {"ne": "resolved"}},
|
||||
{"priority": {"in": ["high", "critical"]}},
|
||||
{"created_date": {"gte": "2024-01-01"}},
|
||||
@@ -364,7 +370,7 @@ results = m.search(
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Pair `agent_id` filters with ticket-specific metadata so shared support bots return only the tickets they can act on in the current session.
|
||||
Pair agent ID filters with ticket-specific metadata so shared support bots return only the tickets they can act on in the current session.
|
||||
</Tip>
|
||||
|
||||
### Content recommendation filtering
|
||||
@@ -373,9 +379,9 @@ results = m.search(
|
||||
# Personalized content filtering
|
||||
results = m.search(
|
||||
"recommend content",
|
||||
user_id="reader123",
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "reader123"},
|
||||
{
|
||||
"OR": [
|
||||
{"genre": {"in": ["sci-fi", "fantasy"]}},
|
||||
@@ -400,8 +406,8 @@ results = m.search(
|
||||
try:
|
||||
results = m.search(
|
||||
"test query",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"user_id": "alice",
|
||||
"invalid_operator": {"unknown": "value"}
|
||||
}
|
||||
)
|
||||
@@ -409,8 +415,7 @@ except ValueError as e:
|
||||
print(f"Filter error: {e}")
|
||||
results = m.search(
|
||||
"test query",
|
||||
user_id="alice",
|
||||
filters={"category": "general"}
|
||||
filters={"user_id": "alice", "category": "general"}
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ async_memory = AsyncMemory.from_config(config)
|
||||
async def search_with_rerank():
|
||||
return await async_memory.search(
|
||||
"What are my preferences?",
|
||||
user_id="alice",
|
||||
filters={"user_id": "alice"},
|
||||
rerank=True
|
||||
)
|
||||
|
||||
@@ -272,7 +272,7 @@ results = m.search("query", filters={"user_id": "alice"})
|
||||
```python
|
||||
results = m.search(
|
||||
"What are my food preferences?",
|
||||
user_id="alice"
|
||||
filters={"user_id": "alice"}
|
||||
)
|
||||
|
||||
for result in results["results"]:
|
||||
@@ -289,13 +289,13 @@ for result in results["results"]:
|
||||
```python
|
||||
results_with_rerank = m.search(
|
||||
"What movies do I like?",
|
||||
user_id="alice",
|
||||
filters={"user_id": "alice"},
|
||||
rerank=True
|
||||
)
|
||||
|
||||
results_without_rerank = m.search(
|
||||
"What movies do I like?",
|
||||
user_id="alice",
|
||||
filters={"user_id": "alice"},
|
||||
rerank=False
|
||||
)
|
||||
```
|
||||
@@ -313,9 +313,9 @@ results_without_rerank = m.search(
|
||||
```python
|
||||
results = m.search(
|
||||
"important work tasks",
|
||||
user_id="alice",
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "alice"},
|
||||
{"category": "work"},
|
||||
{"priority": {"gte": 7}}
|
||||
]
|
||||
@@ -348,8 +348,7 @@ m = Memory.from_config(config)
|
||||
|
||||
results = m.search(
|
||||
"customer having login issues with mobile app",
|
||||
agent_id="support_bot",
|
||||
filters={"category": "technical_support"},
|
||||
filters={"agent_id": "support_bot", "category": "technical_support"},
|
||||
rerank=True
|
||||
)
|
||||
```
|
||||
@@ -363,8 +362,7 @@ results = m.search(
|
||||
```python
|
||||
results = m.search(
|
||||
"science fiction books with space exploration themes",
|
||||
user_id="reader123",
|
||||
filters={"content_type": "book_recommendation"},
|
||||
filters={"user_id": "reader123", "content_type": "book_recommendation"},
|
||||
rerank=True,
|
||||
top_k=10
|
||||
)
|
||||
@@ -383,9 +381,9 @@ for result in results["results"]:
|
||||
```python
|
||||
results = m.search(
|
||||
"What restaurants did I enjoy last month that had good vegetarian options?",
|
||||
user_id="foodie_user",
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "foodie_user"},
|
||||
{"category": "dining"},
|
||||
{"rating": {"gte": 4}},
|
||||
{"date": {"gte": "2024-01-01"}}
|
||||
|
||||
@@ -13,6 +13,10 @@ The Mem0 REST API server exposes every OSS memory operation over HTTP. Run it al
|
||||
- You plan to explore or debug endpoints through the built-in OpenAPI page at `/docs`.
|
||||
</Info>
|
||||
|
||||
<Warning>
|
||||
**First time self-hosting, or upgrading from a pre-1.x build?** Start at [Self-Hosted Setup](/open-source/setup). It walks through the stack, the setup wizard, and the upgrade path for deployments that relied on open endpoints or `ADMIN_API_KEY`. This page covers the API surface and auth modes only.
|
||||
</Warning>
|
||||
|
||||
<Warning>
|
||||
**OSS vs Platform API paths:** The self-hosted OSS server does **not** use the `/v1/` prefix. For example, the endpoint is `POST /memories`, not `POST /v1/memories/`. The [API Reference](/api-reference) documents the hosted platform at `api.mem0.ai` which uses `/v1/` paths — those do not apply to the OSS server.
|
||||
</Warning>
|
||||
@@ -26,7 +30,7 @@ The Mem0 REST API server exposes every OSS memory operation over HTTP. Run it al
|
||||
## Feature
|
||||
|
||||
- **CRUD endpoints:** Create, retrieve, search, update, delete, and reset memories by `user_id`, `agent_id`, or `run_id`.
|
||||
- **API key authentication:** Optionally secure all endpoints with a shared API key via the `X-API-Key` header.
|
||||
- **Authentication:** On by default. Dashboard sessions use JWTs; programmatic clients use per-user `X-API-Key` headers. Legacy `ADMIN_API_KEY` is still supported.
|
||||
- **Status health check:** Access base routes to confirm the server is online.
|
||||
- **OpenAPI explorer:** Visit `/docs` for interactive testing and schema reference.
|
||||
|
||||
@@ -40,51 +44,75 @@ The Mem0 REST API server exposes every OSS memory operation over HTTP. Run it al
|
||||
<Tab title="Steps">
|
||||
1. Create `server/.env` with your keys:
|
||||
|
||||
```bash
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
```bash
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
JWT_SECRET=$(openssl rand -base64 48)
|
||||
```
|
||||
|
||||
2. Start the stack:
|
||||
2. Bootstrap the stack in one command:
|
||||
|
||||
```bash
|
||||
cd server
|
||||
docker compose up
|
||||
```
|
||||
```bash
|
||||
cd server
|
||||
make bootstrap # starts Compose, creates an admin, issues the first API key
|
||||
```
|
||||
|
||||
3. Reach the API at `http://localhost:8888`. Edits to the server or library auto-reload.
|
||||
Or to start the stack only and finish setup via the browser wizard at http://localhost:3000:
|
||||
|
||||
```bash
|
||||
cd server
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
3. API is at `http://localhost:8888`. Code edits auto-reload.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Run with Docker
|
||||
<AccordionGroup>
|
||||
<Accordion title="Other install paths">
|
||||
**Run with Docker**
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Pull image">
|
||||
<Tabs>
|
||||
<Tab title="Pull image">
|
||||
```bash
|
||||
docker pull mem0/mem0-api-server
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Build locally">
|
||||
</Tab>
|
||||
<Tab title="Build locally">
|
||||
```bash
|
||||
docker build -t mem0-api-server .
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
1. Create a `.env` file with `OPENAI_API_KEY`.
|
||||
2. Run the container:
|
||||
1. Create a `.env` file with `OPENAI_API_KEY` and `JWT_SECRET`.
|
||||
2. Run the container:
|
||||
|
||||
```bash
|
||||
docker run -p 8000:8000 --env-file .env mem0-api-server
|
||||
```
|
||||
```bash
|
||||
docker run -p 8000:8000 --env-file .env mem0-api-server
|
||||
```
|
||||
|
||||
3. Visit `http://localhost:8000`.
|
||||
3. Visit `http://localhost:8000`.
|
||||
|
||||
### Run directly (no Docker)
|
||||
**Run directly (no Docker)**
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
<Warning>
|
||||
This path skips Docker and assumes Postgres is already running and reachable at `POSTGRES_HOST:POSTGRES_PORT`. For a single-command local setup with Postgres included, use Docker Compose above.
|
||||
</Warning>
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<Note>
|
||||
Compose publishes internal port 8000 as 8888 on the host. Raw Docker and raw uvicorn listen on 8000 unless remapped.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
`JWT_SECRET` is required once auth is enabled — the server returns `500` on auth endpoints if it's unset. Generate one with `openssl rand -base64 48`. See [Self-Hosted Setup](/open-source/setup#configure-the-environment) for the full env var table.
|
||||
</Note>
|
||||
|
||||
<Tip>
|
||||
Use a process manager such as `systemd`, Supervisor, or PM2 when deploying the FastAPI server for production resilience.
|
||||
@@ -98,35 +126,74 @@ uvicorn main:app --reload
|
||||
|
||||
## Authentication
|
||||
|
||||
The server supports optional API key authentication. When the `ADMIN_API_KEY` environment variable is set, every endpoint requires a valid `X-API-Key` header. The `/` redirect, `/docs`, and `/openapi.json` routes remain open so you can always reach the interactive API explorer.
|
||||
Auth is on by default. Protected endpoints require either a JWT (from the dashboard login flow) or an `X-API-Key` header. The `/` redirect, `/docs`, and `/openapi.json` routes stay open so you can reach the OpenAPI explorer.
|
||||
|
||||
| `ADMIN_API_KEY` value | Behavior |
|
||||
|---|---|
|
||||
| Not set / empty | All endpoints are open (no auth) |
|
||||
| Any non-empty string | Requests must include `X-API-Key: <your-key>` |
|
||||
| Mode | How to send it | When to use it |
|
||||
|---|---|---|
|
||||
| Bearer JWT | `Authorization: Bearer <access_token>` | Dashboard sessions; tokens come from `POST /auth/login` and refresh via `POST /auth/refresh` |
|
||||
| Per-user API key | `X-API-Key: m0sk_...` | Programmatic access tied to the single admin user today. Per-user scoping arrives with the upcoming multi-user invite flow |
|
||||
| Legacy `ADMIN_API_KEY` | `X-API-Key: <env value>` | Back-compat for deployments that set the `ADMIN_API_KEY` env var |
|
||||
| `AUTH_DISABLED=true` | — | Local development only; bypasses auth entirely |
|
||||
|
||||
### Enable authentication
|
||||
The `/docs` OpenAPI explorer supports both auth modes. Click **Authorize** at the top of the page and paste either `Bearer <access_token>` (JWT) or your `X-API-Key` value. Protected endpoints return `401` until you authorize.
|
||||
|
||||
Add the key to your `.env` file:
|
||||
### Log in and use a JWT
|
||||
|
||||
Register the first admin (only works when no user exists yet), then log in:
|
||||
|
||||
```bash
|
||||
ADMIN_API_KEY=your-secret-api-key
|
||||
# First admin only — returns 403 after the first admin is registered
|
||||
curl -X POST http://localhost:8888/auth/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name": "Admin", "email": "admin@example.com", "password": "strong-password"}'
|
||||
```
|
||||
|
||||
Then include the header in every request:
|
||||
```bash
|
||||
curl -X POST http://localhost:8888/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email": "admin@example.com", "password": "your-password"}'
|
||||
```
|
||||
|
||||
Use the returned `access_token` as a bearer token:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/memories \
|
||||
curl -X POST http://localhost:8888/memories \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: your-secret-api-key" \
|
||||
-H "Authorization: Bearer <access_token>" \
|
||||
-d '{
|
||||
"messages": [{"role": "user", "content": "I love pizza."}],
|
||||
"user_id": "alice"
|
||||
}'
|
||||
```
|
||||
|
||||
When the access token expires, exchange the refresh token at `POST /auth/refresh`.
|
||||
|
||||
### Create and use a per-user API key
|
||||
|
||||
Create a key from the dashboard **API Keys** page, or call `POST /api-keys` with a JWT. The full `m0sk_...` value is returned **once** at creation time — store it securely.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8888/memories \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: m0sk_your_key_here" \
|
||||
-d '{
|
||||
"messages": [{"role": "user", "content": "I love pizza."}],
|
||||
"user_id": "alice"
|
||||
}'
|
||||
```
|
||||
|
||||
List or revoke per-user keys via `GET /api-keys` and `DELETE /api-keys/{id}`. The dashboard user issued the key remains its owner; admin-only routes such as `/configure`, `/reset`, `/entities`, and `/requests` require the issuing user to have the admin role.
|
||||
|
||||
### Legacy `ADMIN_API_KEY`
|
||||
|
||||
Set the `ADMIN_API_KEY` environment variable and send it as `X-API-Key`. The request is treated as admin-level and is not tied to a dashboard user. This mode is kept for back-compat with older self-hosted deployments — prefer JWT or per-user keys for new setups.
|
||||
|
||||
```bash
|
||||
ADMIN_API_KEY=your-long-admin-key
|
||||
```
|
||||
|
||||
<Warning>
|
||||
The server logs a warning at startup when `ADMIN_API_KEY` is not set. Always set it in production.
|
||||
Setting `AUTH_DISABLED=true` makes every protected endpoint open — the server logs a warning at startup when it's enabled. The server also warns when `ADMIN_API_KEY` is shorter than 16 characters. Never enable `AUTH_DISABLED` in production, and always use a long `ADMIN_API_KEY` if you rely on the legacy fallback.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
@@ -136,7 +203,7 @@ curl -X POST http://localhost:8000/memories \
|
||||
### Create and search memories via HTTP
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/memories \
|
||||
curl -X POST http://localhost:8888/memories \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
@@ -151,7 +218,7 @@ curl -X POST http://localhost:8000/memories \
|
||||
</Info>
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/search \
|
||||
curl -X POST http://localhost:8888/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "vegetable",
|
||||
@@ -161,7 +228,7 @@ curl -X POST http://localhost:8000/search \
|
||||
|
||||
### Explore with OpenAPI docs
|
||||
|
||||
1. Navigate to `http://localhost:8000/docs`.
|
||||
1. Navigate to `http://localhost:8888/docs` (Compose) or `http://localhost:8000/docs` (raw Docker / uvicorn).
|
||||
2. Pick an endpoint (e.g., `POST /search`).
|
||||
3. Fill in parameters and click **Execute** to try requests in-browser.
|
||||
|
||||
@@ -175,9 +242,13 @@ curl -X POST http://localhost:8000/search \
|
||||
|
||||
The OSS REST server exposes the following endpoints. None use the `/v1/` prefix.
|
||||
|
||||
### Memory operations
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `POST` | `/configure` | Set memory configuration |
|
||||
| `POST` | `/configure` | **Admin only.** Set memory configuration. Rejects unbundled providers with a 400 |
|
||||
| `GET` | `/configure` | **Admin only.** Get the current memory configuration |
|
||||
| `GET` | `/configure/providers` | List the LLM and embedder providers bundled in the container |
|
||||
| `POST` | `/memories` | Create memories |
|
||||
| `GET` | `/memories` | Get all memories (filter by `user_id`, `agent_id`, or `run_id`) |
|
||||
| `GET` | `/memories/{memory_id}` | Get a specific memory |
|
||||
@@ -186,7 +257,44 @@ The OSS REST server exposes the following endpoints. None use the `/v1/` prefix.
|
||||
| `DELETE` | `/memories` | Delete all memories for an identifier |
|
||||
| `GET` | `/memories/{memory_id}/history` | Get memory history |
|
||||
| `POST` | `/search` | Search memories |
|
||||
| `POST` | `/reset` | Reset all memories |
|
||||
| `POST` | `/reset` | **Admin only.** Reset all memories |
|
||||
|
||||
### Authentication
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/auth/setup-status` | Returns `{needsSetup: bool}`. Open, no auth required |
|
||||
| `POST` | `/auth/register` | Register the first admin. Registration closes after the first admin is created; additional accounts will be provisioned by the existing admin (multi-user invite flow coming soon). |
|
||||
| `POST` | `/auth/login` | Exchange email and password for access and refresh JWTs |
|
||||
| `POST` | `/auth/refresh` | Exchange a refresh token for a new access token |
|
||||
| `GET` | `/auth/me` | Get the current authenticated user (JWT required) |
|
||||
| `PATCH` | `/auth/me` | Update the caller's name or email. 409 if the new email is already in use |
|
||||
| `POST` | `/auth/change-password` | Change the caller's password. 401 if the current password is wrong; new password must be at least 8 characters |
|
||||
|
||||
### API keys
|
||||
|
||||
All `/api-keys` endpoints require a JWT.
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/api-keys` | List the caller's API keys |
|
||||
| `POST` | `/api-keys` | Create a new key; the full `m0sk_...` value is returned once |
|
||||
| `DELETE` | `/api-keys/{id}` | Revoke an API key |
|
||||
|
||||
### Request logs
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/requests?limit=N` | **Admin only.** Recent API call log |
|
||||
|
||||
### Entities
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/entities` | **Admin only.** Distinct `user_id` / `agent_id` / `run_id` values with memory counts |
|
||||
| `DELETE` | `/entities/{entity_type}/{entity_id}` | **Admin only.** Cascade-delete all memories for an entity; `entity_type` is `user`, `agent`, or `run` |
|
||||
|
||||
The `/auth/*`, `/api-keys`, `/requests`, and `/entities` routes are new to the self-hosted server and primarily back the dashboard, but you can call them directly from your own tooling.
|
||||
|
||||
---
|
||||
|
||||
@@ -201,7 +309,7 @@ The OSS REST server exposes the following endpoints. None use the `/v1/` prefix.
|
||||
|
||||
## Best practices
|
||||
|
||||
1. **Enable authentication:** Set `ADMIN_API_KEY` to secure all endpoints, or use an API gateway for more advanced schemes.
|
||||
1. **Keep auth on:** Auth is enabled by default. Never set `AUTH_DISABLED=true` in production. If you rely on `ADMIN_API_KEY`, use a long value (16+ chars) or prefer per-user API keys.
|
||||
2. **Use HTTPS:** Terminate TLS at your load balancer or reverse proxy.
|
||||
3. **Monitor uptime:** Track request rates, latency, and error codes per endpoint.
|
||||
4. **Version configs:** Keep environment files and Docker Compose definitions in source control.
|
||||
|
||||
@@ -76,7 +76,6 @@ By default the Node SDK uses local-friendly settings (OpenAI `gpt-5-mini`, `text
|
||||
import { Memory } from "mem0ai/oss";
|
||||
|
||||
const memory = new Memory({
|
||||
version: "v1.1",
|
||||
embedder: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
@@ -221,7 +220,6 @@ Mem0 offers granular configuration across vector stores, LLMs, embedders, and hi
|
||||
| Parameter | Description | Default |
|
||||
| --- | --- | --- |
|
||||
| `historyDbPath` | Path to history database | `"{mem0_dir}/history.db"` |
|
||||
| `version` | API version | `"v1.0"` |
|
||||
| `customInstructions` | Custom processing prompt | `undefined` |
|
||||
</Accordion>
|
||||
<Accordion title="History store">
|
||||
@@ -234,7 +232,6 @@ Mem0 offers granular configuration across vector stores, LLMs, embedders, and hi
|
||||
<Accordion title="Complete config example">
|
||||
```ts
|
||||
const config = {
|
||||
version: "v1.1",
|
||||
embedder: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
|
||||
@@ -15,12 +15,15 @@ Mem0 Open Source delivers the same adaptive memory engine as the platform, but p
|
||||
- **Extendable codebase**: Fork the repo, add providers, and ship custom automations.
|
||||
|
||||
<Info>
|
||||
Begin with the <Link href="/open-source/python-quickstart">Python quickstart</Link> (or the Node.js variant) to clone the repo, configure dependencies, and validate memory reads/writes locally.
|
||||
Two ways to run Mem0 OSS: as a **library** inside your app (Python or Node), or as a **self-hosted server** with a dashboard, per-user API keys, and a request audit log.
|
||||
</Info>
|
||||
|
||||
## Choose your path
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Self-hosted setup" icon="rocket-launch" href="/open-source/setup">
|
||||
Run `make bootstrap` to launch the server + dashboard, create an admin, and issue your first API key.
|
||||
</Card>
|
||||
<Card title="Python Quickstart" icon="python" href="/open-source/python-quickstart">
|
||||
Bootstrap CLI and verify add/search loop.
|
||||
</Card>
|
||||
@@ -41,15 +44,6 @@ Mem0 Open Source delivers the same adaptive memory engine as the platform, but p
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Deploy with Docker Compose" icon="server" href="/open-source/features/rest-api">
|
||||
Reference deployment with REST endpoints.
|
||||
</Card>
|
||||
<Card title="Use the REST API" icon="code" href="/open-source/features/rest-api">
|
||||
Async add/search flows and automation.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Need a managed alternative? Compare hosting models in the <Link href="/platform/platform-vs-oss">Platform vs OSS guide</Link> or switch tabs to the Platform documentation.
|
||||
</Tip>
|
||||
@@ -70,19 +64,27 @@ Mem0 Open Source delivers the same adaptive memory engine as the platform, but p
|
||||
## Default components
|
||||
|
||||
<Note>
|
||||
Mem0 OSS works out of the box with sensible defaults:
|
||||
**Library defaults** (when you `import` Mem0 and call `Memory()` directly):
|
||||
- LLM: OpenAI `gpt-5-mini` (via `OPENAI_API_KEY`)
|
||||
- Embeddings: OpenAI `text-embedding-3-small`
|
||||
- Vector store: Local Qdrant instance storing data at `/tmp/qdrant`
|
||||
- History store: SQLite database at `~/.mem0/history.db`
|
||||
- Reranker: Disabled until you configure a provider
|
||||
- Vector store: Local Qdrant at `/tmp/qdrant`
|
||||
- History store: SQLite at `~/.mem0/history.db`
|
||||
- Reranker: Disabled until configured
|
||||
|
||||
Override any component with <Link href="/open-source/configuration">`Memory.from_config`</Link>.
|
||||
</Note>
|
||||
|
||||
## Keep going
|
||||
<Note>
|
||||
**Self-hosted server defaults** (the `server/` Docker Compose stack):
|
||||
- LLM: OpenAI `gpt-4.1-nano-2025-04-14` (override with `MEM0_DEFAULT_LLM_MODEL`)
|
||||
- Embeddings: OpenAI `text-embedding-3-small` (override with `MEM0_DEFAULT_EMBEDDER_MODEL`)
|
||||
- Vector store: Postgres + pgvector
|
||||
- Bundled providers: `openai`, `anthropic`, `gemini` — switch from the Configuration page
|
||||
|
||||
{/* DEBUG: verify CTA targets */}
|
||||
See <Link href="/open-source/setup#supported-providers">Self-Hosted Setup</Link> for the full provider list and how to extend it.
|
||||
</Note>
|
||||
|
||||
## Keep going
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
@@ -98,7 +100,3 @@ Mem0 Open Source delivers the same adaptive memory engine as the platform, but p
|
||||
href="/open-source/python-quickstart"
|
||||
/>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Need a managed alternative? Compare hosting models in the <Link href="/platform/platform-vs-oss">Platform vs OSS guide</Link> or switch tabs to the Platform documentation.
|
||||
</Tip>
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
---
|
||||
title: "Self-Hosted Setup"
|
||||
description: "Stand up the Mem0 REST server and dashboard in a few minutes — admin account, API keys, and a live audit log included."
|
||||
icon: "rocket-launch"
|
||||
---
|
||||
|
||||
The self-hosted bundle ships the REST API and a web dashboard together. Configure your LLM provider and secrets in a `.env` file, start the containers, then choose how to create your admin account: through the browser-based setup wizard, or from the command line.
|
||||
|
||||
<Info>
|
||||
**Use this page when…**
|
||||
- You want a self-hosted Mem0 with a dashboard, not just the Python or Node library.
|
||||
- You need per-user API keys and a request audit log for your team.
|
||||
- You're upgrading from a pre-1.x server that relied on `ADMIN_API_KEY` or open endpoints.
|
||||
</Info>
|
||||
|
||||
<Warning>
|
||||
**Upgrading from 1.x?** Auth is now on by default. Deployments that ran with an empty `ADMIN_API_KEY` will return `401` on every protected endpoint until you either set `ADMIN_API_KEY`, register an admin through the wizard, or set `AUTH_DISABLED=true` for local development. See [Upgrade notes](#upgrade-notes) below.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker and Docker Compose (the reference path).
|
||||
- An `OPENAI_API_KEY` (or equivalent — the server reads the same component config as the library).
|
||||
- A free port `8888` for the API and `3000` for the dashboard.
|
||||
|
||||
---
|
||||
|
||||
## Configure the environment
|
||||
|
||||
Copy `server/.env.example` to `server/.env` and fill in the required values. The server refuses to start if `JWT_SECRET` is unset once auth is enabled.
|
||||
|
||||
| Variable | Required | Purpose |
|
||||
|---|---|---|
|
||||
| `OPENAI_API_KEY` | Yes | Default LLM and embedder provider. |
|
||||
| `JWT_SECRET` | Yes | Signs access and refresh tokens. Use a long random value. A missing secret causes auth endpoints to return `500`. |
|
||||
| `ADMIN_API_KEY` | Optional | Legacy shared admin key. Kept for back-compat; prefer per-user keys for new setups. |
|
||||
| `AUTH_DISABLED` | Optional | `true` turns off auth for local development only. Never enable in production. |
|
||||
| `DASHBOARD_URL` | Optional | Origin the API accepts for CORS. Defaults to `http://localhost:3000`. Set this when you front the dashboard on a custom domain. |
|
||||
| `POSTGRES_*` | Optional | Override the bundled Postgres / pgvector connection. |
|
||||
|
||||
<Tip>
|
||||
Generate a `JWT_SECRET` with `openssl rand -base64 48` or `python -c "import secrets; print(secrets.token_urlsafe(48))"`.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## Start the stack
|
||||
|
||||
Pick the path that fits your workflow.
|
||||
|
||||
### Browser-first (setup wizard)
|
||||
|
||||
```bash
|
||||
cd server
|
||||
make up
|
||||
```
|
||||
|
||||
This starts the containers and runs database migrations. The REST API listens on `http://localhost:8888` and the dashboard on `http://localhost:3000`.
|
||||
|
||||
Open `http://localhost:3000` — since no admin account exists yet, the dashboard redirects to the one-time setup wizard at `/setup`. See [Run the setup wizard](#run-the-setup-wizard) below.
|
||||
|
||||
### Agent-first (command line)
|
||||
|
||||
First, set `OPENAI_API_KEY` (or `ANTHROPIC_API_KEY` / `GOOGLE_API_KEY`) in `server/.env`. `make bootstrap` does not prompt for it, and the runtime test will fail without a valid provider key.
|
||||
|
||||
```bash
|
||||
cd server
|
||||
make bootstrap
|
||||
```
|
||||
|
||||
`make bootstrap` starts the same containers, then automatically creates the admin account and generates the first API key via the CLI. The admin credentials and API key are printed to your terminal — no browser required.
|
||||
|
||||
You can override the generated credentials:
|
||||
|
||||
```bash
|
||||
make bootstrap EMAIL=admin@company.com PASSWORD='strong-password' NAME='Admin'
|
||||
```
|
||||
|
||||
Because `make bootstrap` already creates the admin, the setup wizard is skipped. Opening `http://localhost:3000` takes you straight to the login page.
|
||||
|
||||
<Tip>
|
||||
For machine-readable output (useful in CI), run `OUTPUT=json make seed` after `make up`.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## Run the setup wizard
|
||||
|
||||
<Info>
|
||||
This section applies to the **browser-first** path (`make up`). If you used `make bootstrap`, the admin and API key were already created — skip ahead to [What the dashboard gives you](#what-the-dashboard-gives-you).
|
||||
</Info>
|
||||
|
||||
On a fresh install the dashboard redirects to `/setup`. Each step submits on Enter.
|
||||
|
||||
**1. Create the admin account.** Name, email, password. This account becomes the first admin. Registration closes after the first admin is created; additional accounts are provisioned by the existing admin.
|
||||
|
||||
**2. Review the effective config.** Read-only display of the LLM and embedder the server is running with, sourced from your environment. If anything is wrong here, stop the stack, fix the `.env`, and restart — the dashboard intentionally does not let you change provider secrets at runtime.
|
||||
|
||||
**3. Generate your first API key.** The full `m0sk_...` value is shown **once**. Copy it immediately — the server only stores the prefix and a bcrypt hash.
|
||||
|
||||
**4. Tell us your use case.** Pick a preset or describe your use case in a few words. Mem0 generates custom instructions that tell the memory system what to prioritize. You can edit the instructions before saving, or skip this step entirely.
|
||||
|
||||
**5. Test the key.** A ready-to-paste `curl` exercises `POST /memories` against your new key. Click "Run Test" to fire it from the browser. Success lands you in the dashboard at `/dashboard/requests`, where you'll see the test call in the live audit log.
|
||||
|
||||
---
|
||||
|
||||
## What the dashboard gives you
|
||||
|
||||
| Page | What it does |
|
||||
|---|---|
|
||||
| **Requests** | Default landing page. Live audit log of every API call, with status, latency, and auth mode. |
|
||||
| **Memories** | Browse and search the memories your server has stored. |
|
||||
| **Entities** | Distinct `user_id` / `agent_id` / `run_id` values with memory counts and cascade-delete. |
|
||||
| **API Keys** | Issue per-user keys, label them, and revoke. |
|
||||
| **Configuration** | Runtime override for LLM and embedder. Changes persist to the app database and reapply on restart, layered over the values from your `.env`. |
|
||||
| **Settings** | Account and session controls. |
|
||||
|
||||
For the underlying endpoints (including `/auth/*`, `/api-keys`, `/requests`, `/entities`), see the [REST API reference](/open-source/features/rest-api).
|
||||
|
||||
---
|
||||
|
||||
## Supported providers
|
||||
|
||||
The shipped container bundles the Python packages for:
|
||||
|
||||
- **LLMs** — `openai`, `anthropic`, `gemini`
|
||||
- **Embedders** — `openai`, `gemini`
|
||||
|
||||
The Configuration page and `POST /configure` only accept providers from these lists. Anything else returns a 400 up front instead of failing at the first memory write.
|
||||
|
||||
**To add another provider**, for example to run embeddings locally with `sentence-transformers`:
|
||||
|
||||
1. Add the package to `server/requirements.txt` (e.g. `sentence-transformers>=2.0`).
|
||||
2. Extend `BUNDLED_LLM_PROVIDERS` or `BUNDLED_EMBEDDER_PROVIDERS` in `server/main.py`.
|
||||
3. Rebuild the image (`make up` or `docker compose build`).
|
||||
|
||||
Heavy providers (`sentence-transformers` pulls in PyTorch, ~2 GB) are intentionally kept out of the default image.
|
||||
|
||||
---
|
||||
|
||||
## Upgrade notes
|
||||
|
||||
### Upgrading from a pre-auth build
|
||||
|
||||
Previous self-hosted builds allowed open access when `ADMIN_API_KEY` was unset. This build enables auth by default. After pulling the new image, pick **one**:
|
||||
|
||||
1. **Fastest, zero client changes** — set `ADMIN_API_KEY` to a long random value (16+ characters). Existing clients that send `X-API-Key: <your-key>` keep working unchanged.
|
||||
2. **Recommended for teams** — visit `http://<host>:3000`, run the setup wizard, and switch clients to per-user API keys. You get the audit log and revocation for free.
|
||||
3. **Local development only** — set `AUTH_DISABLED=true`. The server logs a warning on every boot. Never use this in production.
|
||||
|
||||
The server prints an unmissable startup banner when it detects the "upgraded but not configured" state so you know exactly which option to pick.
|
||||
|
||||
### Other changes in this release
|
||||
|
||||
- Dashboard ships as a second container in the reference Compose stack, wired to the API over the internal Docker network.
|
||||
- New tables: `users`, `api_keys`, `request_logs`. Alembic handles the migration automatically on first boot.
|
||||
|
||||
If `alembic upgrade head` fails on first boot, see the [Troubleshooting](#troubleshooting) section below.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Port 3000 or 8888 is already in use">
|
||||
Find the owning process on either port:
|
||||
```bash
|
||||
lsof -iTCP:3000 -sTCP:LISTEN
|
||||
lsof -iTCP:8888 -sTCP:LISTEN
|
||||
```
|
||||
Kill it (`kill <PID>`) or change the host port in `server/docker-compose.yaml`.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="JWT_SECRET is required">
|
||||
The server refuses to start without one. Generate a secret and add it to `server/.env`:
|
||||
```bash
|
||||
echo "JWT_SECRET=$(openssl rand -base64 48)" >> server/.env
|
||||
```
|
||||
`AUTH_DISABLED=true` is valid for local dev only, never production.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title=".env changes aren't applied after editing">
|
||||
`docker compose restart` does not re-read `env_file`. To pick up changes:
|
||||
```bash
|
||||
cd server && docker compose up -d --force-recreate mem0
|
||||
# or
|
||||
cd server && make up
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Provider returns 401 (bad API key)">
|
||||
Provider credential errors surface as `502 Upstream provider error.`. Check `docker compose logs mem0` for the full trace, then fix the key on the Configuration page and hit **Save**.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Alembic migrations fail on startup">
|
||||
Inspect the logs:
|
||||
```bash
|
||||
docker compose logs mem0 | grep -i alembic
|
||||
```
|
||||
If the database is unrecoverable, reset the volume (**this destroys all memories and users**):
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="REST API reference" icon="code" href="/open-source/features/rest-api">
|
||||
Endpoint tables, auth modes, and example requests.
|
||||
</Card>
|
||||
<Card title="Configure components" icon="sliders" href="/open-source/configuration">
|
||||
Swap LLMs, embedders, vector stores, and rerankers.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
+17
-2
@@ -419,7 +419,7 @@
|
||||
},
|
||||
"results": {
|
||||
"type": "array",
|
||||
"description": "Array of results produced by the event."
|
||||
"description": "Array of results produced by the event. For add events, this confirms the write completed; temporal reasoning enrichment runs asynchronously by default."
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
@@ -2071,7 +2071,7 @@
|
||||
"memories"
|
||||
],
|
||||
"summary": "Search memories (V3)",
|
||||
"description": "Relevance-ranked search across stored memories. V3 uses hybrid retrieval — the returned `score` is a combined `[0, 1]` value; per-signal component scores are not exposed on the response. Entity IDs **must** be passed inside the `filters` object — top-level `user_id` / `agent_id` / `run_id` are rejected with 400. At least one entity ID is required.",
|
||||
"description": "Relevance-ranked search across stored memories. V3 uses hybrid retrieval and can also apply temporal reasoning for time-aware queries. Entity IDs **must** be passed inside the `filters` object — top-level `user_id` / `agent_id` / `run_id` are rejected with 400. At least one entity ID is required.",
|
||||
"operationId": "memories_search_v3",
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
@@ -2112,6 +2112,21 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Apply the managed reranker for better ordering (adds latency)."
|
||||
},
|
||||
"reference_date": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"nullable": true,
|
||||
"description": "Optional query anchor time for relative temporal interpretation. Accepts Unix epoch, YYYY-MM-DD, or ISO datetime."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -53,7 +53,7 @@ For detailed per-client instructions, see the [Mem0 MCP Quickstart](/platform/me
|
||||
|
||||
## Available tools
|
||||
|
||||
The MCP server exposes 9 memory tools to your AI client:
|
||||
The MCP server exposes 11 memory tools to your AI client:
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
@@ -66,6 +66,8 @@ The MCP server exposes 9 memory tools to your AI client:
|
||||
| `delete_entities` | Remove user/agent/app entities |
|
||||
| `get_memory` | Retrieve single memory by ID |
|
||||
| `list_entities` | View stored entities |
|
||||
| `list_events` | List memory operation events with filters and pagination |
|
||||
| `get_event_status` | Check the status of an async memory operation by `event_id` |
|
||||
|
||||
## How it works
|
||||
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
---
|
||||
title: Memory Decay
|
||||
description: "Boost recently-used memories and gently dampen stale ones at search time, without filtering anything out."
|
||||
---
|
||||
|
||||
# Memory Decay
|
||||
|
||||
Older memories drift in relevance at different speeds. A user's coffee order matters every morning; a one-off project name from last quarter rarely matters again. Memory Decay makes that intuition explicit at search time: every time a memory is returned in a search it gets a small reinforcement, and memories that haven't been touched in a while have their ranking score gently dampened.
|
||||
|
||||
It is **a soft ranking bias, never a filter.** Decay never zeroes a candidate out — at worst it scales its score by `0.3×`. Anything that would have surfaced without decay can still surface with decay on, just with a different ranking among similarly-scored results.
|
||||
|
||||
<Info>
|
||||
**Use Memory Decay when…**
|
||||
- Search results are crowded with old facts the user no longer cares about.
|
||||
- You want recently-used memories to drift to the top automatically — without writing custom scoring logic.
|
||||
- You want this preference applied per project so cohorts can be compared side-by-side.
|
||||
</Info>
|
||||
|
||||
<Warning>
|
||||
Memory Decay is **opt-in per project** and **off by default**. Search behavior is bit-identical to today until you turn it on. The toggle applies to v3 search only.
|
||||
</Warning>
|
||||
|
||||
## How it works
|
||||
|
||||
Every memory carries a small piece of bookkeeping: when was it last retrieved, and how often. Memory Decay turns that history into a *scaling factor* in the range `0.3×` to `1.5×` and multiplies it into the ranking score at search time.
|
||||
|
||||
| Memory state | Scaling factor | Ranking effect |
|
||||
|---|---|---|
|
||||
| Just accessed | ≈ **1.5×** | Strong boost |
|
||||
| Touched today | 1.2 – 1.4× | Mild boost |
|
||||
| Idle for a few days | 0.6 – 1.0× | Mild dampening |
|
||||
| Idle for weeks | 0.4 – 0.6× | Stronger dampening |
|
||||
| Idle for many months / years | ≈ **0.3×** | Floor — never lower |
|
||||
|
||||
The bounds matter: `0.3` is the floor and `1.5` is the ceiling, so decay can meaningfully reorder candidates without ever dominating the underlying relevance score.
|
||||
|
||||
At search time the pipeline:
|
||||
|
||||
1. Widens the candidate pool (`top_k × 3`, with a floor of 50) so reordering has room.
|
||||
2. Multiplies each candidate's score by its scaling factor.
|
||||
3. Sorts on the unclamped product so the full `0.3×–1.5×` range can rearrange candidates.
|
||||
4. Returns the public `score` clamped to `[0, 1]` so the API contract is preserved.
|
||||
5. Truncates to the `top_k` you requested.
|
||||
6. Records a fire-and-forget reinforcement against each returned memory — its access history grows by one, capped at the most recent 20 touches.
|
||||
|
||||
Memories created before decay was enabled don't yet have an access history. They use a sensible fallback: their `updated_at` is treated as a single past touch, so the same scale above applies based on how stale that update is — a recently-updated legacy memory enters near the neutral band, a long-stale one sits closer to the floor. Once surfaced in a search after decay is on, they accumulate access history naturally and behave like any other memory.
|
||||
|
||||
## Configure access
|
||||
|
||||
- Set `MEM0_API_KEY` in your environment, or pass it to the SDK constructor.
|
||||
- Initialize the client with the organization and project you want to scope to.
|
||||
|
||||
The toggle lives on the project. You enable decay by patching the project's `decay` field; everything else — your `add` calls, your `search` calls, your application code — stays exactly the same.
|
||||
|
||||
## Enable decay for a project
|
||||
|
||||
### 1. Turn the flag on
|
||||
|
||||
The toggle is exposed on the standard project-update endpoint, the same place where `multilingual` and `custom_categories` live.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
client.project.update(decay=True)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
await client.project.update({ decay: true });
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X PATCH https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PROJECT_ID/ \
|
||||
-H "Authorization: Token $MEM0_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"decay": true}'
|
||||
```
|
||||
|
||||
```json Response
|
||||
{ "message": "Updated decay" }
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 2. Confirm the state
|
||||
|
||||
`decay` is returned on every project read. To fetch only this field, use `?fields=decay`.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
response = client.project.get(fields=["decay"])
|
||||
print(response["decay"])
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const response = await client.project.get({ fields: ["decay"] });
|
||||
console.log(response.decay);
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl "https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PROJECT_ID/?fields=decay" \
|
||||
-H "Authorization: Token $MEM0_API_KEY"
|
||||
```
|
||||
|
||||
```json Response
|
||||
{ "decay": true }
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 3. Turn it back off
|
||||
|
||||
The toggle is fully reversible. Setting it to `false` immediately restores the pre-decay ranking; nothing about your stored memories is modified or lost.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
client.project.update(decay=False)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
await client.project.update({ decay: false });
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X PATCH https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PROJECT_ID/ \
|
||||
-H "Authorization: Token $MEM0_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"decay": false}'
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
The toggle is idempotent. Re-applying the same value is a no-op, and access history accumulated while decay was on is preserved if you flip it back on later.
|
||||
</Note>
|
||||
|
||||
## What changes when decay is on
|
||||
|
||||
- **Search ranking reorders.** A relevant memory you reinforced an hour ago will tend to outrank an equally-relevant memory that was last touched a month ago.
|
||||
- **The candidate pool over-fetches** to give the scaling factor room to reorder. You still get exactly the `top_k` you requested, but the items returned can come from a deeper slice of the pre-decay ranking than before.
|
||||
- **The public `score` field stays in `[0, 1]`.** Even when the internal product exceeds 1, the field returned to the client is clamped, so existing assertions and downstream UI logic continue to work.
|
||||
|
||||
## What stays the same
|
||||
|
||||
- **Public API shape** — every endpoint accepts the same parameters and returns the same fields. You don't touch your client code.
|
||||
- **Threshold semantics on the request side** — your `threshold` is still applied during candidate selection.
|
||||
- **Memory creation and storage** — every new memory still lands the same way. Decay is a search-time concern.
|
||||
- **Per-memory data** — categories, metadata, timestamps, embeddings: untouched.
|
||||
|
||||
<Warning>
|
||||
Because the scaling factor is applied *after* the threshold filter has already run, an item that passed the request `threshold` can come back with a public `score` slightly below it (a stale candidate dampened by `0.3×`). This is intentional — decay is a soft bias, not a filter. If you require a hard `score >= threshold` invariant on the response, filter client-side after the call.
|
||||
</Warning>
|
||||
|
||||
## Lifecycle of a memory under decay
|
||||
|
||||
| Stage | Scaling factor | Effect |
|
||||
|---|---|---|
|
||||
| Just added | ≈ 1.5× | Strong boost — fresh facts surface easily. |
|
||||
| Reinforced on a recent search | 1.2 – 1.5× | Sustains its boost for the next several searches. |
|
||||
| Idle for a few days | 0.6 – 1.0× | Falls back into the neutral band. |
|
||||
| Idle for weeks | 0.4 – 0.6× | Mild dampening — can still surface for strong matches. |
|
||||
| Pre-decay legacy memory (no access history) | 0.3 – 1.0× | Falls back to `updated_at`: recently-updated entries land near 1.0×, long-stale entries approach the 0.3× floor. |
|
||||
|
||||
The reinforcement is bounded: each memory tracks at most the last 20 access timestamps, so the boost stays well-behaved no matter how many times a memory is retrieved.
|
||||
|
||||
## FAQ
|
||||
|
||||
**Will decay ever drop a result that would otherwise surface?**
|
||||
No. The floor is `0.3×` — the scaling factor can dampen a score, never zero it. Threshold filtering happens *before* decay, so any candidate that cleared the threshold is in the pool decay reorders.
|
||||
|
||||
**Why is the public score sometimes below my requested threshold?**
|
||||
The threshold is applied to the candidate pool pre-decay; the scaling factor then reshapes scores in the `0.3×–1.5×` band. A stale-but-relevant candidate can come back with a final score slightly under your threshold by design — the candidate stays visible but visibly dampened. Filter client-side if you need a hard floor on the response.
|
||||
|
||||
**Does decay change how I add memories?**
|
||||
No. The `client.add(...)` path is unchanged. Decay is a search-time ranking adjustment.
|
||||
|
||||
**What if I had memories before turning decay on?**
|
||||
They use a fallback: the memory's `updated_at` is treated as a single historical touch, so the same scaling applies based on how stale that update is — a recently-updated legacy memory enters near the neutral band (~1.0×), a long-stale one closer to the floor (~0.3×). Once retrieved they accumulate access history and behave like any other memory.
|
||||
|
||||
**Can I tune how aggressively decay scales scores?**
|
||||
Not in this version. The current scaling is calibrated to be conservative — wide enough to meaningfully reorder candidates, narrow enough to never dominate the underlying relevance score. Per-project tuning is on the roadmap.
|
||||
|
||||
**Can I see the scaling factor per result?**
|
||||
Internal scoring details are persisted on the search Event for support and debugging. They aren't exposed in the public response by design — the response surface stays a single `score` field.
|
||||
|
||||
**Does decay interact with reranking?**
|
||||
Yes — they layer cleanly. The reranker produces a richer relevance score; decay then biases that score by reinforcement history before final truncation to `top_k`.
|
||||
|
||||
## What's next
|
||||
|
||||
This release is deliberately the simplest version of decay we could ship — every memory contributes to ranking through its access history alone, so the signal can be evaluated in isolation. On the roadmap:
|
||||
|
||||
- **Category-aware weighting.** A fact tagged `health` will be able to carry more weight than a passing observation tagged `misc`, so important categories don't get dampened the same way as noise.
|
||||
- **Auto-tuning per project.** Project-scoped automatic adjustment of how aggressively decay scales scores, based on observed access patterns — replacing the fixed scaling band with one that fits your workload.
|
||||
|
||||
Both extensions are forward-compatible — no migration on your side will be needed when they ship.
|
||||
@@ -0,0 +1,145 @@
|
||||
---
|
||||
title: Temporal Reasoning
|
||||
description: "Time-aware memory retrieval for Mem0 Platform v3 so queries like 'last week', 'upcoming', and 'right now' return the right memories."
|
||||
icon: "clock"
|
||||
badge: "v3"
|
||||
---
|
||||
|
||||
Some memories matter because of **when** they happened, not just because they sound similar. Temporal Reasoning lets Mem0 Platform v3 understand time-aware queries and return the most contextually appropriate results.
|
||||
|
||||
<Info>
|
||||
**Use Temporal Reasoning when…**
|
||||
- Users ask questions like "what happened last week?" or "what do I have coming up?"
|
||||
- Your app stores both past events and future plans for the same person
|
||||
- You want time-aware retrieval without building your own date-parsing layer
|
||||
</Info>
|
||||
|
||||
<Warning>
|
||||
Temporal Reasoning is a **Mem0 Platform v3** feature. It is not available on OSS memory stores or older Platform endpoints.
|
||||
</Warning>
|
||||
|
||||
## Configure access
|
||||
|
||||
Confirm your `MEM0_API_KEY` is set and that you are using the v3 Platform client:
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
When a memory describes an event, a future plan, or an ongoing state, Temporal Reasoning recognizes the time context so the right results surface at search time.
|
||||
|
||||
A query like `what did I do last week?` should return a completed past event — not an upcoming appointment and not a stable fact that hasn't changed. Temporal Reasoning handles that distinction automatically.
|
||||
|
||||
### Memory types Temporal Reasoning handles
|
||||
|
||||
| Type | What it represents | Example |
|
||||
| --- | --- | --- |
|
||||
| Dated occurrence | Something that happened at a known time | "I finished the Q1 review on March 10, 2025." |
|
||||
| Future plan | A future commitment or scheduled item | "I have a dentist appointment on March 18, 2025." |
|
||||
| Ongoing state | A fact that remains true over time | "I am the product lead at Acme Corp." |
|
||||
| Relationship | A durable connection between people or entities | "Priya manages Jordan." |
|
||||
| Preference | A stable preference or habit | "I prefer morning meetings." |
|
||||
|
||||
Results come back in the normal search response shape — Temporal Reasoning affects ranking, not the response format.
|
||||
|
||||
## Configure it
|
||||
|
||||
Temporal Reasoning is enabled by default for all v3 searches and writes. There is no per-request toggle.
|
||||
|
||||
Two parameters give you precise control when you need it:
|
||||
|
||||
- `timestamp` on `add()` — anchors an imported memory to the time it actually happened, rather than the time it was added to Mem0
|
||||
- `reference_date` on `search()` — resolves relative phrases like `last week` against a fixed point in time
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from datetime import datetime, timezone
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
# Import a historical memory anchored to when it happened
|
||||
client.add(
|
||||
[{"role": "user", "content": "I finished the Q1 review on March 10, 2025."}],
|
||||
user_id="jordan",
|
||||
timestamp=int(datetime(2025, 3, 10, tzinfo=timezone.utc).timestamp()),
|
||||
)
|
||||
|
||||
# Search with a relative query anchored to a known date
|
||||
results = client.search(
|
||||
"what did I do last week?",
|
||||
filters={"user_id": "jordan"},
|
||||
reference_date="2025-03-21T00:00:00Z",
|
||||
)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import { MemoryClient } from "mem0ai";
|
||||
|
||||
const client = new MemoryClient({ apiKey: "your-api-key" });
|
||||
|
||||
// Import a historical memory anchored to when it happened
|
||||
await client.add(
|
||||
[{ role: "user", content: "I finished the Q1 review on March 10, 2025." }],
|
||||
{
|
||||
userId: "jordan",
|
||||
timestamp: Math.floor(new Date("2025-03-10T00:00:00Z").getTime() / 1000),
|
||||
}
|
||||
);
|
||||
|
||||
// Search with a relative query anchored to a known date
|
||||
const results = await client.search("what did I do last week?", {
|
||||
filters: { user_id: "jordan" },
|
||||
referenceDate: "2025-03-21T00:00:00Z",
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
`reference_date` is especially useful in automated tests and demos because it makes relative phrases like `last week` resolve consistently every time.
|
||||
</Tip>
|
||||
|
||||
## Supported query patterns
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Historical questions">
|
||||
Examples: `last week`, `last month`, `in March 2025`, `on 2025-03-10`
|
||||
</Accordion>
|
||||
<Accordion title="Upcoming questions">
|
||||
Examples: `upcoming`, `next week`, `tomorrow`, `what do I have coming up?`
|
||||
</Accordion>
|
||||
<Accordion title="Current-state questions">
|
||||
Examples: `right now`, `currently`, `where do I work now?`
|
||||
</Accordion>
|
||||
<Accordion title="As-of questions">
|
||||
Examples: `as of March 2025`, `where was I living as of 2024?`
|
||||
</Accordion>
|
||||
<Accordion title="Duration questions">
|
||||
Examples: `how long have I lived here?`, `since when have I worked there?`
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Verify the feature is working
|
||||
|
||||
- Run a temporal search with a time-aware query (e.g., "what did I do last week?") and confirm the memory that fits the time window ranks first.
|
||||
- Use `reference_date` in test queries so relative phrases resolve consistently across runs.
|
||||
- For backfilled data, pass `timestamp` on `add()` to confirm the memory reflects the right point in time.
|
||||
|
||||
## Best practices
|
||||
|
||||
- Use explicit dates in source conversations when events or plans matter temporally.
|
||||
- Pass `timestamp` during historical imports so the ingestion time does not become the only time anchor.
|
||||
- Scope searches with `filters` so time-aware ranking operates inside the right user boundary.
|
||||
- Use `reference_date` in automated tests and reproducible demos.
|
||||
|
||||
<CardGroup cols={1}>
|
||||
<Card title="Memory Timestamps" icon="calendar" href="/platform/features/timestamp">
|
||||
Anchor imported memories to when they actually happened.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -7,10 +7,10 @@ estimatedTime: "~2 minutes"
|
||||
|
||||
<Info>
|
||||
**Prerequisites**
|
||||
- Mem0 Platform account (<a href="https://app.mem0.ai" rel="nofollow">Sign up here</a>)
|
||||
- API key (<a href="https://app.mem0.ai/settings/api-keys" rel="nofollow">Get one from dashboard</a>)
|
||||
- Mem0 Platform account (<a href="https://app.mem0.ai?utm_source=oss&utm_medium=platform-mem0-mcp" rel="nofollow">Sign up here</a>)
|
||||
- API key (<a href="https://app.mem0.ai/settings/api-keys?utm_source=oss&utm_medium=platform-mem0-mcp" rel="nofollow">Get one from dashboard</a>)
|
||||
- Node.js 14+ (for npx)
|
||||
- An MCP-compatible client (Claude, Claude Code, Cursor, Windsurf, VS Code, OpenCode)
|
||||
- An MCP-compatible client (Claude, Claude Code, Codex, Cursor, Windsurf, VS Code, OpenCode)
|
||||
</Info>
|
||||
|
||||
## What is Mem0 MCP?
|
||||
@@ -46,6 +46,8 @@ The MCP server exposes these memory tools to your AI client:
|
||||
| `delete_all_memories` | Bulk delete all memories in scope |
|
||||
| `delete_entities` | Delete a user/agent/app/run entity and its memories |
|
||||
| `list_entities` | Enumerate users/agents/apps/runs stored in Mem0 |
|
||||
| `list_events` | List memory operation events with filters and pagination |
|
||||
| `get_event_status` | Check the status of an async memory operation by `event_id` |
|
||||
|
||||
---
|
||||
|
||||
@@ -86,6 +88,33 @@ You can also configure individual clients:
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Codex">
|
||||
**Direct MCP (fastest, MCP only).** Codex reads MCP servers from `~/.codex/config.toml` as TOML (not JSON). Add:
|
||||
|
||||
```toml
|
||||
[mcp_servers.mem0]
|
||||
url = "https://mcp.mem0.ai/mcp"
|
||||
bearer_token_env_var = "MEM0_API_KEY"
|
||||
```
|
||||
|
||||
Export `MEM0_API_KEY` in the shell you launch Codex from, then restart Codex. `codex mcp add` only supports stdio servers, so HTTP servers must be added via `config.toml` directly — or via the **Plugins → Connect to a custom MCP → Streamable HTTP** UI in the Codex app.
|
||||
|
||||
<Note>
|
||||
Codex uses the server name `mem0` (not `mem0-mcp` like the other clients on this page) so it matches the name the bundled plugin registers if you ever sideload it later.
|
||||
</Note>
|
||||
|
||||
**Sideloaded plugin (full experience).** If you want the memory protocol skill, Mem0 SDK skill, and opt-in lifecycle hooks alongside the MCP server, sideload the plugin from a clone of `mem0ai/mem0`. The repo ships a marketplace manifest at `.agents/plugins/marketplace.json`, so you can register it with one CLI call:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mem0ai/mem0.git ~/codex-plugins/mem0-source
|
||||
codex plugin marketplace add ~/codex-plugins/mem0-source
|
||||
```
|
||||
|
||||
Then run `codex` and `/plugins`, browse the **Mem0 Plugins** marketplace, and install **Mem0**. Don't combine this with the Direct MCP setup above — the sideloaded plugin auto-registers `mem0` via `.codex-mcp.json`, so a manual `[mcp_servers.mem0]` block would create a duplicate.
|
||||
|
||||
See the [Codex integration guide](/integrations/codex) for full details, lifecycle-hook setup, and management commands (`codex plugin marketplace upgrade` / `remove`).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Cursor">
|
||||
```bash
|
||||
npx mcp-add \
|
||||
@@ -163,7 +192,7 @@ Agent: Updated your project status successfully.
|
||||
```
|
||||
|
||||
<Info icon="check">
|
||||
If you get "Connection failed", ensure you have a valid API key from <a href="https://app.mem0.ai/settings/api-keys" rel="nofollow">Mem0 Dashboard</a>.
|
||||
If you get "Connection failed", ensure you have a valid API key from <a href="https://app.mem0.ai/settings/api-keys?utm_source=oss&utm_medium=platform-mem0-mcp" rel="nofollow">Mem0 Dashboard</a>.
|
||||
</Info>
|
||||
|
||||
---
|
||||
@@ -171,7 +200,7 @@ Agent: Updated your project status successfully.
|
||||
## Quick Recovery
|
||||
|
||||
- **"Connection refused"** → Check your internet connection and ensure the MCP client is correctly configured
|
||||
- **"Invalid API key"** → Get a new key from <a href="https://app.mem0.ai/settings/api-keys" rel="nofollow">Mem0 Dashboard</a>
|
||||
- **"Invalid API key"** → Get a new key from <a href="https://app.mem0.ai/settings/api-keys?utm_source=oss&utm_medium=platform-mem0-mcp" rel="nofollow">Mem0 Dashboard</a>
|
||||
- **"npx command not found"** → Install Node.js from [nodejs.org](https://nodejs.org)
|
||||
|
||||
---
|
||||
|
||||
@@ -60,7 +60,7 @@ Mem0 is the memory engine that keeps conversations contextual so users never rep
|
||||
<Card title="Connect Integrations" icon="plug" href="/integrations">
|
||||
LangChain, CrewAI, Vercel AI SDK.
|
||||
</Card>
|
||||
<Card title="Monitor in the Dashboard" icon="presentation" href="https://app.mem0.ai/login">
|
||||
<Card title="Monitor in the Dashboard" icon="presentation" href="https://app.mem0.ai/login?utm_source=oss&utm_medium=platform-overview">
|
||||
Track activity and manage workspaces.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -150,7 +150,7 @@ Mem0 offers two powerful ways to add memory to your AI applications. Choose base
|
||||
<Card
|
||||
title="Try Platform Free"
|
||||
icon="rocket"
|
||||
href="https://app.mem0.ai/login"
|
||||
href="https://app.mem0.ai/login?utm_source=oss&utm_medium=platform-vs-oss"
|
||||
>
|
||||
Sign up and test the Platform with our free tier. No credit card required.
|
||||
</Card>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user