docs(skills): refresh mem0 skills against SDK 2.2.1 / TS 3.3.1 (#7548)

This commit is contained in:
Kartik
2026-10-07 18:36:15 +05:30
committed by GitHub
parent d62ce07fac
commit b7ad69afda
33 changed files with 1239 additions and 814 deletions
@@ -1,16 +1,17 @@
# OSS → Platform API mapping
Exact translation of the mem0 OSS (self-hosted `Memory`) API to the hosted `MemoryClient` API.
**Always confirm against the installed package** (see SKILL.md Phase 2) — versions drift. The facts
below match `mem0ai` 2.0.x (the v3 platform API) and the official guide:
https://docs.mem0.ai/migration/oss-v2-to-v3
**Always confirm against the installed package** (see SKILL.md Phase 2), since versions drift. The
facts below match Python `mem0ai` 2.2.x and TypeScript `mem0ai` 3.3.x (the `/v3/memories/*` platform
API). Moving stored data: https://docs.mem0.ai/migration/oss-to-platform. OSS upgrade changes
(Python 1.x to 2.x, TS 2.x to 3.x): https://docs.mem0.ai/migration/oss-v2-to-v3
## Contents
- [Python](#python)
- [TypeScript / JavaScript](#typescript--javascript)
- [Return shapes](#return-shapes)
- [Dependencies & environment](#dependencies--environment)
- [v2→v3 default/behavior changes](#v2v3-defaultbehavior-changes)
- [OSS vs Platform defaults and behavior](#oss-vs-platform-defaults-and-behavior)
---
@@ -35,28 +36,38 @@ memory = MemoryClient() # reads MEM0_API_KEY from the env
```
Notes:
- The client reads `MEM0_API_KEY` from the environment when `api_key` is omitted.
- **Drop** `vector_store`, `llm`, `embedder`, `graph_store`, `history_db_path` — these are managed
server-side now.
- **Drop** `org_id` / `project_id` constructor args if present — they're resolved from the API key
in v3.
- **Drop** `vector_store`, `llm`, `embedder`, `reranker`, `history_db_path`, `version` (and
`graph_store` if a pre-2.0 config still has it): these are managed server-side now.
- `custom_instructions` does have a hosted equivalent: `client.project.update(custom_instructions=...)`
(project-wide) or `custom_instructions=` on `add()`.
- **Drop** `org_id` / `project_id` constructor args if present, they're resolved from the API key.
- For async codebases, use `AsyncMemoryClient` (same methods, `await`-ed).
### Method calls
| Operation | OSS `Memory` | Hosted `MemoryClient` |
|---|---|---|
| add | `memory.add(messages, user_id="u")` | `memory.add(messages, user_id="u")` — unchanged (top-level entity IDs accepted) |
| search | `memory.search(q, user_id="u", limit=N)` *(older)* or `…, filters={"user_id":"u"}, top_k=N` *(newer)* | `memory.search(q, filters={"user_id": "u"}, top_k=N)` — entity IDs **must** be inside `filters`; top-level `user_id`/`agent_id`/`app_id`/`run_id` raise `ValueError` |
| get_all | `memory.get_all(user_id="u")` or `…, filters={"user_id":"u"}` | `memory.get_all(filters={"user_id": "u"}, page=1, page_size=N)` — entity IDs in `filters`; paginated with `page`/`page_size` (**not** `top_k`) |
| delete_all | `memory.delete_all(user_id="u")` | `memory.delete_all(user_id="u")` — unchanged |
| add | `memory.add(messages, user_id="u")` | `memory.add(messages, user_id="u")`: same call (top-level entity IDs accepted, plus `app_id`), but the return value differs (see Return shapes) |
| search | `memory.search(q, filters={"user_id": "u"}, top_k=N)` (pre-2.0 code used top-level `user_id=` and `limit=`) | `memory.search(q, filters={"user_id": "u"}, top_k=N)`: entity IDs **must** be inside `filters`; top-level `user_id`/`agent_id`/`app_id`/`run_id` raise `ValueError` (on OSS 2.x too) |
| get_all | `memory.get_all(filters={"user_id": "u"}, top_k=N)` (not paginated) | `memory.get_all(filters={"user_id": "u"}, page=1, page_size=N)`: entity IDs in `filters`; paginated with `page`/`page_size` (**not** `top_k`) |
| delete_all | `memory.delete_all(user_id="u")` | `memory.delete_all(user_id="u")`: same call (entity IDs are query params, at least one is required, `"*"` is a wildcard). `delete_all(filters=...)` is **not** a Platform form |
| get | `memory.get(memory_id)` | `memory.get(memory_id)` |
| update | `memory.update(memory_id, text=...)` *(`data=` is a deprecated alias)* | `memory.update(memory_id, text=...)` — unchanged |
| update | `memory.update(memory_id, text=...)` *(`data=` is a deprecated alias)* | `memory.update(memory_id, text=..., metadata=...)`: use keyword `text=`. A positional string (`update(id, "new text")`) breaks because the second positional is `options`, and there is no `data=` alias |
| delete | `memory.delete(memory_id)` | `memory.delete(memory_id)` |
| reset | `memory.reset()` (wipes the local store) | **No global reset.** Use `memory.delete_all(filters=...)` scoped to the relevant entity. Flag this. |
| history | `memory.history(memory_id)` | `memory.history(memory_id)`: same call, extra fields on each entry (`input`, `user_id`, `categories`, `metadata`); OSS-only `is_deleted`/`actor_id`/`role` are absent (see Return shapes) |
| reset | `memory.reset()` (wipes the local store) | `memory.reset()` exists but calls `delete_users()`, which deletes **all** users, agents, sessions and memories (first page of entities only, see gotchas). Prefer `delete_all` scoped to an entity. Flag this |
Key rule: for **search** and **get_all**, the hosted client requires entity IDs (`user_id`,
`agent_id`, `app_id`, `run_id`) inside a `filters` dict and will raise if you pass them top-level.
For **add** and **delete_all**, top-level entity IDs are accepted.
Filter differences: Platform validates each top-level filter key against a fixed allowlist
(`AND`/`OR`/`NOT`, `user_id`, `agent_id`, `app_id`, `run_id`, `created_at`, `updated_at`, `timestamp`,
`expiration_date`, `categories`, `metadata`, `memory_ids`, `keywords`) and
returns 400 for anything else, so custom metadata keys must be nested under `"metadata"`
(`{"metadata": {"plan": "pro"}}`). Platform `metadata` supports only `eq`/`ne`/`contains` (`contains` is case-sensitive and matches the whole value or one list member, not a substring), and there is
no `nin` (use `{"NOT": [{"categories": {"in": [...]}}]}`; `NOT` must be a list). OSS accepts arbitrary
metadata keys and a wider operator set. Flag any OSS filter that depends on either. Do not filter on `text`: search fails with a 503 and `get_all` rejects it. Pass the text as the search `query`.
---
## TypeScript / JavaScript
@@ -66,36 +77,64 @@ Confirm option names against `node_modules/mem0ai/` types.
### Import & client construction
```typescript
// OSS (self-hosted) — note the "/oss" subpath
// OSS (self-hosted): note the "/oss" subpath
import { Memory } from "mem0ai/oss";
const memory = new Memory({ /* vectorStore, embedder, llm, historyStore … */ });
const memory = new Memory({ /* vectorStore, embedder, llm, historyStore, reranker, customInstructions … */ });
// Platform (hosted) — default export from the package root
// Platform (hosted): default export from the package root
import MemoryClient from "mem0ai";
const memory = new MemoryClient({ apiKey: process.env.MEM0_API_KEY });
// Drop organizationId / projectId — resolved from the API key in v3.
const memory = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
```
Notes:
- Unlike Python, the TS client does **not** read `MEM0_API_KEY` itself: `apiKey` is required and the
constructor throws if it is empty. Pass it explicitly.
- Drop `organizationId` / `projectId` if present, they're resolved from the API key.
- Drop `vectorStore`, `embedder`, `llm`, `historyStore`, `historyDbPath`, `reranker`, `disableHistory`,
`version`. `customInstructions` maps to `client.updateProject({ customInstructions })` or
`customInstructions` on `add()`.
### Method calls (option-object differences)
| Operation | OSS / old client | Hosted client (v3) |
| Operation | OSS `Memory` | Hosted client |
|---|---|---|
| add | `memory.add(messages, { userId: "u" })` | `memory.add(messages, { userId: "u" })` — unchanged |
| search | `memory.search(q, { userId: "u", limit: 20 })` | `memory.search(q, { filters: { userId: "u" }, topK: 20 })` — entity IDs into `filters`; `limit` → `topK` |
| getAll | `memory.getAll({ userId: "u" })` | `memory.getAll({ filters: { userId: "u" } })` — entity IDs into `filters` |
| deleteAll | `memory.deleteAll({ userId: "u" })` | `memory.deleteAll({ userId: "u" })` |
| get / update / delete | `memory.get(id)` etc. | same, by memory id |
| add | `memory.add(messages, { userId: "u" })` (`messages` may be a string or `Message[]`) | `memory.add(messages, { userId: "u" })`: `messages` must be `Message[]` (wrap a bare string as `[{ role: "user", content: str }]`); the response is an async event (see Return shapes) |
| search | `memory.search(q, { filters: { user_id: "u" }, topK: 20 })` (pre-3.0 code used top-level `userId` and `limit`) | `memory.search(q, { filters: { user_id: "u" }, topK: 20 })`: entity IDs go inside `filters` with **snake_case** keys (`user_id`, not `userId`); top-level `userId` throws; `limit` → `topK` |
| getAll | `memory.getAll({ filters: { user_id: "u" }, topK: 20 })` (not paginated) | `memory.getAll({ filters: { user_id: "u" }, page: 1, pageSize: 50 })`: paginated with `page`/`pageSize` (not `topK`) |
| deleteAll | `memory.deleteAll({ userId: "u" })` | `memory.deleteAll({ userId: "u" })`: same call (at least one entity ID is required) |
| update | `memory.update(id, "new text")` or `memory.update(id, { text, metadata })` | `memory.update(id, { text: "new text" })`: the options object is required, a bare string throws |
| get / delete / history | `memory.get(id)` etc. | same, by memory id (`history` field names differ, see Return shapes) |
| reset | `memory.reset()` (wipes the local store) | No `reset()` on the TS client. `deleteUsers()` with no arguments deletes all users, agents, sessions and memories (first page of entities only, see gotchas). Prefer `deleteAll` scoped to an entity. Flag this |
Also drop legacy options that no longer apply on v3: `async_mode`, `output_format`, `enable_graph`.
Also drop legacy options that no longer apply: `async_mode`, `output_format`, `enable_graph`.
---
## Return shapes
- `search(...)` and `get_all(...)` return `{"results": [...]}`; each item has at least a `memory`
(text) field, plus `id` and (for search) `score`. Code that reads `result["results"]` and pulls
`item["memory"]` keeps working.
- `get_all(...)` on the hosted client is paginated: `{"count", "next", "previous", "results": [...]}`.
- `add(...)` returns the created memories. On v3 it returns **only ADD events** — if the old code
branched on `event == "UPDATE"` / `"DELETE"` from `add()` results, that branch is now dead.
- `search(...)` returns `{"results": [...]}` on both sides; each item has at least a `memory` (text)
field, plus `id` and `score`. Code that reads `result["results"]` and pulls `item["memory"]` keeps
working.
- `get_all(...)`: OSS returns `{"results": [...]}` (no pagination). The hosted client is paginated:
`{"count", "next", "previous", "results": [...]}`.
- `add(...)`: OSS extracts synchronously on both runtimes, but the event sits in a different place:
Python OSS returns `{"results": [{"id", "memory", "event": "ADD"}]}`, TS OSS returns
`{ results: [{ id, memory, metadata: { event: "ADD" } }] }` (no top-level `event`).
The hosted `add` is **asynchronous by default** and returns `{"status": "PENDING", "event_id": "..."}`
from Python. The TS hosted client camelCases response keys, so it returns
`{ status: "PENDING", eventId: "..." }` (its typed return `Array<Memory>` does not reflect this).
New memories may not be searchable yet. Only `infer=False` is synchronous and returns `results`.
Neither SDK has an event-poll method: poll `GET /v1/event/{event_id}/` over REST if you must wait.
Code that reads `id`/`memory` from `add()` results must change, and any 1.x-era branch on
`event == "UPDATE"` / `"DELETE"` is dead on both sides (add is ADD-only since 2.0).
- `history(...)` field names differ on all four runtimes:
| Runtime | Entry fields |
|---|---|
| Python OSS | `id`, `memory_id`, `old_memory`, `new_memory`, `event`, `created_at`, `updated_at`, `is_deleted`, `actor_id`, `role` (oldest first) |
| TS OSS | `id`, `memory_id`, `previous_value`, `new_value`, `action`, `created_at`, `updated_at`, `is_deleted` (raw rows, snake_case, newest first) |
| Hosted Python | `id`, `memory_id`, `input`, `old_memory`, `new_memory`, `event`, `user_id`, `categories`, `metadata`, `created_at`, `updated_at` |
| Hosted TS | `id`, `memoryId`, `input`, `oldMemory`, `newMemory`, `event`, `userId`, `categories`, `metadata`, `createdAt`, `updatedAt` |
Code that reads `previous_value` / `new_value` / `action` from TS OSS history must switch to
`oldMemory` / `newMemory` / `event` on the hosted TS client.
---
@@ -109,9 +148,18 @@ Also drop legacy options that no longer apply on v3: `async_mode`, `output_forma
- Local-infra services (e.g. a Qdrant docker-compose service) that existed only for mem0 can be
retired — flag this rather than deleting infrastructure unilaterally.
## v2→v3 default/behavior changes
From the official migration guide — surface any that affect the project:
- Python `top_k` default changed 100 → 20; TS `limit` renamed to `topK`.
- New `threshold` default `0.1` (was none); new `rerank` default `false` (was true).
- `custom_fact_extraction_prompt` → `custom_instructions`; `custom_update_memory_prompt` deprecated.
- Graph memory (`enable_graph`, `graph_store`) removed from the OSS v3 surface — see gotchas.
## OSS vs Platform defaults and behavior
Surface any that affect the project. Defaults differ between the two sides even when a call looks
identical:
- `search`: OSS `top_k=20`, `threshold=0.1`, `rerank=False`. Platform `top_k=10` (allowed 1 to 1000),
`rerank=false`, and `threshold` is a server-side cutoff, not a floor on the returned `score`. Pass `top_k` explicitly to keep the old result count.
- `get_all`: OSS `top_k=20`, not paginated. Platform `page=1`, `page_size=100`.
- `custom_fact_extraction_prompt` (TS `customPrompt`) was renamed `custom_instructions`
(`customInstructions`) in OSS 2.0/3.0; `custom_update_memory_prompt` is deprecated. See the
constructor notes for the hosted equivalent.
- Graph memory (`enable_graph`, `graph_store`) was removed from OSS (Python 2.0.0, TS 3.0.0). On the
Platform graph is built in and always on, with no flag. See gotchas.
- Platform-only: `app_id`, webhooks, custom categories, batch update/delete, feedback, memory export,
user profiles. `timestamp`, `reference_date` and `decay` raise on OSS.
- OSS-only (no Platform option): `reranker` and `history_db_path` config, `memory_type` and `prompt`
on `add`, `explain` on `search`.