12 KiB
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), 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
- TypeScript / JavaScript
- Return shapes
- Dependencies & environment
- OSS vs Platform defaults and behavior
Python
Import & client construction
# OSS (self-hosted)
from mem0 import Memory
memory = Memory() # or:
memory = Memory.from_config({ # all of this local config disappears
"vector_store": {...},
"llm": {...},
"embedder": {...},
"history_db_path": "...",
})
# Platform (hosted)
from mem0 import MemoryClient
memory = MemoryClient() # reads MEM0_API_KEY from the env
# or: MemoryClient(api_key="...")
Notes:
- The client reads
MEM0_API_KEYfrom the environment whenapi_keyis omitted. - Drop
vector_store,llm,embedder,reranker,history_db_path,version(andgraph_storeif a pre-2.0 config still has it): these are managed server-side now. custom_instructionsdoes have a hosted equivalent:client.project.update(custom_instructions=...)(project-wide) orcustom_instructions=onadd().- Drop
org_id/project_idconstructor 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"): 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=..., 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) |
| 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
The hosted and OSS SDKs ship in the same mem0ai npm package, distinguished by import path.
Confirm option names against node_modules/mem0ai/ types.
Import & client construction
// OSS (self-hosted): note the "/oss" subpath
import { Memory } from "mem0ai/oss";
const memory = new Memory({ /* vectorStore, embedder, llm, historyStore, reranker, customInstructions … */ });
// Platform (hosted): default export from the package root
import MemoryClient from "mem0ai";
const memory = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
Notes:
- Unlike Python, the TS client does not read
MEM0_API_KEYitself:apiKeyis required and the constructor throws if it is empty. Pass it explicitly. - Drop
organizationId/projectIdif present, they're resolved from the API key. - Drop
vectorStore,embedder,llm,historyStore,historyDbPath,reranker,disableHistory,version.customInstructionsmaps toclient.updateProject({ customInstructions })orcustomInstructionsonadd().
Method calls (option-object differences)
| Operation | OSS Memory |
Hosted client |
|---|---|---|
| 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: async_mode, output_format, enable_graph.
Return shapes
-
search(...)returns{"results": [...]}on both sides; each item has at least amemory(text) field, plusidandscore. Code that readsresult["results"]and pullsitem["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-levelevent). The hostedaddis 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 returnArray<Memory>does not reflect this). New memories may not be searchable yet. Onlyinfer=Falseis synchronous and returnsresults. Neither SDK has an event-poll method: pollGET /v1/event/{event_id}/over REST if you must wait. Code that readsid/memoryfromadd()results must change, and any 1.x-era branch onevent == "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_atHosted TS id,memoryId,input,oldMemory,newMemory,event,userId,categories,metadata,createdAt,updatedAtCode that reads
previous_value/new_value/actionfrom TS OSS history must switch tooldMemory/newMemory/eventon the hosted TS client.
Dependencies & environment
- Keep the
mem0aidependency —MemoryClientships in the same package. No version bump is required just to use the hosted client (confirm the installed version supports it). - Remove dependencies that existed only to back the local mem0 store/embedder/LLM and are now
unused (e.g.
qdrant-client,chromadb, a local embedding lib). Only remove what you can confirm is unused elsewhere. - Add
MEM0_API_KEYto the environment /.env.example/ secrets manager / deployment config. - 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.
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: OSStop_k=20,threshold=0.1,rerank=False. Platformtop_k=10(allowed 1 to 1000),rerank=false, andthresholdis a server-side cutoff, not a floor on the returnedscore. Passtop_kexplicitly to keep the old result count.get_all: OSStop_k=20, not paginated. Platformpage=1,page_size=100.custom_fact_extraction_prompt(TScustomPrompt) was renamedcustom_instructions(customInstructions) in OSS 2.0/3.0;custom_update_memory_promptis 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_dateanddecayraise on OSS. - OSS-only (no Platform option):
rerankerandhistory_db_pathconfig,memory_typeandpromptonadd,explainonsearch.