diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 82ce93578..8b0e16623 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -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.1" } ] } diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index c23fc2e22..e5e868c49 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -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" } ] } diff --git a/README.md b/README.md index a0eef407e..9eef64f7c 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@

- 📄 Building Production-Ready AI Agents with Scalable Long-Term Memory → + 📄 Benchmarking Mem0's token-efficient memory algorithm →

## New Memory Algorithm (April 2026) diff --git a/docs/changelog/sdk.mdx b/docs/changelog/sdk.mdx index 930d5157e..d20702f98 100644 --- a/docs/changelog/sdk.mdx +++ b/docs/changelog/sdk.mdx @@ -7,6 +7,23 @@ mode: "wide" + + +**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)) + + + **Major Release** — Python SDK with V3 memory pipeline, ADD-only extraction, and cleaned-up API surface. @@ -893,6 +910,17 @@ See the [OSS v1 to v2 migration guide](https://docs.mem0.ai/migration/oss-v1-to- + + +**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)) + + + **Bug Fixes:** diff --git a/docs/images/banner-sm.png b/docs/images/banner-sm.png index 3e5feeeda..ecc8f3f67 100644 Binary files a/docs/images/banner-sm.png and b/docs/images/banner-sm.png differ diff --git a/mem0-plugin/.claude-plugin/plugin.json b/mem0-plugin/.claude-plugin/plugin.json index e9571b96b..55820ea6f 100644 --- a/mem0-plugin/.claude-plugin/plugin.json +++ b/mem0-plugin/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "mem0", - "version": "0.1.0", + "version": "0.1.1", "description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search to Claude workflows using the Mem0 Platform MCP server.", "author": { "name": "Mem0", diff --git a/mem0-plugin/.codex-plugin/plugin.json b/mem0-plugin/.codex-plugin/plugin.json index d5727b46f..7cd1e89a3 100644 --- a/mem0-plugin/.codex-plugin/plugin.json +++ b/mem0-plugin/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "mem0", - "version": "0.1.0", + "version": "0.1.1", "description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search to Codex workflows using the Mem0 Platform MCP server.", "author": { "name": "Mem0", diff --git a/mem0-plugin/.cursor-plugin/plugin.json b/mem0-plugin/.cursor-plugin/plugin.json index 8ba1249cc..5c0cefd9e 100644 --- a/mem0-plugin/.cursor-plugin/plugin.json +++ b/mem0-plugin/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "mem0", - "version": "0.1.0", + "version": "0.1.1", "description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search using the Mem0 Platform MCP server.", "author": { "name": "Mem0", diff --git a/mem0-plugin/README.md b/mem0-plugin/README.md index 95415e7b8..12845318f 100644 --- a/mem0-plugin/README.md +++ b/mem0-plugin/README.md @@ -74,20 +74,30 @@ This points Codex at the repo's `.agents/plugins/marketplace.json`, which refere > **Don't combine with Option A.** The plugin manifest auto-registers `mem0` as an MCP server via `mem0-plugin/.codex-mcp.json` — adding a manual `[mcp_servers.mem0]` block would duplicate the registration. -**Optional — enable lifecycle hooks.** Codex doesn't auto-wire hooks from plugin manifests; it only reads `~/.codex/hooks.json` (or `/.codex/hooks.json`). Run the bundled installer once to merge Mem0's entries: +**Optional — enable lifecycle hooks.** Codex doesn't auto-wire hooks from plugin manifests; it only reads `~/.codex/hooks.json` (or `/.codex/hooks.json`) ([docs](https://developers.openai.com/codex/hooks)). Run the bundled installer once to merge Mem0's entries: ```bash python3 ~/codex-plugins/mem0-source/mem0-plugin/scripts/install_codex_hooks.py ``` -Then enable the feature flag in `~/.codex/config.toml`: +This merges three entries into `~/.codex/hooks.json` with absolute paths pointing into your clone: + +| Event | What it does | +|-------|--------------| +| `SessionStart` | Loads prior memories as bootstrap context | +| `UserPromptSubmit` | Injects relevant memories into the prompt | +| `Stop` | Reminds the agent to persist learnings at turn end | + +Re-running the installer is idempotent (replaces the Mem0 entries rather than duplicating) and preserves any other hooks you have. To remove: `python3 .../install_codex_hooks.py --uninstall`. If you move or delete the clone directory, re-run the installer from the new location — the hooks file stores absolute paths. + +Codex hooks also require the `codex_hooks` feature flag in `~/.codex/config.toml`: ```toml [features] codex_hooks = true ``` -Restart Codex. This registers `SessionStart` (loads prior memories), `UserPromptSubmit` (injects relevant memories before each prompt), and `Stop` (reminds the agent to persist learnings at turn end). The installer is idempotent. To remove: `python3 .../install_codex_hooks.py --uninstall`. If you move or delete the clone directory, re-run the installer from the new location — the hooks file stores absolute paths into your clone. +The installer prints a reminder if the flag isn't set. Restart Codex after editing the config. **Managing the plugin:** diff --git a/mem0-plugin/hooks/codex-hooks.json b/mem0-plugin/hooks/codex-hooks.json new file mode 100644 index 000000000..0676308a9 --- /dev/null +++ b/mem0-plugin/hooks/codex-hooks.json @@ -0,0 +1,39 @@ +{ + "hooks": { + "SessionStart": [ + { + "matcher": "startup|resume", + "hooks": [ + { + "type": "command", + "command": "${CODEX_PLUGIN_ROOT}/scripts/on_session_start.sh", + "statusMessage": "Loading mem0 context..." + } + ] + } + ], + "UserPromptSubmit": [ + { + "hooks": [ + { + "type": "command", + "command": "${CODEX_PLUGIN_ROOT}/scripts/on_user_prompt.sh", + "statusMessage": "Searching mem0 memories...", + "timeout": 5 + } + ] + } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "${CODEX_PLUGIN_ROOT}/scripts/on_stop_codex.sh", + "timeout": 10 + } + ] + } + ] + } +} diff --git a/mem0-plugin/scripts/install_codex_hooks.py b/mem0-plugin/scripts/install_codex_hooks.py new file mode 100755 index 000000000..f3164287f --- /dev/null +++ b/mem0-plugin/scripts/install_codex_hooks.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +"""Install Mem0 lifecycle hooks into ~/.codex/hooks.json. + +Codex discovers hooks only at ~/.codex/hooks.json or /.codex/hooks.json, +and has no plugin-host mechanism for auto-wiring hooks from an installed +plugin. This installer reads the template at hooks/codex-hooks.json, rewrites +the ${CODEX_PLUGIN_ROOT} placeholder to the absolute install path of this +plugin, then merges the entries into ~/.codex/hooks.json. + +Re-running is idempotent: existing Mem0 entries (identified by the plugin +directory name in the command string) are removed before fresh entries are +added, so upgrades don't leave duplicates. + +Usage: + python3 install_codex_hooks.py # install or update + python3 install_codex_hooks.py --uninstall # remove Mem0 entries + +After installing, Codex requires the hooks feature flag in ~/.codex/config.toml: + + [features] + codex_hooks = true +""" + +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path + +SCRIPT_DIR = Path(__file__).resolve().parent +PLUGIN_ROOT = SCRIPT_DIR.parent + +CODEX_DIR = Path.home() / ".codex" +HOOKS_FILE = CODEX_DIR / "hooks.json" +CONFIG_FILE = CODEX_DIR / "config.toml" + +TEMPLATE_FILE = PLUGIN_ROOT / "hooks" / "codex-hooks.json" + +# Substring we look for when identifying entries this installer owns. +# Matches the plugin directory name, which stays stable across install paths. +OWNER_MARKER = "mem0-plugin" + + +def load_template() -> dict: + raw = TEMPLATE_FILE.read_text() + raw = raw.replace("${CODEX_PLUGIN_ROOT}", str(PLUGIN_ROOT)) + return json.loads(raw) + + +def load_existing() -> dict: + if not HOOKS_FILE.exists(): + return {"hooks": {}} + try: + return json.loads(HOOKS_FILE.read_text()) + except (json.JSONDecodeError, OSError) as e: + print(f"error: failed to read {HOOKS_FILE}: {e}", file=sys.stderr) + sys.exit(1) + + +def is_owned_entry(entry: dict) -> bool: + for hook in entry.get("hooks", []): + if OWNER_MARKER in hook.get("command", ""): + return True + return False + + +def strip_owned_entries(config: dict) -> dict: + hooks = config.get("hooks", {}) or {} + for event in list(hooks.keys()): + hooks[event] = [e for e in hooks[event] if not is_owned_entry(e)] + if not hooks[event]: + del hooks[event] + config["hooks"] = hooks + return config + + +def merge_template(config: dict, template: dict) -> dict: + hooks = config.setdefault("hooks", {}) + for event, entries in template.get("hooks", {}).items(): + hooks.setdefault(event, []).extend(entries) + return config + + +def write_config(config: dict) -> None: + CODEX_DIR.mkdir(parents=True, exist_ok=True) + HOOKS_FILE.write_text(json.dumps(config, indent=2) + "\n") + + +def feature_flag_enabled() -> bool: + if not CONFIG_FILE.exists(): + return False + content = CONFIG_FILE.read_text() + for line in content.splitlines(): + stripped = line.split("#", 1)[0].strip().replace(" ", "") + if stripped == "codex_hooks=true": + return True + return False + + +def print_feature_flag_hint() -> None: + print() + print("Codex hooks feature flag is not enabled.") + print(f"Add this to {CONFIG_FILE}:") + print() + print(" [features]") + print(" codex_hooks = true") + print() + print("Then restart Codex.") + + +def main() -> int: + parser = argparse.ArgumentParser(description="Install or remove Mem0 Codex hooks.") + parser.add_argument( + "--uninstall", + action="store_true", + help="Remove Mem0 entries from ~/.codex/hooks.json and exit.", + ) + args = parser.parse_args() + + config = load_existing() + + if args.uninstall: + config = strip_owned_entries(config) + write_config(config) + print(f"Removed Mem0 hooks from {HOOKS_FILE}") + return 0 + + if not TEMPLATE_FILE.exists(): + print(f"error: template not found at {TEMPLATE_FILE}", file=sys.stderr) + return 1 + + template = load_template() + config = strip_owned_entries(config) + config = merge_template(config, template) + write_config(config) + + print(f"Installed Mem0 hooks into {HOOKS_FILE}") + print(f"Plugin path: {PLUGIN_ROOT}") + print("Events: SessionStart, UserPromptSubmit, Stop") + + if not feature_flag_enabled(): + print_feature_flag_hint() + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/mem0-plugin/scripts/on_stop_codex.sh b/mem0-plugin/scripts/on_stop_codex.sh new file mode 100755 index 000000000..80c16d311 --- /dev/null +++ b/mem0-plugin/scripts/on_stop_codex.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# Hook: Stop (Codex) +# +# Fires when Codex finishes a turn. Reminds the agent to persist any +# important learnings via the mem0 MCP tools before the turn closes. +# +# Input: JSON on stdin with session_id, turn_id, stop_hook_active, +# last_assistant_message, transcript_path, cwd, +# hook_event_name, model +# Output: JSON on stdout (Codex rejects plain text on Stop). +# - stop_hook_active=true -> {"continue": true} (let the turn end) +# - stop_hook_active=false -> {"decision":"block","reason":"..."} +# (continue the turn with the reminder as context) +# +# We must respect stop_hook_active or we'd loop forever: every "block" +# reopens the turn, which triggers Stop again when the agent settles. + +set -uo pipefail + +INPUT=$(cat) +STOP_HOOK_ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false' 2>/dev/null || echo "false") + +if [ "$STOP_HOOK_ACTIVE" = "true" ]; then + printf '{"continue":true}\n' + exit 0 +fi + +REASON=$(cat <<'EOF' +Before finishing, check if there are important learnings from this interaction that should be persisted using the mem0 `add_memory` tool: + +1. Were any significant decisions made? -> Store with metadata `{"type": "decision"}` +2. Were any new patterns or strategies discovered? -> Store with metadata `{"type": "task_learning"}` +3. Did any approach fail? -> Store with metadata `{"type": "anti_pattern"}` +4. Did you learn anything about the user's preferences? -> Store with metadata `{"type": "user_preference"}` +5. Were there environment/setup discoveries? -> Store with metadata `{"type": "environmental"}` + +Memories can be as detailed as needed — include full context, reasoning, code snippets, file paths, and examples. Longer, searchable memories are more valuable than vague one-liners. + +If nothing notable happened in this interaction, it's fine to skip. Only store genuinely useful learnings. +EOF +) + +jq -cn --arg reason "$REASON" '{decision:"block", reason:$reason}' +exit 0 diff --git a/mem0-plugin/skills/mem0/SKILL.md b/mem0-plugin/skills/mem0/SKILL.md index c700e80a1..1ba8b43f9 100644 --- a/mem0-plugin/skills/mem0/SKILL.md +++ b/mem0-plugin/skills/mem0/SKILL.md @@ -1,25 +1,34 @@ --- name: mem0 description: > - Integrate Mem0 Platform into AI applications for persistent memory, personalization, and semantic search. - Use this skill when the user mentions "mem0", "memory layer", "remember user preferences", - "persistent context", "personalization", or needs to add long-term memory to chatbots, agents, - or AI apps. Covers Python and TypeScript SDKs, framework integrations (LangChain, CrewAI, - Vercel AI SDK, OpenAI Agents SDK, Pipecat), and the full Platform API. Use even when the user - doesn't explicitly say "mem0" but describes needing conversation memory, user context retention, - or knowledge retrieval across sessions. + Mem0 Platform SDK for adding persistent memory to AI applications. + TRIGGER when: user mentions "mem0", "MemoryClient", "memory layer", + "remember user preferences", "persistent context", "personalization", + or needs to add long-term memory to chatbots, agents, or AI apps. + Covers Python SDK (mem0ai), TypeScript SDK (mem0ai), and framework integrations + (LangChain, CrewAI, OpenAI Agents SDK, Pipecat, LlamaIndex, AutoGen, LangGraph). + Also covers the open-source self-hosted Memory class. + This is the DEFAULT mem0 skill for ambiguous queries. + DO NOT TRIGGER when: user asks about CLI commands, terminal usage, or shell + scripts (use mem0-cli), or Vercel AI SDK / @mem0/vercel-ai-provider / createMem0 + (use mem0-vercel-ai-sdk). license: Apache-2.0 metadata: author: mem0ai - version: "0.1.0" + version: "0.1.1" category: ai-memory tags: "memory, personalization, ai, python, typescript, vector-search" -compatibility: Requires Python 3.10+ or Node.js 18+, pip install mem0ai or npm install mem0ai, MEM0_API_KEY env var, and internet access to api.mem0.ai +compatibility: Requires Python 3.10+ or Node.js 18+, pip install mem0ai or npm install mem0ai, MEM0_API_KEY env var (Platform), and internet access to api.mem0.ai. Uses Mem0 v3 API. --- # Mem0 Platform Integration -Mem0 is a managed memory layer for AI applications. It stores, retrieves, and manages user memories via API — no infrastructure to deploy. +> **Skill Graph:** This skill is part of the Mem0 skill graph: +> - **mem0** (this skill) -- Platform Client SDK + OSS (Python + TypeScript) +> - **[mem0-cli](https://github.com/mem0ai/mem0/tree/main/skills/mem0-cli)** -- Command-line interface +> - **[mem0-vercel-ai-sdk](https://github.com/mem0ai/mem0/tree/main/skills/mem0-vercel-ai-sdk)** -- Vercel AI SDK provider + +Mem0 is a managed memory layer for AI applications. It stores, retrieves, and manages user memories via API — no infrastructure to deploy. For self-hosted usage, see the OSS section in the client references below. ## Step 1: Install and authenticate @@ -68,14 +77,14 @@ client.add(messages, user_id="alice") ### Search memories ```python -results = client.search("dietary preferences", user_id="alice") +results = client.search("dietary preferences", filters={"user_id": "alice"}) for mem in results.get("results", []): print(mem["memory"]) ``` ### Get all memories ```python -all_memories = client.get_all(user_id="alice") +all_memories = client.get_all(filters={"user_id": "alice"}) ``` ### Update a memory @@ -100,12 +109,12 @@ openai = OpenAI() def chat(user_input: str, user_id: str) -> str: # 1. Retrieve relevant memories - memories = mem0.search(user_input, user_id=user_id) + memories = mem0.search(user_input, filters={"user_id": user_id}) context = "\n".join([m["memory"] for m in memories.get("results", [])]) # 2. Generate response with memory context response = openai.chat.completions.create( - model="gpt-4.1-nano-2025-04-14", + model="gpt-5-mini", messages=[ {"role": "system", "content": f"User context:\n{context}"}, {"role": "user", "content": user_input}, @@ -123,11 +132,20 @@ def chat(user_input: str, user_id: str) -> str: ## Common edge cases -- **Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_id` matches exactly (case-sensitive). +- **Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_id` matches exactly (case-sensitive) and use `filters={"user_id": "..."}` syntax. - **AND filter with user_id + agent_id returns empty:** Entities are stored separately. Use `OR` instead, or query separately. - **Duplicate memories:** Don't mix `infer=True` (default) and `infer=False` for the same data. Stick to one mode. - **Wrong import:** Always use `from mem0 import MemoryClient` (or `AsyncMemoryClient` for async). Do not use `from mem0 import Memory`. -- **Immutable memories:** Cannot be updated or deleted once created. Use `client.history(memory_id)` to track changes over time. +- **v3 defaults:** `top_k=20`, `threshold=0.1`, `rerank=False`. Adjust as needed for your use case. + +## v2 Compatibility + +If you're using SDK v2.x, note these differences: +- **Entity IDs:** Pass `user_id` as top-level kwarg to `search()` instead of inside `filters` +- **Defaults:** `top_k=100`, no threshold, `rerank=True` +- **Graph memory:** Available via `enable_graph=True` + +See the [migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for details. ## Live documentation search @@ -141,7 +159,17 @@ python ${CLAUDE_SKILL_DIR}/scripts/mem0_doc_search.py --index No API key needed — searches docs.mem0.ai directly. -## References +## Client SDK References + +Language-specific deep references (Platform + OSS): + +| Language | File | +|----------|------| +| Python (MemoryClient + AsyncMemoryClient + Memory OSS) | [client/python.md](client/python.md) | +| TypeScript/Node.js (MemoryClient + Memory OSS) | [client/node.md](client/node.md) | +| Python vs TypeScript differences | [client/differences.md](client/differences.md) | + +## Platform References Load these on demand for deeper detail: @@ -152,5 +180,12 @@ Load these on demand for deeper detail: | API reference (endpoints, filters, object schema) | [references/api-reference.md](references/api-reference.md) | | Architecture (pipeline, lifecycle, scoping, performance) | [references/architecture.md](references/architecture.md) | | Platform features (retrieval, graph, categories, MCP, etc.) | [references/features.md](references/features.md) | -| Framework integrations (LangChain, CrewAI, Vercel AI, etc.) | [references/integration-patterns.md](references/integration-patterns.md) | +| Framework integrations (LangChain, CrewAI, OpenAI Agents, etc.) | [references/integration-patterns.md](references/integration-patterns.md) | | Use cases & examples (real-world patterns with code) | [references/use-cases.md](references/use-cases.md) | + +## Related Mem0 Skills + +| Skill | When to use | Link | +|-------|-------------|------| +| mem0-cli | Terminal commands, scripting, CI/CD, agent tool loops | [GitHub](https://github.com/mem0ai/mem0/tree/main/skills/mem0-cli) | +| mem0-vercel-ai-sdk | Vercel AI SDK provider with automatic memory | [GitHub](https://github.com/mem0ai/mem0/tree/main/skills/mem0-vercel-ai-sdk) | diff --git a/mem0-plugin/skills/mem0/client/differences.md b/mem0-plugin/skills/mem0/client/differences.md new file mode 100644 index 000000000..e5e80e250 --- /dev/null +++ b/mem0-plugin/skills/mem0/client/differences.md @@ -0,0 +1,129 @@ +# Python vs TypeScript SDK Differences + +Quick-reference cheatsheet for developers working across both Mem0 SDKs. + +## Constructor + +| Aspect | Python | TypeScript | +|--------|--------|------------| +| Import (Platform) | `from mem0 import MemoryClient` | `import MemoryClient from 'mem0ai'` | +| Import (OSS) | `from mem0 import Memory` | `import { Memory } from 'mem0ai/oss'` | +| Constructor | `MemoryClient(api_key="m0-xxx")` | `new MemoryClient({ apiKey: 'm0-xxx' })` | +| Required param | `api_key` (positional or kwarg) | `apiKey` (in options object) | + +Both read from `MEM0_API_KEY` env var if no key provided. + +## Method Naming + +| Operation | Python | TypeScript | +|-----------|--------|------------| +| Add | `add()` | `add()` | +| Search | `search()` | `search()` | +| Get | `get()` | `get()` | +| Get all | `get_all()` | `getAll()` | +| Update | `update()` | `update()` | +| Delete | `delete()` | `delete()` | +| Delete all | `delete_all()` | `deleteAll()` | +| History | `history()` | `history()` | +| Batch update | `batch_update()` | `batchUpdate()` | +| Batch delete | `batch_delete()` | `batchDelete()` | +| List users | `users()` | `users()` | +| Delete users | `delete_users()` | `deleteUsers()` | +| Get project | `project.get()` | `getProject()` | +| Update project | `project.update()` | `updateProject()` | +| Create webhook | `create_webhook()` | `createWebhook()` | +| Get webhooks | `get_webhooks()` | `getWebhooks()` | +| Update webhook | `update_webhook()` | `updateWebhook()` | +| Delete webhook | `delete_webhook()` | `deleteWebhook()` | +| Create export | `create_memory_export()` | `createMemoryExport()` | +| Get export | `get_memory_export()` | `getMemoryExport()` | +| Feedback | `feedback()` | `feedback()` | + +**Rule:** Python uses `snake_case`, TypeScript uses `camelCase` for method names. + +## Parameter Passing + +```python +# Python: kwargs +client.add(messages, user_id="alice", metadata={"source": "chat"}) +client.search("query", filters={"user_id": "alice"}, top_k=5, rerank=True) +``` + +```typescript +// TypeScript: options object with camelCase for top-level params, snake_case for filter keys +await client.add(messages, { userId: 'alice', metadata: { source: 'chat' } }); +await client.search('query', { filters: { user_id: 'alice' }, topK: 5, rerank: true }); +``` + +**v3:** Python uses `snake_case` everywhere. TypeScript uses `camelCase` for top-level params (`userId`, `topK`) but `snake_case` for filter keys (`user_id`, `agent_id`). + +## Architectural Differences + +| Aspect | Python | TypeScript | +|--------|--------|------------| +| HTTP library | httpx | axios | +| Default timeout | 300s | 60s | +| Sync support | Yes (`MemoryClient`) | No (all async) | +| Async support | Yes (`AsyncMemoryClient`) | All methods are async | +| Project management | `client.project.*` (separate class) | `client.getProject()` / `client.updateProject()` | +| Context manager | `async with AsyncMemoryClient()` | Not supported | + +## Platform Features: Python-only + +These methods exist in Python but not TypeScript: + +| Method | Description | +|--------|-------------| +| `get_summary(filters)` | Get summary of memories | +| `reset()` | Delete ALL data (users + memories) | +| `project.create(name)` | Create a new project | +| `project.delete()` | Delete current project | +| `project.get_members()` | List project members | +| `project.add_member(email, role)` | Add member to project | +| `project.update_member(email, role)` | Change member role | +| `project.remove_member(email)` | Remove member | + +## Platform Features: TypeScript-only + +| Method | Description | +|--------|-------------| +| `deleteUser(data)` | Convenience method for single entity deletion | +| `ping()` | Health check endpoint | + +## OSS Config Naming + +| Python config key | TypeScript config key | +|-------------------|----------------------| +| `vector_store` | `vectorStore` | +| `history_db_path` | `historyDbPath` | +| `custom_instructions` | `customInstructions` | + +## OSS Scope Parameter Naming + +| Python | TypeScript | +|--------|------------| +| `user_id="alice"` | `userId: 'alice'` | +| `agent_id="bot"` | `agentId: 'bot'` | +| `run_id="session"` | `runId: 'session'` | + +## Entity ID Passing (v3) + +| Method | Python | TypeScript | +|--------|--------|------------| +| add() | Top-level: `user_id="alice"` | Top-level: `{ userId: 'alice' }` | +| search() | In filters: `filters={"user_id": "alice"}` | In filters: `{ filters: { user_id: 'alice' } }` | +| get_all() | In filters: `filters={"user_id": "alice"}` | In filters: `{ filters: { user_id: 'alice' } }` | + +## Common Gotcha + +When searching/filtering, both Python and TypeScript use `snake_case` for filter keys. TypeScript only uses `camelCase` for top-level method parameters: + +```python +# Python - snake_case in filters +results = client.search("query", filters={"user_id": "alice"}) +``` + +```typescript +// TypeScript - snake_case in filters, camelCase for top-level params +const results = await client.search('query', { filters: { user_id: 'alice' }, topK: 20 }); +``` diff --git a/mem0-plugin/skills/mem0/client/node.md b/mem0-plugin/skills/mem0/client/node.md new file mode 100644 index 000000000..ca85ba7ba --- /dev/null +++ b/mem0-plugin/skills/mem0/client/node.md @@ -0,0 +1,418 @@ +# Mem0 Node.js / TypeScript SDK Reference + +Complete reference for the `mem0ai` npm package. Covers both the Platform client (managed API) and the Open Source self-hosted variant. + +--- + +## Platform Client + +### Installation + +```bash +npm install mem0ai +export MEM0_API_KEY="m0-your-api-key" +``` + +### MemoryClient + +```typescript +import MemoryClient from 'mem0ai'; + +const client = new MemoryClient({ apiKey: 'm0-xxx' }); +``` + +**Constructor:** `new MemoryClient({ apiKey })`. If `apiKey` is not provided, reads from `MEM0_API_KEY` environment variable. + +- HTTP library: `axios` +- Timeout: 60 seconds +- Base URL: `https://api.mem0.ai` +- All methods are async (return `Promise`) + +--- + +### Memory Methods + +#### add(messages, options?) + +Store new memories from messages. + +```typescript +const messages = [ + { role: 'user', content: "I'm a vegetarian and allergic to nuts." }, + { role: 'assistant', content: "Got it! I'll remember that." }, +]; +await client.add(messages, { userId: 'alice' }); +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `messages` | `Message[]` | Array of `{role, content}` objects | +| `options.userId` | string | User identifier | +| `options.agentId` | string | Agent identifier | +| `options.appId` | string | Application identifier | +| `options.runId` | string | Session identifier | +| `options.metadata` | object | Custom key-value pairs | +| `options.infer` | boolean | If false, store raw text (default: true) | + +**Returns:** `Promise` -- list of events + +#### search(query, options?) + +Search memories by semantic similarity. + +```typescript +const results = await client.search('dietary preferences', { filters: { user_id: 'alice' }, topK: 20 }); +for (const mem of results.results) { + console.log(mem.memory, mem.score); +} +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `query` | string | Natural language search query | +| `options.filters` | object | Filter object with entity IDs (`user_id`, `agent_id`, etc.) and/or `AND`/`OR`/`NOT` conditions | +| `options.topK` | number | Number of results (default: 20) | +| `options.rerank` | boolean | Enable semantic reranking (default: false) | +| `options.threshold` | number | Minimum similarity (default: 0.1) | + +**Returns:** `Promise` -- `{results: [{id, memory, score, ...}]}` + +#### get(memoryId) + +```typescript +const memory = await client.get('ea925981-...'); +``` + +#### getAll(options?) + +Retrieve all memories. Requires at least one entity identifier in filters. + +```typescript +const memories = await client.getAll({ filters: { user_id: 'alice' } }); +// With filters +const filtered = await client.getAll({ + filters: { AND: [{ user_id: 'alice' }, { categories: { contains: 'health' } }] }, +}); +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `options.filters` | object | Filter object with entity IDs (`user_id`, `agent_id`, etc.) and/or `AND`/`OR`/`NOT` conditions | +| `options.page` | number | Page number | +| `options.pageSize` | number | Results per page | + +#### update(memoryId, data) + +```typescript +await client.update('ea925981-...', { text: 'Updated: vegan since 2024' }); +await client.update('ea925981-...', { text: 'Updated', metadata: { verified: true } }); +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `memoryId` | string | Memory ID | +| `data.text` | string | New content | +| `data.metadata` | object | New metadata | +| `data.timestamp` | string | New timestamp | + +#### delete(memoryId) + +```typescript +await client.delete('ea925981-...'); +``` + +#### deleteAll(options?) + +```typescript +await client.deleteAll({ userId: 'alice' }); +``` + +#### history(memoryId) + +```typescript +const history = await client.history('ea925981-...'); +// Returns: [{previousValue, newValue, action, timestamps}] +``` + +--- + +### Batch Methods + +#### batchUpdate(memories) + +```typescript +await client.batchUpdate([ + { memoryId: 'uuid-1', text: 'Updated text' }, + { memoryId: 'uuid-2', text: 'Another update' }, +]); +``` + +#### batchDelete(memories) + +```typescript +await client.batchDelete(['uuid-1', 'uuid-2', 'uuid-3']); +``` + +--- + +### User/Entity Management + +#### users() + +```typescript +const users = await client.users(); +// Returns: {results: [{type: "user", name: "alice"}, ...]} +``` + +#### deleteUser(data) / deleteUsers(data) + +```typescript +await client.deleteUser({ userId: 'alice' }); // Single entity +await client.deleteUsers({ agentId: 'bot-1' }); // Flexible +``` + +--- + +### Project Management + +```typescript +// Get project config +const config = await client.getProject({ fields: ['customCategories'] }); + +// Update project settings +await client.updateProject({ + customInstructions: 'Extract dietary preferences and health info', + customCategories: [{ health: 'Medical and dietary info' }], +}); +``` + +--- + +### Webhooks + +```typescript +// List +const webhooks = await client.getWebhooks({ projectId: 'proj_123' }); + +// Create +const webhook = await client.createWebhook({ + url: 'https://your-app.com/webhook', + name: 'Memory Logger', + projectId: 'proj_123', + eventTypes: ['memory_add', 'memory_update'], +}); + +// Update +await client.updateWebhook({ + webhookId: 'wh_123', + name: 'Updated Logger', + url: 'https://new-url.com', +}); + +// Delete +await client.deleteWebhook({ webhookId: 'wh_123' }); +``` + +--- + +### Feedback + +```typescript +await client.feedback({ + memoryId: 'mem-123', + feedback: 'POSITIVE', + feedbackReason: 'Accurately captured preference', +}); +``` + +--- + +### Export + +```typescript +const exportReq = await client.createMemoryExport({ + schema: JSON.stringify({ type: 'object', properties: { name: { type: 'string' } } }), + filters: { user_id: 'alice' }, +}); + +const result = await client.getMemoryExport({ memoryExportId: exportReq.id }); +``` + +--- + +### TypeScript Types + +Key interfaces from `mem0.types.ts`: + +```typescript +interface Message { role: string; content: string; } +interface Memory { id: string; memory: string; userId: string; categories: string[]; score?: number; /* ... */ } +interface MemoryOptions { userId?: string; agentId?: string; appId?: string; runId?: string; metadata?: object; /* ... */ } +interface SearchOptions { filters?: object; topK?: number; rerank?: boolean; threshold?: number; /* ... */ } +interface MemoryHistory { id: string; memoryId: string; previousValue: string; newValue: string; action: string; /* ... */ } +interface FeedbackPayload { memoryId: string; feedback: string; feedbackReason?: string; } +interface WebhookCreatePayload { url: string; name: string; projectId: string; eventTypes: string[]; } +``` + +--- + +## Open Source / Self-Hosted + +### Installation + +```bash +npm install mem0ai +``` + +### Memory Class + +```typescript +import { Memory } from 'mem0ai/oss'; + +const m = new Memory(); // Uses default config +``` + +**Import:** `from 'mem0ai/oss'` (NOT the default export -- that is `MemoryClient` for Platform) + +### Configuration + +```typescript +const config = { + llm: { + provider: 'openai', // openai, groq, anthropic, google, ollama, lmstudio, mistral, azure + config: { + model: 'gpt-5-mini', + apiKey: 'sk-xxx', + }, + }, + embedder: { + provider: 'openai', // openai, ollama, lmstudio, google, azure, langchain, anthropic + config: { + model: 'text-embedding-3-small', + apiKey: 'sk-xxx', + }, + }, + vectorStore: { + provider: 'qdrant', // memory, qdrant, redis, supabase, langchain, azure_ai_search, pgvector + config: { + collectionName: 'my_memories', + host: 'localhost', + port: 6333, + }, + }, + historyDbPath: 'history.db', + customInstructions: '...', + disableHistory: false, +}; + +const m = new Memory(config); +// Or from dict with validation: +const m2 = Memory.fromConfig(config); +``` + +### Methods + +All methods are async (return `Promise`): + +#### add(messages, config) + +```typescript +await m.add('I prefer dark mode', { userId: 'alice' }); +await m.add([ + { role: 'user', content: 'I like hiking' }, + { role: 'assistant', content: 'Great outdoor activity!' }, +], { userId: 'alice' }); +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `messages` | `string \| Message[]` | Content to store | +| `config.userId` | string | User identifier (at least one scope required) | +| `config.agentId` | string | Agent identifier | +| `config.runId` | string | Session identifier | +| `config.metadata` | object | Custom key-value pairs | +| `config.filters` | object | Additional filters | +| `config.infer` | boolean | LLM inference (default: true) | + +**Returns:** `Promise<{results: [...], relations?: [...]}>` + +#### search(query, config) + +```typescript +const results = await m.search('dietary preferences', { filters: { user_id: 'alice' }, topK: 5 }); +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `query` | string | Search query | +| `config.filters` | object | Filter object with entity IDs (`user_id`, `agent_id`, `run_id`, etc.) | +| `config.topK` | number | Max results (default: 20) | + +#### get(memoryId) / getAll(config) / update(memoryId, data) / delete(memoryId) / deleteAll(config) / history(memoryId) + +Same interface patterns. Note: OSS `update` takes a string for data, not an object. + +```typescript +await m.update('mem-id', 'new content'); +``` + +#### reset() + +Clear the entire vector store and history. + +```typescript +await m.reset(); +``` + +--- + +## Key Differences: Platform vs OSS + +| Aspect | Platform (`MemoryClient`) | OSS (`Memory`) | +|--------|--------------------------|----------------| +| **Import** | `import MemoryClient from 'mem0ai'` | `import { Memory } from 'mem0ai/oss'` | +| **Auth** | API key required (`MEM0_API_KEY`) | No API key -- config-based | +| **Execution** | API calls to `api.mem0.ai` | Local execution | +| **Infrastructure** | Fully managed | Self-managed vector DB, embedder, LLM | +| **Param style** | Top-level: `camelCase` (`userId`, `topK`), filter keys: `snake_case` (`user_id`) | Top-level: `camelCase` (`userId`, `topK`), filter keys: `snake_case` (`user_id`) | +| **Batch ops** | `batchUpdate`, `batchDelete` | Not available | +| **Webhooks** | Full CRUD | Not available | +| **Export** | `createMemoryExport` | Not available | +| **Feedback** | `feedback()` | Not available | +| **Project mgmt** | `getProject`, `updateProject` | Not available | +| **User listing** | `users()`, `deleteUser()` | Not available | +| **History** | Platform-managed | SQLite (configurable) | + +--- + +## v2 Compatibility + +If you're using SDK v2.x: + +**Naming Changes:** +- Top-level params now use camelCase: `topK`, `rerank` (not `top_k`) +- Filter keys use snake_case: `user_id`, `agent_id` +- OSS: `limit` renamed to `topK` + +**API Changes:** +```typescript +// v2 - top-level entity IDs, snake_case +await client.search("query", { user_id: "alice", top_k: 20 }); + +// v3 - filters object with snake_case keys, camelCase top-level params +await client.search("query", { filters: { user_id: "alice" }, topK: 20 }); +``` + +**Default Changes:** +| Param | v2 | v3 | +|-------|----|----| +| `topK` | 100 | 20 | +| `threshold` | none | 0.1 | +| `rerank` | true | false | + +**Removed:** +- `OutputFormat` and `API_VERSION` enums +- `organizationId`, `projectId` from constructor +- `enableGraph`, `asyncMode`, `outputFormat`, `immutable`, `expirationDate`, `filterMemories`, `batchSize`, `forceAddOnly`, `includes`, `excludes`, `keywordSearch` + +See the [v2 to v3 migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for details. diff --git a/mem0-plugin/skills/mem0/client/python.md b/mem0-plugin/skills/mem0/client/python.md new file mode 100644 index 000000000..0cf35a550 --- /dev/null +++ b/mem0-plugin/skills/mem0/client/python.md @@ -0,0 +1,487 @@ +# Mem0 Python SDK Reference + +Complete reference for the `mem0ai` Python package. Covers both the Platform client (managed API) and the Open Source self-hosted variant. + +--- + +## Platform Client + +### Installation + +```bash +pip install mem0ai +export MEM0_API_KEY="m0-your-api-key" +``` + +### MemoryClient (Synchronous) + +```python +from mem0 import MemoryClient + +client = MemoryClient(api_key="m0-xxx") +``` + +**Constructor:** `MemoryClient(api_key=None)`. If `api_key` is not provided, reads from `MEM0_API_KEY` environment variable. Raises `ValueError` if no key found. + +- HTTP library: `httpx` +- Timeout: 300 seconds +- Base URL: `https://api.mem0.ai` + +### AsyncMemoryClient (Asynchronous) + +```python +from mem0 import AsyncMemoryClient + +client = AsyncMemoryClient(api_key="m0-xxx") + +# Or use as context manager +async with AsyncMemoryClient(api_key="m0-xxx") as client: + results = await client.search("query", filters={"user_id": "alice"}) +``` + +Same methods as `MemoryClient`, all `async`/`await`. Supports async context manager. + +--- + +### Memory Methods + +#### add(messages, **kwargs) + +Store new memories from messages. + +```python +messages = [ + {"role": "user", "content": "I'm a vegetarian and allergic to nuts."}, + {"role": "assistant", "content": "Got it! I'll remember that."} +] +client.add(messages, user_id="alice") +``` + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `messages` | str \| dict \| list[dict] | required | Message content. Strings auto-convert to user messages | +| `user_id` | str | None | User identifier | +| `agent_id` | str | None | Agent identifier | +| `app_id` | str | None | Application identifier | +| `run_id` | str | None | Session/run identifier | +| `metadata` | dict | None | Custom key-value pairs | +| `infer` | bool | True | If False, store raw text without LLM inference | +| `custom_categories` | list | None | Override project categories | +| `custom_instructions` | str | None | Override extraction instructions | +| `timestamp` | int \| float \| str | None | Custom timestamp (Unix epoch or ISO 8601) | + +**Returns:** `dict` -- list of events: `[{"id": "...", "event": "ADD", "data": {"memory": "..."}}]` + +#### search(query, **kwargs) + +Search memories by semantic similarity. + +```python +results = client.search("dietary preferences", filters={"user_id": "alice"}) +for mem in results.get("results", []): + print(mem["memory"], mem["score"]) +``` + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `query` | str | required | Natural language search query | +| `filters` | dict | None | Filter object with entity IDs and/or `AND`/`OR`/`NOT` conditions (e.g., `{"user_id": "alice"}`) | +| `top_k` | int | 10 | Number of results | +| `rerank` | bool | False | Enable deep semantic reranking (+150-200ms) | +| `threshold` | float | 0.1 | Minimum similarity score | +| `fields` | list | None | Specific fields to return | +| `categories` | list | None | Filter by category | + +**Returns:** `dict` -- `{"results": [{id, memory, user_id, categories, score, created_at, ...}]}` + +#### get(memory_id) + +Retrieve a single memory by ID. + +```python +memory = client.get(memory_id="ea925981-...") +``` + +**Returns:** `dict` -- full memory object + +#### get_all(**kwargs) + +Retrieve all memories with optional filtering. Requires at least one entity identifier. + +```python +memories = client.get_all(filters={"user_id": "alice"}) +# With compound filters +memories = client.get_all(filters={"AND": [{"user_id": "alice"}, {"categories": {"contains": "health"}}]}) +``` + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `filters` | dict | None | Filter object with entity IDs and/or `AND`/`OR`/`NOT` conditions | +| `top_k` | int | None | Limit results | +| `page` | int | None | Page number | +| `page_size` | int | None | Results per page | + +**Returns:** `dict` -- `{"results": [...]}` + +#### update(memory_id, text=None, metadata=None, timestamp=None) + +Update a memory's content, metadata, or timestamp. At least one parameter required. + +```python +client.update("ea925981-...", text="Updated: vegan since 2024") +client.update("ea925981-...", metadata={"verified": True}) +``` + +**Returns:** `dict` -- updated memory + +#### delete(memory_id) + +Permanently delete a single memory. + +```python +client.delete("ea925981-...") +``` + +#### delete_all(**kwargs) + +Delete all memories matching filters. Irreversible. + +```python +client.delete_all(user_id="alice") +``` + +#### history(memory_id) + +Get the change history of a memory. + +```python +history = client.history("ea925981-...") +# Returns: [{previous_value, new_value, action, timestamps}] +``` + +--- + +### Batch Methods + +#### batch_update(memories) + +Update up to 1000 memories in a single request. + +```python +client.batch_update([ + {"memory_id": "uuid-1", "text": "Updated text"}, + {"memory_id": "uuid-2", "text": "Another update", "metadata": {"verified": True}}, +]) +``` + +#### batch_delete(memories) + +Delete up to 1000 memories in a single request. + +```python +client.batch_delete([ + {"memory_id": "uuid-1"}, + {"memory_id": "uuid-2"}, +]) +``` + +--- + +### User/Entity Management + +#### users() + +List all users, agents, and sessions that have memories. + +```python +users = client.users() +# Returns: {"results": [{"type": "user", "name": "alice"}, ...]} +``` + +#### delete_users(user_id=None, agent_id=None, app_id=None, run_id=None) + +Delete a specific entity and all its memories. + +```python +client.delete_users(user_id="alice") +``` + +#### reset() + +Delete ALL users, agents, sessions, and memories. Complete data reset. + +```python +client.reset() +``` + +--- + +### Export & Summary + +#### create_memory_export(schema, **kwargs) + +Create a structured export of memories. + +```python +import json + +schema = json.dumps({ + "type": "object", + "properties": { + "name": {"type": "string"}, + "preferences": {"type": "array", "items": {"type": "string"}}, + } +}) +export = client.create_memory_export(schema=schema, user_id="alice") +``` + +#### get_memory_export(**kwargs) + +Retrieve a previously created export. + +```python +result = client.get_memory_export(memory_export_id=export["id"]) +``` + +#### get_summary(filters=None) + +Get a summary of memories. + +```python +summary = client.get_summary(filters={"user_id": "alice"}) +``` + +--- + +### Feedback + +#### feedback(memory_id, feedback=None, feedback_reason=None) + +Provide quality feedback on a memory. + +```python +client.feedback( + memory_id="mem-123", + feedback="POSITIVE", # POSITIVE | NEGATIVE | VERY_NEGATIVE | None (clear) + feedback_reason="Accurately captured preference" +) +``` + +--- + +### Webhooks + +```python +# List +webhooks = client.get_webhooks(project_id="proj_123") + +# Create +webhook = client.create_webhook( + url="https://your-app.com/webhook", + name="Memory Logger", + project_id="proj_123", + event_types=["memory_add", "memory_update"] +) + +# Update +client.update_webhook(webhook_id=123, name="Updated", url="https://new-url.com") + +# Delete +client.delete_webhook(webhook_id=123) +``` + +--- + +### Project Management + +Access via `client.project.*`: + +```python +# Get project config +config = client.project.get(fields=["custom_categories", "custom_instructions"]) + +# Update project settings +client.project.update( + custom_instructions="Extract dietary preferences and health info", + custom_categories=[{"health": "Medical and dietary info"}], + multilingual=True, +) + +# Create/delete project +client.project.create(name="My Project", description="...") +client.project.delete() + +# Member management +members = client.project.get_members() +client.project.add_member(email="user@example.com", role="READER") # READER or OWNER +client.project.update_member(email="user@example.com", role="OWNER") +client.project.remove_member(email="user@example.com") +``` + +--- + +## Open Source / Self-Hosted + +### Installation + +```bash +pip install mem0ai +``` + +### Memory Class + +```python +from mem0 import Memory + +m = Memory() # Uses default config (OpenAI embedder + in-memory vector store) +``` + +**Import:** `from mem0 import Memory` (NOT `MemoryClient` -- that is the Platform client) + +### Configuration + +```python +config = { + "llm": { + "provider": "openai", # openai, groq, azure, ollama, lmstudio, google, anthropic, mistral + "config": { + "model": "gpt-5-mini", + "api_key": "sk-xxx", + } + }, + "embedder": { + "provider": "openai", # openai, ollama, azure, lmstudio, google, huggingface + "config": { + "model": "text-embedding-3-small", + "api_key": "sk-xxx", + } + }, + "vector_store": { + "provider": "qdrant", # faiss, qdrant, pgvector, redis, supabase, azure_ai_search, memory + "config": { + "collection_name": "my_memories", + "host": "localhost", + "port": 6333, + } + }, + "history_db_path": "history.db", # SQLite path for change history + "custom_instructions": "...", # Custom LLM prompt for extraction +} + +m = Memory.from_config(config) +``` + +### Context Manager + +```python +with Memory(config) as m: + m.add("I prefer dark mode", user_id="alice") + results = m.search("preferences", filters={"user_id": "alice"}) +# SQLite connections released automatically +``` + +### Methods + +All methods mirror the Platform client but run locally: + +#### add(messages, *, user_id, agent_id, run_id, metadata, infer=True) + +```python +m.add("I'm a vegetarian", user_id="alice") +m.add([ + {"role": "user", "content": "I like hiking"}, + {"role": "assistant", "content": "Great outdoor activity!"} +], user_id="alice") +``` + +At least one of `user_id`, `agent_id`, `run_id` required. + +**Returns:** `{"results": [...], "relations": [...]}` + +#### search(query, *, filters=None, top_k=20, threshold=0.1, rerank=False) + +```python +results = m.search("dietary preferences", filters={"user_id": "alice"}, top_k=5) +``` + +Entity IDs (`user_id`, `agent_id`, `run_id`) must be passed inside the `filters` dict. + +Supports filter operators: `eq`, `ne`, `in`, `nin`, `gt`, `gte`, `lt`, `lte`, `contains`, `not_contains`. + +#### get(memory_id) / get_all(**kwargs) / update(memory_id, data, metadata=None) / delete(memory_id) / delete_all(**kwargs) / history(memory_id) + +Same interface as Platform client. + +#### reset() + +Clear the entire vector store collection and history database. Recreates the vector store. + +```python +m.reset() +``` + +#### close() + +Release SQLite connections. Called automatically when using context manager. + +### AsyncMemory + +```python +from mem0 import AsyncMemory + +m = AsyncMemory(config) +await m.add("text", user_id="alice") +results = await m.search("query", filters={"user_id": "alice"}) +``` + +--- + +## Key Differences: Platform vs OSS + +| Aspect | Platform (`MemoryClient`) | OSS (`Memory`) | +|--------|--------------------------|----------------| +| **Import** | `from mem0 import MemoryClient` | `from mem0 import Memory` | +| **Auth** | API key required (`MEM0_API_KEY`) | No API key -- config-based | +| **Execution** | API calls to `api.mem0.ai` | Local execution | +| **Infrastructure** | Fully managed | Self-managed vector DB, embedder, LLM | +| **Entity filtering** | `filters={"user_id": "..."}` | `filters={"user_id": "..."}` | +| **Batch ops** | `batch_update`, `batch_delete` | Not available | +| **Webhooks** | Full CRUD | Not available | +| **Export** | `create_memory_export`, `get_memory_export` | Not available | +| **Feedback** | `feedback()` | Not available | +| **Project mgmt** | `client.project.*` | Not available | +| **User listing** | `users()`, `delete_users()` | Not available | +| **Custom prompts** | Via project settings | Direct config (`custom_instructions`) | +| **History** | Platform-managed | SQLite (configurable) | +| **Async** | `AsyncMemoryClient` | `AsyncMemory` | + +--- + +## v2 Compatibility + +If you're using SDK v2.x or the v2 API: + +**API Changes:** +- **Entity IDs in search/get_all:** Pass `user_id`, `agent_id` as top-level kwargs instead of inside `filters` + ```python + # v2 + results = client.search("query", user_id="alice") + # v3 + results = client.search("query", filters={"user_id": "alice"}) + ``` +- **add() returns:** v2 returns ADD, UPDATE, DELETE events; v3 returns ADD only + +**Default Changes:** +| Param | v2 | v3 | +|-------|----|----| +| `top_k` | 100 | 20 | +| `threshold` | None | 0.1 | +| `rerank` | True | False | + +**Removed Parameters:** +- Constructor: `org_id`, `project_id` +- add(): `async_mode`, `output_format`, `enable_graph`, `immutable`, `expiration_date`, `filter_memories`, `batch_size`, `force_add_only`, `includes`, `excludes`, `keyword_search` +- search()/get_all(): `enable_graph` +- Config: `enable_graph`, `graph_store`, `custom_fact_extraction_prompt` (renamed to `custom_instructions`) + +See the [v2 to v3 migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for full details. diff --git a/mem0-plugin/skills/mem0/references/api-reference.md b/mem0-plugin/skills/mem0/references/api-reference.md index e9fd20f24..62ec4bea7 100644 --- a/mem0-plugin/skills/mem0/references/api-reference.md +++ b/mem0-plugin/skills/mem0/references/api-reference.md @@ -8,13 +8,15 @@ All endpoints require: `Authorization: Token ` | Operation | Method | URL | |-----------|--------|-----| -| Add Memories | `POST` | `/v1/memories/` | -| Search Memories | `POST` | `/v2/memories/search/` | -| Get All Memories | `POST` | `/v2/memories/` | +| Add Memories | `POST` | `/v3/memories/add/` | +| Search Memories | `POST` | `/v3/memories/search/` | +| Get All Memories | `POST` | `/v3/memories/` | | Get Single Memory | `GET` | `/v1/memories/{memory_id}/` | | Update Memory | `PUT` | `/v1/memories/{memory_id}/` | | Delete Memory | `DELETE` | `/v1/memories/{memory_id}/` | +Note: v1/v2 endpoints still work (backward compatible). + ## Memory Object Structure | Field | Type | Description | @@ -27,8 +29,6 @@ All endpoints require: `Authorization: Token ` | `run_id` | string (nullable) | Run/session identifier | | `metadata` | object | Custom key-value pairs | | `categories` | array of strings | Auto-assigned category tags | -| `immutable` | boolean | If true, prevents modification | -| `expiration_date` | datetime (nullable) | Auto-expiry date | | `hash` | string | Content hash | | `created_at` | datetime | Creation timestamp | | `updated_at` | datetime | Last modification timestamp | @@ -50,10 +50,9 @@ Memories can be scoped to different levels: ## Processing Model -- Memories are processed **asynchronously by default** (`async_mode=true`) -- Add responses return queued events (`ADD`, `UPDATE`, `DELETE`) for tracking -- Set `async_mode=false` for synchronous processing when needed -- Graph metadata is processed asynchronously -- use `get_all()` for complete graph data +- Memories are processed **asynchronously** (v3 default) +- Add responses return queued `ADD` events only (v3 is ADD-only, no UPDATE/DELETE) +- Poll status via `GET /v1/event/{event_id}/` ## Filter System @@ -106,19 +105,17 @@ Root must be `AND`, `OR`, or `NOT`. Simple shorthand `{"user_id": "alice"}` also ## Response Formats -### Add Response +### Add Response (v3) ```json -[ - { - "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" +} ``` -Event types: `ADD`, `UPDATE`, `DELETE`. A single add can trigger multiple events. +v3 is ADD-only. No UPDATE or DELETE events. ### Search Response @@ -137,4 +134,17 @@ Event types: `ADD`, `UPDATE`, `DELETE`. A single add can trigger multiple events } ``` -With `enable_graph=true`, includes additional `relations` array with entity relationships. +In v3, `score` is a combined multi-signal relevance score. + +### Get All Response (v3) + +```json +{ + "count": 123, + "next": "https://api.mem0.ai/v3/memories/?page=2&page_size=50", + "previous": null, + "results": [...] +} +``` + +v3 returns paginated envelope. Use `page` and `page_size` query params. diff --git a/mem0-plugin/skills/mem0/references/architecture.md b/mem0-plugin/skills/mem0/references/architecture.md index f0c5c1bc8..4a04c820b 100644 --- a/mem0-plugin/skills/mem0/references/architecture.md +++ b/mem0-plugin/skills/mem0/references/architecture.md @@ -25,9 +25,9 @@ User Input → Retrieve relevant memories → Enrich LLM prompt → Generate res Mem0 handles the complexity of extraction, deduplication, conflict resolution, and semantic retrieval so your application only needs to call `search()` and `add()`. -**Dual storage architecture:** +**Storage architecture:** - **Vector store**: Embeddings for semantic similarity search -- **Graph store** (optional): Entity nodes and relationship edges for structured knowledge +- **Entity store**: Automatic entity linking for relationship-aware retrieval --- @@ -40,41 +40,32 @@ Messages In │ ▼ ┌─────────────────────┐ -│ 1. EXTRACTION │ LLM analyzes messages, extracts key facts +│ 1. EXTRACTION │ Single LLM call extracts all distinct new facts │ (infer=True) │ If infer=False, stores raw text as-is └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ -│ 2. CONFLICT │ Checks existing memories for duplicates -│ RESOLUTION │ Latest truth wins (newer overrides older) -│ │ Only runs when infer=True +│ 2. DEDUPLICATION │ Hash-based dedup (MD5 prevents exact duplicates) +│ │ No UPDATE/DELETE - v3 is ADD-only └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ -│ 3. STORAGE │ Generates embeddings → vector store -│ │ Optional: entity extraction → graph store -│ │ Indexes metadata, categories, timestamps +│ 3. STORAGE │ Batch embed → vector store +│ │ Entity extraction → entity store └─────────┬───────────┘ │ ▼ Memory Object - (id, memory, categories, structured_attributes) ``` -### Processing modes +### Processing (v3) -**Async (default, `async_mode=True`):** -- API returns immediately: `{"status": "PENDING", "event_id": "..."}` -- Processing happens in background +v3 processes memories asynchronously by default: +- API returns immediately: `{"status": "PENDING", "event_id": "evt-..."}` +- Poll status via `GET /v1/event/{event_id}/` - Use webhooks for completion notifications -- Best for: high-throughput, non-blocking workflows - -**Sync (`async_mode=False`):** -- API waits for full processing -- Returns complete memory object with `id`, `event`, `memory` -- Best for: real-time access immediately after add ### Extraction modes @@ -93,7 +84,7 @@ Messages In --- -## Retrieval Pipeline +## Retrieval Pipeline (v3) ### What happens when you call `client.search()` @@ -102,45 +93,37 @@ Query In │ ▼ ┌─────────────────────┐ -│ 1. QUERY EMBEDDING │ Convert query to vector representation +│ 1. PREPROCESSING │ Lemmatize keywords, extract entities └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ -│ 2. VECTOR SEARCH │ Cosine similarity across stored embeddings -│ │ Scoped by filters (user_id, agent_id, etc.) -└─────────┬───────────┘ - │ - ▼ (optional enhancements) -┌─────────────────────┐ -│ 3a. KEYWORD SEARCH │ Expands results with specific terms (+10ms) -│ 3b. RERANKING │ Deep semantic reordering (+150-200ms) -│ 3c. FILTER MEMORIES │ Precision filtering, removes low-relevance (+200-300ms) -└─────────┬───────────┘ - │ - ▼ (if enable_graph=True) -┌─────────────────────┐ -│ 4. GRAPH LOOKUP │ Finds entity relationships -│ │ Appends relations WITHOUT reranking vector results +│ 2. PARALLEL SCORING │ Semantic search (vector similarity) +│ │ BM25 keyword search (term matching) +│ │ Entity matching (entity graph boost) └─────────┬───────────┘ │ ▼ - Results + Relations +┌─────────────────────┐ +│ 3. SCORE FUSION │ Combine signals into single score +│ │ Optional: rerank=True for deep reordering +└─────────┬───────────┘ + │ + ▼ + Results (combined score per memory) ``` -### Retrieval enhancement combinations +### v3 Search Defaults -| Configuration | Latency | Best for | -|--------------|---------|----------| -| Base search only | ~100ms | Simple lookups | -| `keyword_search=True` | ~110ms | Entity-heavy queries, broad coverage | -| `rerank=True` | ~250-300ms | User-facing results, top-N precision | -| `keyword_search=True` + `rerank=True` | ~310ms | Balanced (recommended for most apps) | -| `rerank=True` + `filter_memories=True` | ~400-500ms | Safety-critical, production systems | +| Parameter | Default | Notes | +|-----------|---------|-------| +| `top_k` | 20 | Was 100 in v2 | +| `threshold` | 0.1 | Was None in v2 | +| `rerank` | False | Was True in v2 | ### Implicit null scoping -When you search with `user_id="alice"` only, Mem0 returns memories where `agent_id`, `app_id`, and `run_id` are all null. This prevents cross-scope leakage by default. +When you search with `filters={"user_id": "alice"}` only, Mem0 returns memories where `agent_id`, `app_id`, and `run_id` are all null. This prevents cross-scope leakage by default. To include memories with non-null fields, use explicit filters: ```python @@ -150,53 +133,23 @@ filters={"OR": [{"user_id": "alice"}]} --- -## Memory Lifecycle +## Memory Lifecycle (v3) -``` -CREATE ──→ ACTIVE ──→ UPDATE ──→ ACTIVE - │ │ │ - │ ▼ ▼ - │ EXPIRED EXPIRED - │ (still stored, (still stored, - │ not retrieved) not retrieved) - │ │ │ - ▼ ▼ ▼ -DELETE DELETE DELETE -(permanent) -``` +v3 uses ADD-only extraction. Memories accumulate over time rather than being consolidated. ### Creation -- Triggered by `client.add(messages, user_id="...")` -- Messages processed through extraction → conflict resolution → storage -- Gets unique UUID, `created_at` timestamp -- Optional: custom `timestamp`, `expiration_date`, `metadata`, `immutable` +- `client.add(messages, user_id="...")` +- Single-pass extraction → deduplication → storage +- Returns `{"event_id": "...", "status": "PENDING"}` ### Updates -- `client.update(memory_id, text="...")` replaces text and reindexes -- `client.batch_update([...])` for up to 1000 memories at once -- Immutable memories (`immutable=True`) cannot be updated — must delete and re-add - -### Deduplication -- Automatic during `add()` with `infer=True` -- Conflict resolution merges duplicate facts -- Latest truth wins when contradictions detected -- Prevents memory bloat from repeated information - -### Expiration -- Optional `expiration_date` parameter (ISO 8601 or `YYYY-MM-DD`) -- After expiration: memory NOT returned in searches but remains in storage -- Useful for time-sensitive info (events, temporary preferences, session state) +- `client.update(memory_id, text="...")` replaces text +- Batch: `client.batch_update([...])` ### Deletion -- Single: `client.delete(memory_id)` — permanent, no recovery -- Batch: `client.batch_delete([memory_ids])` — up to 1000 -- Bulk: `client.delete_all(user_id="alice")` — all memories for entity -- `delete_all()` without filters raises error to prevent accidental data loss - -### History tracking -- `client.history(memory_id)` returns version timeline -- Shows all changes: `{previous_value, new_value, action, timestamps}` -- Useful for audit trails and debugging +- Single: `client.delete(memory_id)` +- Batch: `client.batch_delete([...])` +- Bulk: `client.delete_all(filters={"user_id": "alice"})` --- @@ -214,8 +167,6 @@ DELETE DELETE DELETE "categories": ["health", "preferences"], "created_at": "2025-03-12T12:34:56Z", "updated_at": "2025-03-12T12:34:56Z", - "expiration_date": null, - "immutable": false, "structured_attributes": { "day": 12, "month": 3, "year": 2025, "hour": 12, "minute": 34, @@ -239,8 +190,6 @@ DELETE DELETE DELETE | `categories` | array | Auto-assigned or custom category tags | | `created_at` | datetime | Creation timestamp | | `updated_at` | datetime | Last modification timestamp | -| `expiration_date` | datetime | Auto-expiry date (stops retrieval, data persists) | -| `immutable` | boolean | If true, prevents modification | | `structured_attributes` | object | Temporal breakdown for time-based queries | | `score` | float | Semantic similarity (search results only, 0-1) | @@ -322,7 +271,7 @@ Mem0 supports three layers of memory, from shortest to longest lived: ```python def chat(user_input: str, user_id: str, session_id: str) -> str: # 1. Retrieve user memories (long-term preferences) - user_mems = mem0.search(user_input, user_id=user_id) + user_mems = mem0.search(user_input, filters={"user_id": user_id}) # 2. Retrieve session memories (current task context) session_mems = mem0.search(user_input, filters={ @@ -350,18 +299,13 @@ def chat(user_input: str, user_id: str, session_id: str) -> str: | Operation | Typical Latency | |-----------|----------------| -| Base vector search | ~100ms | -| + keyword_search | +10ms | +| Hybrid search (v3 default) | ~100-150ms | | + reranking | +150-200ms | -| + filter_memories | +200-300ms | -| Add (async, default) | < 50ms response, background processing | -| Add (sync) | 500ms-2s depending on extraction complexity | -| Graph operations | Slight overhead for large stores | +| Add (async) | < 50ms response | ### Processing -- **Async mode (default):** Returns immediately, processes in background -- **Sync mode:** Waits for full extraction + storage pipeline +- **Async (default):** Returns immediately, processes in background - **Batch operations:** Up to 1000 memories per batch_update/batch_delete - **Webhooks:** Real-time notifications when async processing completes diff --git a/mem0-plugin/skills/mem0/references/features.md b/mem0-plugin/skills/mem0/references/features.md index fa2130f47..b5d5e73ea 100644 --- a/mem0-plugin/skills/mem0/references/features.md +++ b/mem0-plugin/skills/mem0/references/features.md @@ -5,7 +5,7 @@ Additional platform capabilities beyond core CRUD operations. ## Table of Contents - [Advanced Retrieval](#advanced-retrieval) -- [Graph Memory](#graph-memory) +- [Entity Linking](#entity-linking) - [Custom Categories](#custom-categories) - [Custom Instructions](#custom-instructions) - [Criteria Retrieval](#criteria-retrieval) @@ -18,124 +18,58 @@ Additional platform capabilities beyond core CRUD operations. ## Advanced Retrieval -Three enhancement options for tuning search precision, recall, and latency. +### Hybrid Search (v3 Default) -### Keyword Search (`keyword_search=True`) +v3 uses multi-signal hybrid search combining: +- **Semantic search** (vector similarity) +- **BM25 keyword search** (normalized term matching) +- **Entity matching** (entity graph boost) -Expands results to include memories with specific terms, names, and technical keywords. - -- Latency: +10ms -- Recall: Significantly increased -- Best for: entity-heavy queries, comprehensive coverage +This is automatic — no configuration needed. ### Reranking (`rerank=True`) Deep semantic reordering of results — most relevant first. - Latency: +150-200ms -- Accuracy: Significantly improved +- Default: `False` (was `True` in v2) - Best for: user-facing results, top-N precision -### Filter Memories (`filter_memories=True`) - -Precision filtering — removes low-relevance results entirely. - -- Latency: +200-300ms -- Precision: Maximized -- Best for: safety-critical applications, production systems - -### Recommended Combinations - **Python:** ```python -# Fast & broad -results = client.search(query, keyword_search=True, user_id="user123") - -# Balanced (recommended for most apps) -results = client.search(query, keyword_search=True, rerank=True, user_id="user123") - -# High precision (critical apps) -results = client.search(query, rerank=True, filter_memories=True, user_id="user123") +results = client.search(query, filters={"user_id": "user123"}, rerank=True) ``` **TypeScript:** ```typescript const results = await client.search(query, { - user_id: 'user123', - keyword_search: true, + filters: { user_id: 'user123' }, rerank: true, }); ``` --- -## Graph Memory +## Entity Linking -Entity-level knowledge graph that creates relationships between memories. +v3 replaces graph memory with built-in entity linking. Entities (proper nouns, quoted text, compound noun phrases) are automatically extracted and linked across memories. ### How It Works -1. **Extraction**: LLM analyzes conversation and identifies entities and relationships -2. **Storage**: Embeddings go to vector store; entity nodes and edges go to graph store -3. **Retrieval**: Vector search returns semantic matches; graph relations are appended to results +1. **Extraction**: During `add()`, entities are automatically extracted from memory text +2. **Storage**: Entities are stored in a parallel collection (`{collection}_entities`) +3. **Retrieval**: During `search()`, query entities are matched and used to boost relevant memories -Graph relations **augment** vector results without reordering them. Vector similarity always determines hit sequence. +Entity linking is automatic — no configuration required. The boost is folded into the combined `score` on each result. -### Enabling Graph Memory +### v2 Migration Note -**Per request:** -```python -client.add(messages, user_id="alice", enable_graph=True) -client.search("query", user_id="alice", enable_graph=True) -client.get_all(filters={"AND": [{"user_id": "alice"}]}, enable_graph=True) -``` +If you were using `enable_graph=True` in v2: +- Remove `enable_graph` from all API calls +- Remove `graph_store` from OSS configuration +- Entity relationships are now consumed through retrieval ranking, not exposed as a separate `relations` array -**Project-level (default for all operations):** -```python -client.project.update(enable_graph=True) -``` - -```javascript -await client.updateProject({ enable_graph: true }); -``` - -### Relation Structure - -Each relation in the response contains: - -| Field | Type | Description | -|-------|------|-------------| -| `source` | string | Source entity name | -| `source_type` | string | Source entity type (e.g., "Person") | -| `relationship` | string | Relationship label (e.g., "lives_in") | -| `target` | string | Target entity name | -| `target_type` | string | Target entity type (e.g., "City") | -| `score` | number | Confidence score | - -**Example:** -```json -{ - "relations": [ - { - "source": "Joseph", - "source_type": "Person", - "relationship": "lives_in", - "target": "Seattle", - "target_type": "City", - "score": 0.92 - } - ] -} -``` - -### Technical Notes - -- Graph Memory adds processing time; see docs for current plan availability -- Works optimally with rich conversation histories containing entity relationships -- Best suited for long-running assistants tracking evolving information -- Graph writes and reads toggle independently per request -- Multi-agent context supported via `user_id`, `agent_id`, `run_id` scoping -- Add operations are asynchronous; graph metadata may not be immediately available +See the [v2 to v3 migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for details. --- @@ -160,7 +94,7 @@ client.project.update(custom_categories=new_categories) ``` ```javascript -await client.updateProject({ custom_categories: new_categories }); +await client.updateProject({ customCategories: newCategories }); ``` **Retrieve active categories:** @@ -185,7 +119,7 @@ client.project.update(custom_instructions="Your guidelines here...") ``` ```javascript -await client.updateProject({ custom_instructions: "Your guidelines here..." }); +await client.updateProject({ customInstructions: "Your guidelines here..." }); ``` ### Template Structure @@ -229,7 +163,7 @@ client.project.update(retrieval_criteria=retrieval_criteria) ```typescript await client.updateProject({ - retrieval_criteria: [ + retrievalCriteria: [ { name: 'joy', description: 'Positive emotions', weight: 3 }, { name: 'urgency', description: 'Time-sensitive items', weight: 4 }, ], @@ -281,7 +215,7 @@ for item in feedback_data: ```typescript await client.feedback('mem-123', { feedback: 'POSITIVE', - feedback_reason: 'Accurately captured dietary preference', + feedbackReason: 'Accurately captured dietary preference', }); ``` @@ -349,23 +283,18 @@ Use the `name` field in messages to identify speakers. Mem0 maps names to entity ## MCP Integration -Model Context Protocol integration enables AI clients (Claude Desktop, Cursor, custom agents) to manage Mem0 memory autonomously. +Model Context Protocol integration enables AI clients (Claude, Claude Code, Cursor, Windsurf, VS Code, OpenCode) to manage Mem0 memory autonomously. -### Configuration +### Setup -```json -{ - "mcpServers": { - "mem0": { - "command": "uvx", - "args": ["mem0-mcp-server"], - "env": { - "MEM0_API_KEY": "m0-your-api-key", - "MEM0_DEFAULT_USER_ID": "your-user-id" - } - } - } -} +Add Mem0 MCP to your clients with a single command: + +```bash +npx mcp-add \ + --name mem0-mcp \ + --type http \ + --url "https://mcp.mem0.ai/mcp" \ + --clients "claude,claude code,cursor,windsurf,vscode,opencode" ``` ### Available MCP Tools @@ -377,7 +306,7 @@ The MCP server exposes 9 memory tools that AI agents can use autonomously: ### How It Works -1. Configure the MCP server in your AI client +1. Add Mem0 MCP to your AI client using the setup command above 2. The agent autonomously decides when to store/retrieve memories 3. No manual API calls needed — the agent manages memory as part of its reasoning diff --git a/mem0-plugin/skills/mem0/references/integration-patterns.md b/mem0-plugin/skills/mem0/references/integration-patterns.md index e00d07ba7..71cfa981c 100644 --- a/mem0-plugin/skills/mem0/references/integration-patterns.md +++ b/mem0-plugin/skills/mem0/references/integration-patterns.md @@ -27,7 +27,7 @@ from langchain_core.messages import SystemMessage, HumanMessage from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from mem0 import MemoryClient -llm = ChatOpenAI(model="gpt-4.1-nano-2025-04-14") +llm = ChatOpenAI(model="gpt-5-mini") mem0 = MemoryClient() prompt = ChatPromptTemplate.from_messages([ @@ -38,7 +38,7 @@ prompt = ChatPromptTemplate.from_messages([ def retrieve_context(query: str, user_id: str): """Retrieve relevant memories from Mem0""" - memories = mem0.search(query, user_id=user_id) + memories = mem0.search(query, filters={"user_id": user_id}) memory_list = memories['results'] serialized = ' '.join([m["memory"] for m in memory_list]) return [ @@ -116,73 +116,24 @@ result = crew.kickoff() ## Vercel AI SDK -Source: [docs.mem0.ai/integrations/vercel-ai-sdk](https://docs.mem0.ai/integrations/vercel-ai-sdk) +> **Dedicated skill available.** For comprehensive Vercel AI SDK documentation, see the [mem0-vercel-ai-sdk skill](https://github.com/mem0ai/mem0/tree/main/skills/mem0-vercel-ai-sdk). Install: `npm install @mem0/vercel-ai-provider` -### Basic Text Generation with Memory +Quick example (wrapped model with automatic memory): ```typescript import { generateText } from "ai"; import { createMem0 } from "@mem0/vercel-ai-provider"; -const mem0 = createMem0({ - provider: "openai", - mem0ApiKey: "m0-xxx", - apiKey: "openai-api-key", -}); - -const { text } = await generateText({ - model: mem0("gpt-4-turbo", { user_id: "borat" }), - prompt: "Suggest me a good car to buy!", -}); -``` - -### Streaming with Memory - -```typescript -import { streamText } from "ai"; -import { createMem0 } from "@mem0/vercel-ai-provider"; - const mem0 = createMem0(); - -const { textStream } = streamText({ - model: mem0("gpt-4-turbo", { user_id: "borat" }), +const { text } = await generateText({ + model: mem0("gpt-5-mini", { user_id: "borat" }), prompt: "Suggest me a good car to buy!", }); - -for await (const textPart of textStream) { - process.stdout.write(textPart); -} ``` -### Using Memory Utilities Standalone - -```typescript -import { openai } from "@ai-sdk/openai"; -import { generateText } from "ai"; -import { retrieveMemories, addMemories } from "@mem0/vercel-ai-provider"; - -// Retrieve memories and inject into any provider -const prompt = "Suggest me a good car to buy."; -const memories = await retrieveMemories(prompt, { user_id: "borat", mem0ApiKey: "m0-xxx" }); - -const { text } = await generateText({ - model: openai("gpt-4-turbo"), - prompt: prompt, - system: memories, -}); - -// Store new memories -await addMemories( - [{ role: "user", content: [{ type: "text", text: "I love red cars." }] }], - { user_id: "borat", mem0ApiKey: "m0-xxx" } -); -``` - -### Supported Providers - -`openai`, `anthropic`, `google`, `groq` +Supported providers: `openai`, `anthropic`, `google`, `groq`, `cohere` --- @@ -199,7 +150,7 @@ mem0 = MemoryClient() @function_tool def search_memory(query: str, user_id: str) -> str: """Search through past conversations and memories""" - memories = mem0.search(query, user_id=user_id, top_k=3) + memories = mem0.search(query, filters={"user_id": user_id}, top_k=3) if memories and memories.get('results'): return "\n".join([f"- {mem['memory']}" for mem in memories['results']]) return "No relevant memories found." @@ -216,7 +167,7 @@ agent = Agent( Use search_memory to recall past conversations. Use save_memory to store important information.""", tools=[search_memory, save_memory], - model="gpt-4.1-nano-2025-04-14" + model="gpt-5-mini" ) result = Runner.run_sync(agent, "I love Italian food and I'm planning a trip to Rome next month") @@ -232,21 +183,21 @@ travel_agent = Agent( name="Travel Planner", instructions="You are a travel planning specialist. Use search_memory and save_memory tools.", tools=[search_memory, save_memory], - model="gpt-4.1-nano-2025-04-14" + model="gpt-5-mini" ) health_agent = Agent( name="Health Advisor", instructions="You are a health and wellness advisor. Use search_memory and save_memory tools.", tools=[search_memory, save_memory], - model="gpt-4.1-nano-2025-04-14" + model="gpt-5-mini" ) triage_agent = Agent( name="Personal Assistant", instructions="""Route travel questions to Travel Planner, health questions to Health Advisor.""", handoffs=[travel_agent, health_agent], - model="gpt-4.1-nano-2025-04-14" + model="gpt-5-mini" ) result = Runner.run_sync(triage_agent, "Plan a healthy meal for my Italy trip") @@ -303,7 +254,7 @@ from langchain_openai import ChatOpenAI from mem0 import MemoryClient from langchain_core.messages import SystemMessage, HumanMessage, AIMessage -llm = ChatOpenAI(model="gpt-4") +llm = ChatOpenAI(model="gpt-5-mini") mem0 = MemoryClient() class State(TypedDict): @@ -315,7 +266,7 @@ def chatbot(state: State): user_id = state["mem0_user_id"] # Retrieve relevant memories - memories = mem0.search(messages[-1].content, user_id=user_id) + memories = mem0.search(messages[-1].content, filters={"user_id": user_id}) context = "Relevant context:\n" for memory in memories["results"]: context += f"- {memory['memory']}\n" @@ -368,7 +319,7 @@ memory = Mem0Memory.from_client( from llama_index.core.agent import FunctionCallingAgent from llama_index.llms.openai import OpenAI -llm = OpenAI(model="gpt-4") +llm = OpenAI(model="gpt-5-mini") agent = FunctionCallingAgent.from_tools( tools=[], llm=llm, @@ -401,14 +352,14 @@ USER_ID = "alice" agent = ConversableAgent( "chatbot", - llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]}, + llm_config={"config_list": [{"model": "gpt-5-mini", "api_key": os.environ["OPENAI_API_KEY"]}]}, code_execution_config=False, human_input_mode="NEVER", ) def get_context_aware_response(question: str) -> str: # Retrieve memories for context - relevant_memories = memory_client.search(question, user_id=USER_ID) + relevant_memories = memory_client.search(question, filters={"user_id": USER_ID}) context = "\n".join([m["memory"] for m in relevant_memories.get("results", [])]) prompt = f"""Answer considering previous interactions: diff --git a/mem0-plugin/skills/mem0/references/quickstart.md b/mem0-plugin/skills/mem0/references/quickstart.md index cfd34b86e..0a47a2fd4 100644 --- a/mem0-plugin/skills/mem0/references/quickstart.md +++ b/mem0-plugin/skills/mem0/references/quickstart.md @@ -27,7 +27,7 @@ messages = [ client.add(messages, user_id="user123") # Search memories -results = client.search("What are my dietary restrictions?", user_id="user123") +results = client.search("What are my dietary restrictions?", filters={"user_id": "user123"}) print(results) ``` @@ -39,7 +39,7 @@ from mem0 import AsyncMemoryClient client = AsyncMemoryClient(api_key="your-api-key") await client.add(messages, user_id="user123") -results = await client.search("query", user_id="user123") +results = await client.search("query", filters={"user_id": "user123"}) ``` ## TypeScript / JavaScript Setup @@ -59,11 +59,11 @@ const messages = [ {"role": "user", "content": "I'm a vegetarian and allergic to nuts."}, {"role": "assistant", "content": "Got it! I'll remember your dietary preferences."} ]; -await client.add(messages, { user_id: "user123" }); +await client.add(messages, { userId: "user123" }); // Search memories const results = await client.search("What are my dietary restrictions?", { - user_id: "user123" + filters: { user_id: "user123" } }); console.log(results); ``` @@ -86,7 +86,7 @@ curl -X POST https://api.mem0.ai/v1/memories/ \ }' # Search memories -curl -X POST https://api.mem0.ai/v2/memories/search/ \ +curl -X POST https://api.mem0.ai/v3/memories/search/ \ -H "Authorization: Token $MEM0_API_KEY" \ -H "Content-Type: application/json" \ -d '{ diff --git a/mem0-plugin/skills/mem0/references/sdk-guide.md b/mem0-plugin/skills/mem0/references/sdk-guide.md index dc744d625..512c0d19c 100644 --- a/mem0-plugin/skills/mem0/references/sdk-guide.md +++ b/mem0-plugin/skills/mem0/references/sdk-guide.md @@ -2,6 +2,8 @@ Complete SDK reference for Python and TypeScript. All methods use `MemoryClient` (Platform API). +> **For language-specific deep references (including OSS):** See [client/python.md](../client/python.md) and [client/node.md](../client/node.md). For Python vs TypeScript differences: [client/differences.md](../client/differences.md). + ## Initialization **Python:** @@ -38,16 +40,12 @@ client.add(messages, user_id="alice") # With metadata client.add(messages, user_id="alice", metadata={"source": "onboarding"}) - -# With graph memory -client.add(messages, user_id="alice", enable_graph=True) ``` **TypeScript:** ```typescript -await client.add(messages, { user_id: "alice" }); -await client.add(messages, { user_id: "alice", metadata: { source: "onboarding" } }); -await client.add(messages, { user_id: "alice", enable_graph: true }); +await client.add(messages, { userId: "alice" }); +await client.add(messages, { userId: "alice", metadata: { source: "onboarding" } }); ``` ### Parameters @@ -59,32 +57,14 @@ await client.add(messages, { user_id: "alice", enable_graph: true }); | `agent_id` | string | Agent identifier | | `run_id` | string | Session identifier | | `metadata` | object | Custom key-value pairs | -| `enable_graph` | boolean | Activate knowledge graph | | `infer` | boolean | If `false`, store raw text without inference (default: `true`) | -| `immutable` | boolean | Prevents modification after creation | -| `expiration_date` | string | Auto-expiry date (`YYYY-MM-DD`) | -| `includes` | string | Preference filters for inclusion | -| `excludes` | string | Preference filters for exclusion | -| `async_mode` | boolean | Async processing (default: `true`). Set `false` to wait | ### Advanced Add Options ```python -# Immutable -- cannot be modified or overwritten -client.add(messages, user_id="alice", immutable=True) - -# Expiring memory -client.add(messages, user_id="alice", expiration_date="2025-12-31") - -# Selective extraction -client.add(messages, user_id="alice", includes="dietary preferences", excludes="payment info") - # Agent + session scoping client.add(messages, user_id="alice", agent_id="nutrition-agent", run_id="session-456") -# Synchronous processing (wait for completion) -client.add(messages, user_id="alice", async_mode=False) - # Raw text -- skip LLM inference client.add( [{"role": "user", "content": "User prefers dark mode."}], @@ -99,7 +79,7 @@ client.add( **Python:** ```python -results = client.search("dietary preferences?", user_id="alice") +results = client.search("dietary preferences?", filters={"user_id": "alice"}) # With filters and reranking results = client.search( @@ -109,20 +89,14 @@ results = client.search( rerank=True, threshold=0.5 ) - -# With graph relations -results = client.search("colleagues", user_id="alice", enable_graph=True) - -# Keyword search -results = client.search("vegetarian", user_id="alice", keyword_search=True) ``` **TypeScript:** ```typescript -const results = await client.search("dietary preferences", { user_id: "alice" }); +const results = await client.search("dietary preferences", { filters: { user_id: "alice" } }); const results = await client.search("work experience", { filters: { AND: [{ user_id: "alice" }, { categories: { contains: "professional_details" } }] }, - top_k: 5, + topK: 5, rerank: true, }); ``` @@ -132,19 +106,17 @@ const results = await client.search("work experience", { | Name | Type | Description | |------|------|-------------| | `query` | string | Natural language search query | -| `user_id` | string | Filter by user | -| `filters` | object | V2 filter object (AND/OR operators) | -| `top_k` | number | Number of results (default: 10) | -| `rerank` | boolean | Enable reranking for better relevance | -| `threshold` | number | Minimum similarity score (default: 0.3) | -| `keyword_search` | boolean | Use keyword-based search | -| `enable_graph` | boolean | Include graph relations | +| `filters` | object | Filter object (AND/OR operators). Use `{"user_id": "..."}` to filter by user | +| `top_k` | number | Number of results (default: 10 for Platform) | +| `rerank` | boolean | Enable reranking for better relevance (default: `false`) | +| `threshold` | number | Minimum similarity score (default: 0.1) | ### Common Filter Patterns +**Python:** ```python -# Single user (shorthand) -client.search("query", user_id="alice") +# Single user filter +filters={"user_id": "alice"} # OR across agents filters={"OR": [{"user_id": "alice"}, {"agent_id": {"in": ["travel-agent", "sports-agent"]}}]} @@ -177,6 +149,21 @@ filters={"AND": [ ]} ``` +**TypeScript:** +```typescript +// Single user filter +filters: { user_id: "alice" } + +// OR across agents +filters: { OR: [{ user_id: "alice" }, { agent_id: { in: ["travel-agent", "sports-agent"] } }] } + +// Category filtering (partial match) +filters: { AND: [{ user_id: "alice" }, { categories: { contains: "finance" } }] } + +// Category filtering (exact match) +filters: { AND: [{ user_id: "alice" }, { categories: { in: ["personal_information"] } }] } +``` + --- ## get() / getAll() -- Retrieve Memories @@ -187,7 +174,7 @@ filters={"AND": [ memory = client.get(memory_id="ea925981-...") # All memories for a user -memories = client.get_all(filters={"AND": [{"user_id": "alice"}]}) +memories = client.get_all(filters={"user_id": "alice"}) # With date range memories = client.get_all( @@ -196,15 +183,12 @@ memories = client.get_all( {"created_at": {"gte": "2024-07-01", "lte": "2024-07-31"}} ]} ) - -# With graph data -memories = client.get_all(filters={"AND": [{"user_id": "alice"}]}, enable_graph=True) ``` **TypeScript:** ```typescript const memory = await client.get("ea925981-..."); -const memories = await client.getAll({ filters: { AND: [{ user_id: "alice" }] } }); +const memories = await client.getAll({ filters: { user_id: "alice" } }); ``` **Note:** `get_all` requires at least one of `user_id`, `agent_id`, `app_id`, or `run_id` in filters. @@ -224,8 +208,6 @@ client.update(memory_id="ea925981-...", text="Updated", metadata={"verified": Tr await client.update("ea925981-...", { text: "Updated: vegan since 2024" }); ``` -Cannot update immutable memories. - --- ## delete() / deleteAll() -- Remove Memories @@ -239,7 +221,7 @@ client.delete_all(user_id="alice") # Irreversible bulk delete **TypeScript:** ```typescript await client.delete("ea925981-..."); -await client.deleteAll({ user_id: "alice" }); +await client.deleteAll({ userId: "alice" }); ``` --- @@ -299,10 +281,73 @@ data = client.get_memory_export(memory_export_id=export["id"]) 2. **SQL operators rejected** -- use `gte`, `lt`, etc. Not `>=`, `<`. 3. **Metadata filtering is limited** -- only top-level keys with `eq`, `contains`, `ne`. 4. **Wildcard `*` excludes null** -- only matches non-null values. -5. **Default threshold is 0.3** -- increase for stricter matching. +5. **Default threshold is 0.1** -- increase for stricter matching. 6. **Async processing** -- memories process asynchronously. Wait 2-3s after `add()` before searching. -7. **Immutable memories** -- cannot be updated or deleted once created. ## Naming Conventions -Python uses `snake_case` (`user_id`, `memory_id`, `get_all`). TypeScript uses `camelCase` for methods (`getAll`, `deleteAll`, `batchUpdate`) but `snake_case` for API parameters (`user_id`, `agent_id`). +Python uses `snake_case` everywhere (`user_id`, `memory_id`, `get_all`). TypeScript uses `camelCase` for methods (`getAll`, `deleteAll`, `batchUpdate`) and top-level parameters (`userId`, `topK`, `pageSize`), but filter keys use `snake_case` (`user_id`, `agent_id`). + +--- + +## v2 to v3 Migration + +### Breaking Changes in v3 + +**1. Entity IDs in search() and getAll()** + +v3 requires entity IDs (`user_id`, `agent_id`, `run_id`) inside `filters` instead of as top-level parameters: + +```python +# v2 (deprecated) +client.search("query", user_id="alice") +client.get_all(user_id="alice") + +# v3 +client.search("query", filters={"user_id": "alice"}) +client.get_all(filters={"user_id": "alice"}) +``` + +```typescript +// v2 (deprecated) +await client.search("query", { user_id: "alice" }); +await client.getAll({ user_id: "alice" }); + +// v3 +await client.search("query", { filters: { user_id: "alice" } }); +await client.getAll({ filters: { user_id: "alice" } }); +``` + +**2. TypeScript Parameter Naming** + +v3 TypeScript uses camelCase for all parameters: + +| v2 | v3 | +|----|-----| +| `user_id` | `userId` | +| `agent_id` | `agentId` | +| `run_id` | `runId` | +| `top_k` | `topK` | +| `page_size` | `pageSize` | + +**3. Default Values Changed** + +| Parameter | v2 Default | v3 Default | +|-----------|------------|------------| +| `threshold` | 0.3 | 0.1 | +| `rerank` | (not specified) | `false` | + +**4. Removed Parameters** + +The following parameters are no longer supported: + +| Parameter | Status | +|-----------|--------| +| `enable_graph` | Removed from add/search/getAll | +| `keyword_search` | Removed from search | +| `filter_memories` | Removed | +| `immutable` | Removed from add | +| `expiration_date` | Removed from add | +| `includes` | Removed from add | +| `excludes` | Removed from add | +| `async_mode` | Removed from add | diff --git a/mem0-plugin/skills/mem0/references/use-cases.md b/mem0-plugin/skills/mem0/references/use-cases.md index eaca88896..5f3ba655d 100644 --- a/mem0-plugin/skills/mem0/references/use-cases.md +++ b/mem0-plugin/skills/mem0/references/use-cases.md @@ -39,7 +39,7 @@ Use these known facts about the user to personalize your response: {context if context else 'No prior context yet.'}""" response = openai_client.chat.completions.create( - model="gpt-4.1-nano-2025-04-14", + model="gpt-5-mini", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_input}, @@ -72,14 +72,14 @@ const openai = new OpenAI(); async function chat(userInput: string, userId: string): Promise { // 1. Retrieve relevant memories - const memories = await mem0.search(userInput, { user_id: userId }); + const memories = await mem0.search(userInput, { filters: { user_id: userId } }); const context = memories.results ?.map((m: any) => `- ${m.memory}`) .join('\n') || 'No prior context yet.'; // 2. Generate response with memory context const response = await openai.chat.completions.create({ - model: 'gpt-4.1-nano-2025-04-14', + model: 'gpt-5-mini', messages: [ { role: 'system', content: `You are Ray, a personal fitness coach.\nUser context:\n${context}` }, { role: 'user', content: userInput }, @@ -90,7 +90,7 @@ async function chat(userInput: string, userId: string): Promise { // 3. Store interaction await mem0.add( [{ role: 'user', content: userInput }, { role: 'assistant', content: reply }], - { user_id: userId } + { userId: userId } ); return reply; } @@ -182,7 +182,7 @@ await client.updateProject({ async function logInteraction(userId: string, message: string, priority = 'normal') { await client.add( [{ role: 'user', content: message }], - { user_id: userId, metadata: { priority, source: 'support_chat' } } + { userId: userId, metadata: { priority, source: 'support_chat' } } ); } @@ -230,7 +230,7 @@ def consult(user_id: str, question: str) -> str: context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])]) response = openai_client.chat.completions.create( - model="gpt-4.1-nano-2025-04-14", + model="gpt-5-mini", messages=[ {"role": "system", "content": f"You are a health coach. Patient context:\n{context}"}, {"role": "user", "content": question}, @@ -264,20 +264,20 @@ const openai = new OpenAI(); async function savePatientInfo(userId: string, info: string) { await mem0.add( [{ role: 'user', content: info }], - { user_id: userId, run_id: 'healthcare_session', metadata: { type: 'patient_information' } } + { userId: userId, runId: 'healthcare_session', metadata: { type: 'patient_information' } } ); } async function consult(userId: string, question: string): Promise { const memories = await mem0.search(question, { - user_id: userId, - top_k: 5, + filters: { user_id: userId }, + topK: 5, threshold: 0.7, }); const context = memories.results?.map((m: any) => `- ${m.memory}`).join('\n') || ''; const response = await openai.chat.completions.create({ - model: 'gpt-4.1-nano-2025-04-14', + model: 'gpt-5-mini', messages: [ { role: 'system', content: `You are a health coach. Patient context:\n${context}` }, { role: 'user', content: question }, @@ -287,7 +287,7 @@ async function consult(userId: string, question: string): Promise { await mem0.add( [{ role: 'user', content: question }, { role: 'assistant', content: reply }], - { user_id: userId, run_id: 'healthcare_session' } + { userId: userId, runId: 'healthcare_session' } ); return reply; } @@ -333,7 +333,7 @@ def draft_content(user_id: str, topic: str) -> str: style_context = "\n".join([f"- {m['memory']}" for m in prefs.get("results", [])]) response = openai_client.chat.completions.create( - model="gpt-4.1-nano-2025-04-14", + model="gpt-5-mini", messages=[ {"role": "system", "content": f"Write content matching these style preferences:\n{style_context}"}, {"role": "user", "content": f"Write a blog post about: {topic}"}, @@ -359,7 +359,7 @@ const openai = new OpenAI(); async function storePreferences(userId: string, preferences: string) { await mem0.add( [{ role: 'user', content: preferences }], - { user_id: userId, run_id: 'editing_session', metadata: { type: 'preferences' } } + { userId: userId, runId: 'editing_session', metadata: { type: 'preferences' } } ); } @@ -370,7 +370,7 @@ async function draftContent(userId: string, topic: string): Promise { const styleContext = prefs.results?.map((m: any) => `- ${m.memory}`).join('\n') || ''; const response = await openai.chat.completions.create({ - model: 'gpt-4.1-nano-2025-04-14', + model: 'gpt-5-mini', messages: [ { role: 'system', content: `Write content matching these preferences:\n${styleContext}` }, { role: 'user', content: `Write a blog post about: ${topic}` }, @@ -465,10 +465,10 @@ async function storeScopedMemory( userId: string, agentId: string, runId: string, appId: string ) { await client.add(messages, { - user_id: userId, - agent_id: agentId, - run_id: runId, - app_id: appId, + userId: userId, + agentId: agentId, + runId: runId, + appId: appId, }); } @@ -520,7 +520,7 @@ def personalized_search(user_id: str, query: str, search_results: list) -> str: user_context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])]) response = openai_client.chat.completions.create( - model="gpt-4.1-nano-2025-04-14", + model="gpt-5-mini", messages=[ {"role": "system", "content": f"Personalize search results using user context:\n{user_context}"}, {"role": "user", "content": f"Query: {query}\n\nSearch results:\n{search_results}"}, @@ -551,11 +551,11 @@ const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! }); const openai = new OpenAI(); async function personalizedSearch(userId: string, query: string, searchResults: string[]): Promise { - const memories = await mem0.search(query, { user_id: userId, top_k: 5 }); + const memories = await mem0.search(query, { filters: { user_id: userId }, topK: 5 }); const context = memories.results?.map((m: any) => `- ${m.memory}`).join('\n') || ''; const response = await openai.chat.completions.create({ - model: 'gpt-4.1-nano-2025-04-14', + model: 'gpt-5-mini', messages: [ { role: 'system', content: `Personalize results using user context:\n${context}` }, { role: 'user', content: `Query: ${query}\nResults: ${searchResults.join(', ')}` }, @@ -563,7 +563,7 @@ async function personalizedSearch(userId: string, query: string, searchResults: }); const reply = response.choices[0].message.content!; - await mem0.add([{ role: 'user', content: query }], { user_id: userId }); + await mem0.add([{ role: 'user', content: query }], { userId: userId }); return reply; } ``` @@ -631,14 +631,14 @@ const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! }); async function storeEmail(userId: string, sender: string, subject: string, body: string, date: string) { await client.add( [{ role: 'user', content: `Email from ${sender}: ${subject}\n\n${body}` }], - { user_id: userId, metadata: { email_type: 'incoming', sender, subject, date } } + { userId: userId, metadata: { email_type: 'incoming', sender, subject, date } } ); } async function searchEmails(userId: string, query: string) { return client.search(query, { filters: { AND: [{ user_id: userId }, { categories: { contains: 'email' } }] }, - top_k: 10, + topK: 10, }); } ``` diff --git a/mem0-ts/package.json b/mem0-ts/package.json index f0cd2994a..ec7235bac 100644 --- a/mem0-ts/package.json +++ b/mem0-ts/package.json @@ -1,6 +1,6 @@ { "name": "mem0ai", - "version": "3.0.1", + "version": "3.0.2", "description": "The Memory Layer For Your AI Apps", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/pyproject.toml b/pyproject.toml index fa3a553e1..94bdf4e1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "mem0ai" -version = "2.0.0" +version = "2.0.1" description = "Long-term memory for AI Agents" authors = [ { name = "Mem0", email = "support@mem0.ai" }