feat(skills): add mem0-oss-to-platform migration skill (#5455)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
This commit is contained in:
co-authored by
Claude Opus 4.8
kartik-mem0
parent
1d56f85705
commit
f48b133101
@@ -0,0 +1,117 @@
|
||||
# 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
|
||||
|
||||
## Contents
|
||||
- [Python](#python)
|
||||
- [TypeScript / JavaScript](#typescript--javascript)
|
||||
- [Return shapes](#return-shapes)
|
||||
- [Dependencies & environment](#dependencies--environment)
|
||||
- [v2→v3 default/behavior changes](#v2v3-defaultbehavior-changes)
|
||||
|
||||
---
|
||||
|
||||
## Python
|
||||
|
||||
### Import & client construction
|
||||
```python
|
||||
# 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_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.
|
||||
- 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 |
|
||||
| get | `memory.get(memory_id)` | `memory.get(memory_id)` |
|
||||
| update | `memory.update(memory_id, data=...)` | `memory.update(memory_id, text=...)` — confirm param name against installed sig |
|
||||
| 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. |
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
```typescript
|
||||
// OSS (self-hosted) — note the "/oss" subpath
|
||||
import { Memory } from "mem0ai/oss";
|
||||
const memory = new Memory({ /* vectorStore, embedder, llm, historyStore … */ });
|
||||
|
||||
// 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.
|
||||
```
|
||||
|
||||
### Method calls (option-object differences)
|
||||
| Operation | OSS / old client | Hosted client (v3) |
|
||||
|---|---|---|
|
||||
| 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 |
|
||||
|
||||
Also drop legacy options that no longer apply on v3: `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.
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & environment
|
||||
- **Keep** the `mem0ai` dependency — `MemoryClient` ships 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_KEY` to 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.
|
||||
|
||||
## 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.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Gotchas — the things that aren't a clean 1:1
|
||||
|
||||
Swapping `Memory` for `MemoryClient` is mostly mechanical. These items are *not* mechanical: they
|
||||
change behavior, move responsibility off the developer's machine, or have no direct equivalent.
|
||||
Every one that applies to the project belongs in the plan's **"Concerns & decisions needed"**
|
||||
section, phrased as a decision for the developer — never silently resolved.
|
||||
|
||||
## 1. Data does not migrate with the code
|
||||
Migrating the *code* does not move the *memories*. Anything stored in the local vector store /
|
||||
history DB stays there; the hosted account starts empty. This is the most surprising gap, so call
|
||||
it out prominently. Data migration is **out of scope** unless the developer explicitly asks. If they
|
||||
do, the rough path is: read everything from the OSS store (`get_all` per user/entity) and re-`add`
|
||||
it to the hosted client — but treat that as a separate, opt-in task.
|
||||
|
||||
## 2. Self-hosting / data residency
|
||||
A local or self-hosted vector store sometimes exists *on purpose* — compliance, data residency, air-
|
||||
gapped deployment, cost. Moving to the managed platform sends memory content to mem0's servers.
|
||||
Don't assume that's acceptable; flag it as an explicit decision, especially for regulated domains.
|
||||
|
||||
## 3. Local models move server-side
|
||||
If the OSS config used specific local/self-chosen models (e.g. Ollama, a particular embedder, a
|
||||
non-OpenAI LLM for fact extraction), those choices disappear — extraction and embedding now run on
|
||||
the platform with the platform's configuration. Memory *content and quality may shift* as a result.
|
||||
Flag where the project depended on a specific model.
|
||||
|
||||
## 4. Graph memory
|
||||
If the project uses graph memory (`enable_graph`, `graph_store`), this changed in v3 and is handled
|
||||
differently on the platform. Don't assume a drop-in mapping — verify current platform graph support
|
||||
in the docs and flag the usage for the developer.
|
||||
|
||||
## 5. Custom prompts / extraction config
|
||||
`custom_fact_extraction_prompt` → `custom_instructions`, and `custom_update_memory_prompt` is
|
||||
deprecated. On the platform these tend to be **project-level settings configured in the dashboard**
|
||||
rather than passed in code. Flag any custom prompt the project relied on so the developer can re-
|
||||
apply it in the dashboard.
|
||||
|
||||
## 6. Every call is now a network request
|
||||
Local calls become remote API calls. That introduces latency, network failures, timeouts, rate
|
||||
limits, and per-call cost. Flag mem0 calls on hot paths or in tight loops, and recommend adding
|
||||
error handling / retries / timeouts where the old local calls were effectively infallible. For async
|
||||
apps, use `AsyncMemoryClient` (Python) so calls don't block the event loop.
|
||||
|
||||
## 7. API key & secrets
|
||||
The hosted client needs `MEM0_API_KEY`. It must come from the environment / a secrets manager — never
|
||||
hardcoded. Ensure it's added to `.env.example`, local `.env`, CI, and deployment config. Without it
|
||||
the client fails to initialize.
|
||||
|
||||
## 8. Dropped constructor args & legacy options
|
||||
`org_id` / `project_id` (Python) and `organizationId` / `projectId` (TS) are no longer passed to the
|
||||
constructor in v3 — they're resolved from the API key. Per-call legacy options like `async_mode`,
|
||||
`output_format`, and `enable_graph` are gone. Remove them rather than leaving dead args.
|
||||
|
||||
## 9. Return-shape drift
|
||||
- `add()` returns **only ADD events** on v3. Code that inspected `add()` results for `UPDATE` /
|
||||
`DELETE` events has dead branches now.
|
||||
- `search` / `get_all` return `{"results": [...]}`; `get_all` is paginated (`count`/`next`/
|
||||
`previous`/`results`). Code that limited via `top_k` on `get_all` should move to `page`/`page_size`.
|
||||
- Default `top_k` dropped 100 → 20, `threshold` now `0.1`, `rerank` now `false` — result counts and
|
||||
ordering can change even when the call looks equivalent.
|
||||
|
||||
## 10. No global `reset()`
|
||||
The OSS `reset()` wipes the whole local store. There's no hosted equivalent that nukes everything;
|
||||
use `delete_all` scoped by `filters`. Flag any `reset()` call.
|
||||
@@ -0,0 +1,72 @@
|
||||
# Plan template — `MEM0_MIGRATION_PLAN.md`
|
||||
|
||||
Write the plan to `MEM0_MIGRATION_PLAN.md` at the repo root using the structure below. Keep it
|
||||
concrete enough to execute from and honest about the gaps. Fill every section from the actual
|
||||
findings — don't leave placeholders. Drop a section only if it genuinely doesn't apply (and say so).
|
||||
|
||||
```markdown
|
||||
# mem0 OSS → Platform Migration Plan
|
||||
|
||||
## Summary
|
||||
- One paragraph: what's moving (self-hosted `Memory` → hosted `MemoryClient`) and why.
|
||||
- Detected language(s) and the installed `mem0ai` version.
|
||||
- Counts: N files touched, M call sites, plus config/deps/env changes.
|
||||
|
||||
## Prerequisites
|
||||
- `MEM0_API_KEY` must be set in the environment before execution/verification (https://app.mem0.ai).
|
||||
- Note where it should live (`.env`, secrets manager, CI, deploy config).
|
||||
|
||||
## Inventory
|
||||
A table of every mem0 touchpoint found, so the developer can see the full footprint:
|
||||
|
||||
| File:line | Current (OSS) usage | Category | Maps to |
|
||||
|-----------|--------------------|----------|---------|
|
||||
| path:LN | `Memory.from_config({...})` | client init | `MemoryClient()` |
|
||||
| path:LN | `memory.search(q, user_id=...)` | call site | `search(q, filters={...}, top_k=...)` |
|
||||
| ... | ... | config / dep / env / infra | ... |
|
||||
|
||||
## Change set
|
||||
Grouped by file. For each, a short before → after with the actual surrounding code, so the edits are
|
||||
unambiguous. Example:
|
||||
|
||||
### `path/to/file.py`
|
||||
- Replace import `from mem0 import Memory` → `from mem0 import MemoryClient`.
|
||||
- Replace the `Memory.from_config({...})` block with `MemoryClient()` (drops local vector_store/
|
||||
llm/embedder/history config).
|
||||
- `search(...)`: move `user_id` into `filters={"user_id": ...}`; keep `top_k`.
|
||||
```
|
||||
# before
|
||||
...
|
||||
# after
|
||||
...
|
||||
```
|
||||
|
||||
## Dependencies & config
|
||||
- `requirements.txt` / `pyproject.toml` / `package.json`: keep `mem0ai`; remove now-unused local-
|
||||
infra deps (list them, with the reason each is safe to remove).
|
||||
- Env: add `MEM0_API_KEY`; remove env vars only used by the old local embedder/LLM if now unused.
|
||||
- Infrastructure: local services that existed only for mem0 (e.g. a Qdrant docker-compose service)
|
||||
can be retired — listed for the developer's confirmation, not auto-deleted.
|
||||
|
||||
## Concerns & decisions needed
|
||||
The non-1:1 items from the gotchas that apply here, each phrased as a decision for the developer.
|
||||
Cover, where relevant: data not migrating, self-hosting/data-residency, local models moving server-
|
||||
side, graph memory, custom prompts (now dashboard settings), network/latency/cost on hot paths,
|
||||
return-shape changes (`add` ADD-only, `get_all` pagination, default `top_k`/threshold/rerank), and
|
||||
any `reset()` usage. Be specific about which file/line each concern affects.
|
||||
|
||||
## Out of scope
|
||||
- Existing memory **data** is not migrated (code only). If wanted, it's a separate opt-in task
|
||||
(export from the OSS store, re-add to the hosted client).
|
||||
- No unrelated refactors, renames, or behavior changes.
|
||||
|
||||
## Verification plan
|
||||
How execution will be confirmed end-to-end:
|
||||
- Imports / type-checks / byte-compiles cleanly.
|
||||
- Smoke test against the hosted API with a real `MEM0_API_KEY`: `add` a fact → `search`/`get_all`
|
||||
returns it → `delete_all` clears it. Plus: the app's own entry point still runs.
|
||||
- Confirm no local mem0 storage dir is created anymore (e.g. `.mem0/`) — proof memory is hosted.
|
||||
|
||||
## Rollback
|
||||
- All changes are in version control; revert with git if needed. Note the branch/commit strategy.
|
||||
```
|
||||
Reference in New Issue
Block a user