diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
new file mode 100644
index 000000000..82ce93578
--- /dev/null
+++ b/.claude-plugin/marketplace.json
@@ -0,0 +1,18 @@
+{
+ "name": "mem0-plugins",
+ "owner": {
+ "name": "Mem0",
+ "email": "support@mem0.ai"
+ },
+ "metadata": {
+ "description": "Official Mem0 plugins for Claude"
+ },
+ "plugins": [
+ {
+ "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"
+ }
+ ]
+}
diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json
new file mode 100644
index 000000000..c23fc2e22
--- /dev/null
+++ b/.cursor-plugin/marketplace.json
@@ -0,0 +1,18 @@
+{
+ "name": "mem0-plugins",
+ "owner": {
+ "name": "Mem0",
+ "email": "support@mem0.ai"
+ },
+ "metadata": {
+ "description": "Official Mem0 plugins for Cursor"
+ },
+ "plugins": [
+ {
+ "name": "mem0",
+ "source": "./mem0-plugin",
+ "description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search.",
+ "version": "0.1.0"
+ }
+ ]
+}
diff --git a/docs/openapi.json b/docs/openapi.json
index 1da505361..e35e73357 100644
--- a/docs/openapi.json
+++ b/docs/openapi.json
@@ -4,7 +4,7 @@
"title": "Mem0 API Docs",
"description": "mem0.ai API Docs",
"contact": {
- "email": "deshraj@mem0.ai"
+ "email": "support@mem0.ai"
},
"license": {
"name": "Apache 2.0"
diff --git a/mem0-plugin/.claude-plugin/plugin.json b/mem0-plugin/.claude-plugin/plugin.json
new file mode 100644
index 000000000..d64acdb67
--- /dev/null
+++ b/mem0-plugin/.claude-plugin/plugin.json
@@ -0,0 +1,12 @@
+{
+ "name": "mem0",
+ "version": "0.1.0",
+ "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",
+ "url": "https://github.com/mem0ai"
+ },
+ "repository": "https://github.com/mem0ai/mem0",
+ "logo": "logo.svg",
+ "license": "Apache-2.0"
+}
diff --git a/mem0-plugin/.cursor-plugin/plugin.json b/mem0-plugin/.cursor-plugin/plugin.json
new file mode 100644
index 000000000..b901e3d43
--- /dev/null
+++ b/mem0-plugin/.cursor-plugin/plugin.json
@@ -0,0 +1,12 @@
+{
+ "name": "mem0",
+ "version": "0.1.0",
+ "description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search using the Mem0 Platform MCP server.",
+ "author": {
+ "name": "Mem0",
+ "url": "https://github.com/mem0ai"
+ },
+ "repository": "https://github.com/mem0ai/mem0",
+ "logo": "logo.svg",
+ "license": "Apache-2.0"
+}
diff --git a/mem0-plugin/.mcp.json b/mem0-plugin/.mcp.json
new file mode 100644
index 000000000..dd091bc0c
--- /dev/null
+++ b/mem0-plugin/.mcp.json
@@ -0,0 +1,11 @@
+{
+ "mcpServers": {
+ "mem0": {
+ "type": "http",
+ "url": "https://mcp.mem0.ai/mcp/",
+ "headers": {
+ "Authorization": "Token ${MEM0_API_KEY}"
+ }
+ }
+ }
+}
diff --git a/mem0-plugin/README.md b/mem0-plugin/README.md
new file mode 100644
index 000000000..c1f1e77f9
--- /dev/null
+++ b/mem0-plugin/README.md
@@ -0,0 +1,81 @@
+# Mem0 Plugin for Claude & Cursor
+
+Add persistent memory to your AI coding workflows. Store, retrieve, and manage memories across sessions using the Mem0 Platform. Works with both **Claude Code** and **Cursor**.
+
+## Step 1: Set your API key
+
+> **You must complete this step before installing the plugin for either Claude Code or Cursor.**
+
+1. Sign up at [app.mem0.ai](https://app.mem0.ai) if you haven't already
+2. Go to [app.mem0.ai/dashboard/api-keys](https://app.mem0.ai/dashboard/api-keys)
+3. Click **Create API Key** and copy the key (starts with `m0-`)
+4. Add it to your shell profile:
+
+ ```bash
+ # For zsh (default on macOS)
+ echo 'export MEM0_API_KEY="m0-your-api-key"' >> ~/.zshrc
+ source ~/.zshrc
+
+ # For bash
+ echo 'export MEM0_API_KEY="m0-your-api-key"' >> ~/.bashrc
+ source ~/.bashrc
+ ```
+
+5. Confirm it's set:
+
+ ```bash
+ echo $MEM0_API_KEY
+ # Should print: m0-your-api-key
+ ```
+
+## Step 2: Install the plugin
+
+Choose one of the options below. Both require `MEM0_API_KEY` to be set first (see above).
+
+### Claude Code
+
+```
+/plugin marketplace add mem0ai/mem0
+/plugin install mem0@mem0-plugins
+```
+
+### Cursor
+
+Click the deeplink below to install the Mem0 MCP server in Cursor:
+
+[Install Mem0 MCP in Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=mem0&config=eyJtY3BTZXJ2ZXJzIjp7Im1lbTAiOnsidHlwZSI6Imh0dHAiLCJ1cmwiOiJodHRwczovL21jcC5tZW0wLmFpL21jcC8iLCJoZWFkZXJzIjp7IkF1dGhvcml6YXRpb24iOiJUb2tlbiAke01FTTBfQVBJX0tFWX0ifX19fQ==)
+
+> **Already have `mem0` configured as an MCP server?** Remove the existing entry from your `.mcp.json` or settings before installing this plugin to avoid duplicate tools.
+
+## Verify it works
+
+After installing, confirm the MCP server is connected:
+
+1. Start a new session (or restart your current one)
+2. Ask: *"List my mem0 entities"* or *"Search my memories for hello"*
+3. If the `mem0` tools appear and respond, you're all set
+
+## What's included
+
+- **MCP Server** — Connects to the Mem0 remote MCP server (`mcp.mem0.ai`), providing tools to add, search, update, and delete memories. No local dependencies required.
+- **Mem0 Skill** — Guides Claude on how to integrate the Mem0 SDK (Python & TypeScript) into your applications
+
+## MCP Tools
+
+Once installed, the following tools are available:
+
+| Tool | Description |
+|------|-------------|
+| `add_memory` | Save text or conversation history for a user/agent |
+| `search_memories` | Semantic search across memories with filters |
+| `get_memories` | List memories with filters and pagination |
+| `get_memory` | Retrieve a specific memory by ID |
+| `update_memory` | Overwrite a memory's text by ID |
+| `delete_memory` | Delete a single memory by ID |
+| `delete_all_memories` | Bulk delete all memories in scope |
+| `delete_entities` | Delete a user/agent/app/run entity and its memories |
+| `list_entities` | List users/agents/apps/runs stored in Mem0 |
+
+## License
+
+Apache-2.0
diff --git a/mem0-plugin/hooks/hooks.json b/mem0-plugin/hooks/hooks.json
new file mode 100644
index 000000000..dbfad555d
--- /dev/null
+++ b/mem0-plugin/hooks/hooks.json
@@ -0,0 +1,79 @@
+{
+ "description": "Mem0 memory capture hooks — automatic memory extraction at key lifecycle points",
+ "hooks": {
+ "SessionStart": [
+ {
+ "matcher": "startup|resume|compact",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/on_session_start.sh",
+ "statusMessage": "Loading mem0 context..."
+ }
+ ]
+ }
+ ],
+ "PreToolUse": [
+ {
+ "matcher": "Write|Edit",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/block_memory_write.sh"
+ }
+ ]
+ }
+ ],
+ "PreCompact": [
+ {
+ "hooks": [
+ {
+ "type": "command",
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/on_pre_compact.sh",
+ "statusMessage": "Preparing pre-compaction summary..."
+ },
+ {
+ "type": "command",
+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/on_pre_compact.py",
+ "statusMessage": "Saving session state to mem0...",
+ "timeout": 30
+ }
+ ]
+ }
+ ],
+ "Stop": [
+ {
+ "hooks": [
+ {
+ "type": "command",
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/on_stop.sh",
+ "timeout": 10
+ }
+ ]
+ }
+ ],
+ "UserPromptSubmit": [
+ {
+ "hooks": [
+ {
+ "type": "command",
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/on_user_prompt.sh",
+ "statusMessage": "Searching mem0 memories...",
+ "timeout": 5
+ }
+ ]
+ }
+ ],
+ "TaskCompleted": [
+ {
+ "hooks": [
+ {
+ "type": "command",
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/on_task_completed.sh",
+ "timeout": 10
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/mem0-plugin/logo.svg b/mem0-plugin/logo.svg
new file mode 100644
index 000000000..cf13d0d38
--- /dev/null
+++ b/mem0-plugin/logo.svg
@@ -0,0 +1,19 @@
+
diff --git a/mem0-plugin/scripts/block_memory_write.sh b/mem0-plugin/scripts/block_memory_write.sh
new file mode 100755
index 000000000..0cf6dbc84
--- /dev/null
+++ b/mem0-plugin/scripts/block_memory_write.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+# Hook: PreToolUse (matcher: Write|Edit)
+#
+# Blocks writes to MEMORY.md and auto-memory files, redirecting Claude
+# to use the mem0 MCP add_memory tool instead.
+#
+# Input: JSON on stdin with tool_name, tool_input
+# Output: stderr message (exit 2 = block)
+#
+# Exit codes:
+# 0 = allow the tool call
+# 2 = block the tool call (stderr is shown to Claude as feedback)
+
+set -euo pipefail
+
+INPUT=$(cat)
+
+FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""' 2>/dev/null || echo "")
+
+if [ -z "$FILE_PATH" ]; then
+ exit 0
+fi
+
+case "$FILE_PATH" in
+ */MEMORY.md|*/memory/*.md|*/.claude/*/memory/*)
+ echo "BLOCKED: Do not write to $FILE_PATH. Use the mem0 MCP \`add_memory\` tool instead to persist memories. This project uses mem0 for all memory storage." >&2
+ exit 2
+ ;;
+ *)
+ exit 0
+ ;;
+esac
diff --git a/mem0-plugin/scripts/on_pre_compact.py b/mem0-plugin/scripts/on_pre_compact.py
new file mode 100755
index 000000000..fb59e8d5c
--- /dev/null
+++ b/mem0-plugin/scripts/on_pre_compact.py
@@ -0,0 +1,239 @@
+#!/usr/bin/env python3
+"""Capture session state via the Mem0 REST API.
+
+Safety net for PreCompact and Stop hooks — reads the transcript JSONL,
+extracts structured session state, and stores it in Mem0 directly.
+
+Used by:
+ - PreCompact hook: Tags with "pre-compaction" (context about to be lost)
+ - Stop hook: Tags with "session-end" (session ending, Claude can't respond)
+
+Input: JSON on stdin with transcript_path, session_id, cwd
+Output: stderr logs only (exit 0 always — must not block)
+"""
+
+from __future__ import annotations
+
+import json
+import logging
+import os
+import sys
+import urllib.request
+import urllib.error
+
+log = logging.getLogger("mem0-capture")
+log.setLevel(logging.DEBUG)
+_handler = logging.StreamHandler(sys.stderr)
+_handler.setFormatter(logging.Formatter("[mem0-capture] %(message)s"))
+log.addHandler(_handler)
+
+API_URL = "https://api.mem0.ai"
+MAX_TAIL_LINES = 500
+MAX_USER_MESSAGES = 30
+MAX_BASH_COMMANDS = 20
+MAX_ASSISTANT_TEXT = 10000
+
+
+def tail_lines(filepath: str, n: int) -> list[str]:
+ """Read last n lines of a file efficiently."""
+ try:
+ with open(filepath, "rb") as f:
+ f.seek(0, 2)
+ file_size = f.tell()
+ if file_size == 0:
+ return []
+ chunk_size = min(file_size, n * 4096)
+ f.seek(max(0, file_size - chunk_size))
+ data = f.read().decode("utf-8", errors="replace")
+ return data.splitlines()[-n:]
+ except OSError:
+ return []
+
+
+def parse_transcript(lines: list[str]) -> dict:
+ """Parse transcript JSONL lines and extract session state."""
+ user_messages: list[str] = []
+ files_modified: set[str] = set()
+ bash_commands: list[str] = []
+ last_assistant_text = ""
+
+ for line in lines:
+ line = line.strip()
+ if not line:
+ continue
+ try:
+ entry = json.loads(line)
+ except json.JSONDecodeError:
+ continue
+
+ entry_type = entry.get("type")
+ if entry_type not in ("user", "assistant"):
+ continue
+ if entry.get("isSidechain"):
+ continue
+
+ message = entry.get("message", {})
+ content_blocks = message.get("content", [])
+
+ if entry_type == "user":
+ parts = []
+ if isinstance(content_blocks, str):
+ parts.append(content_blocks)
+ elif isinstance(content_blocks, list):
+ for block in content_blocks:
+ if isinstance(block, str):
+ parts.append(block)
+ elif isinstance(block, dict) and block.get("type") == "text":
+ parts.append(block.get("text", ""))
+ text = "\n".join(parts).strip()
+ if text and len(text) > 10 and not text.startswith("<"):
+ user_messages.append(text)
+
+ elif entry_type == "assistant":
+ for block in content_blocks:
+ if not isinstance(block, dict):
+ continue
+ if block.get("type") == "text":
+ text = block.get("text", "").strip()
+ if text:
+ last_assistant_text = text
+ if block.get("type") == "tool_use":
+ tool_name = block.get("name", "")
+ tool_input = block.get("input", {})
+ if tool_name in ("Write", "Edit"):
+ fp = tool_input.get("file_path", "")
+ if fp:
+ files_modified.add(fp)
+ elif tool_name == "Bash":
+ cmd = tool_input.get("command", "")
+ if cmd:
+ bash_commands.append(cmd)
+
+ return {
+ "user_messages": user_messages[-MAX_USER_MESSAGES:],
+ "files_modified": sorted(files_modified),
+ "bash_commands": bash_commands[-MAX_BASH_COMMANDS:],
+ "last_assistant_text": last_assistant_text[:MAX_ASSISTANT_TEXT],
+ }
+
+
+def build_content(state: dict, source: str) -> str:
+ """Build structured markdown from parsed state."""
+ parts = [f"## Session State ({source})\n"]
+
+ if state["user_messages"]:
+ parts.append("### What the user was working on")
+ for msg in state["user_messages"]:
+ truncated = msg[:5000] + "..." if len(msg) > 5000 else msg
+ parts.append(f"- {truncated}")
+ parts.append("")
+
+ if state["files_modified"]:
+ parts.append("### Files modified this session")
+ for fp in state["files_modified"]:
+ parts.append(f"- `{fp}`")
+ parts.append("")
+
+ if state["bash_commands"]:
+ parts.append("### Recent commands")
+ for cmd in state["bash_commands"]:
+ truncated = cmd[:1000] + "..." if len(cmd) > 1000 else cmd
+ parts.append(f"- `{truncated}`")
+ parts.append("")
+
+ if state["last_assistant_text"]:
+ parts.append("### Last context")
+ parts.append(state["last_assistant_text"])
+ parts.append("")
+
+ return "\n".join(parts)
+
+
+def store_memory(api_key: str, content: str, user_id: str, source: str) -> bool:
+ """Store session state as a memory via the Mem0 REST API."""
+ body = {
+ "messages": [
+ {"role": "user", "content": content}
+ ],
+ "user_id": user_id,
+ "metadata": {
+ "type": "session_state",
+ "source": source,
+ },
+ }
+
+ data = json.dumps(body).encode("utf-8")
+ req = urllib.request.Request(
+ f"{API_URL}/v1/memories/",
+ data=data,
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Token {api_key}",
+ },
+ method="POST",
+ )
+
+ try:
+ with urllib.request.urlopen(req, timeout=15) as resp:
+ if resp.status in (200, 201):
+ log.info("Session state stored successfully")
+ return True
+ log.warning("API returned status %d", resp.status)
+ return False
+ except urllib.error.URLError as e:
+ log.warning("API call failed: %s", e)
+ return False
+
+
+def main():
+ source = "pre-compaction"
+ for arg in sys.argv[1:]:
+ if arg.startswith("--source="):
+ source = arg.split("=", 1)[1]
+
+ api_key = os.environ.get("MEM0_API_KEY", "")
+ if not api_key:
+ log.debug("MEM0_API_KEY not set, skipping capture")
+ return
+
+ try:
+ hook_input = json.loads(sys.stdin.read())
+ except (json.JSONDecodeError, OSError):
+ log.debug("No valid JSON on stdin")
+ return
+
+ transcript_path = hook_input.get("transcript_path", "")
+ if not transcript_path:
+ log.debug("No transcript_path provided")
+ return
+
+ user_id = os.environ.get("MEM0_USER_ID", os.environ.get("USER", "default"))
+
+ lines = tail_lines(transcript_path, MAX_TAIL_LINES)
+ if not lines:
+ log.debug("Transcript empty or unreadable: %s", transcript_path)
+ return
+
+ state = parse_transcript(lines)
+ if not state["user_messages"] and not state["files_modified"]:
+ log.debug("No meaningful session state to capture")
+ return
+
+ content = build_content(state, source)
+
+ log.info(
+ "Capturing session state: %d user msgs, %d files, %d commands",
+ len(state["user_messages"]),
+ len(state["files_modified"]),
+ len(state["bash_commands"]),
+ )
+
+ store_memory(api_key, content, user_id, source)
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except Exception as e:
+ log.error("Unexpected error: %s", e)
+ sys.exit(0)
diff --git a/mem0-plugin/scripts/on_pre_compact.sh b/mem0-plugin/scripts/on_pre_compact.sh
new file mode 100755
index 000000000..0cd1dead2
--- /dev/null
+++ b/mem0-plugin/scripts/on_pre_compact.sh
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+# Hook: PreCompact
+#
+# Fires BEFORE context compaction. This is the last chance to capture
+# the full context before it gets compressed.
+#
+# Output: Text instructions injected into Claude's context.
+# Claude still has the full conversation and can write an accurate summary.
+# A companion Python script (on_pre_compact.py) also runs to capture
+# transcript state directly via the Mem0 REST API as a safety net.
+
+set -euo pipefail
+
+cat <<'EOF'
+## CRITICAL: Pre-Compaction Session Summary
+
+Context compaction is about to happen. You are about to lose most of your conversation history. You MUST store a comprehensive session summary NOW using the mem0 `add_memory` tool.
+
+### Step 1: Store session summary
+
+Call `add_memory` with a thorough summary covering ALL of the following:
+
+```
+## Session Summary (Pre-Compaction)
+
+### User's Goal
+[What the user originally asked for and their intent]
+
+### What Was Accomplished
+[Numbered list of tasks completed, features built, bugs fixed]
+
+### Key Decisions Made
+[Architectural choices, design decisions, trade-offs discussed]
+
+### Files Created or Modified
+[List of important file paths with what changed in each]
+
+### Current State
+[What is in progress RIGHT NOW — the task you were in the middle of]
+[Any pending items, blockers, or next steps]
+
+### Important Context
+[User preferences observed, coding patterns, anything that would help
+the post-compaction agent continue without asking redundant questions]
+```
+
+Include metadata: `{"type": "session_state", "source": "pre-compaction"}`
+
+### Step 2: Store any unstored learnings
+
+If there are learnings from this session that you haven't stored yet, store them as separate memories:
+- Failed approaches -> metadata `{"type": "anti_pattern"}`
+- Successful strategies -> metadata `{"type": "task_learning"}`
+- Architecture decisions -> metadata `{"type": "decision"}`
+
+### Step 3: Acknowledge
+
+After storing, briefly tell the user that session state has been saved and you're ready for compaction.
+
+Do this NOW. Do not skip any section. The quality of this summary directly determines whether you can continue the user's task after compaction.
+EOF
+
+exit 0
diff --git a/mem0-plugin/scripts/on_session_start.sh b/mem0-plugin/scripts/on_session_start.sh
new file mode 100755
index 000000000..353a17130
--- /dev/null
+++ b/mem0-plugin/scripts/on_session_start.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+# Hook: SessionStart (matcher: startup|resume|compact)
+#
+# Bootstraps mem0 context at the start of every session.
+# Output becomes part of Claude's context so it calls mem0 MCP tools.
+#
+# Input: JSON on stdin with session_id, source, transcript_path, model, cwd
+# Output: Text injected into Claude's context (exit 0)
+
+# Intentionally omit -e so the script always outputs a bootstrap prompt
+# even if jq is missing or stdin is malformed.
+set -uo pipefail
+
+INPUT=$(cat)
+SOURCE=$(echo "$INPUT" | jq -r '.source // "startup"' 2>/dev/null || echo "startup")
+
+if [ "$SOURCE" = "startup" ]; then
+ cat <<'EOF'
+## Mem0 Session Bootstrap
+
+You have access to persistent memory via the mem0 MCP tools. Before doing anything else:
+
+1. Call `search_memories` with a query related to the current project or user request to load relevant context.
+2. Review the returned memories to understand what has been learned in prior sessions.
+3. If appropriate, call `get_memories` to browse all stored memories for this user.
+
+IMPORTANT: Do NOT skip this step. Always bootstrap context first.
+EOF
+
+elif [ "$SOURCE" = "resume" ]; then
+ cat <<'EOF'
+## Mem0 Session Resumed
+
+This is a resumed session. Your prior context is already loaded. Before continuing:
+
+1. Call `search_memories` with a query related to the current task to refresh relevant memories.
+2. If significant time has passed, search for recent project-wide updates.
+
+Continue where you left off.
+EOF
+
+elif [ "$SOURCE" = "compact" ]; then
+ cat <<'EOF'
+## Mem0 Post-Compaction Recovery
+
+Context was just compacted. You may have lost important session context.
+
+1. Call `search_memories` with queries related to what you were working on to reload relevant knowledge.
+2. Check for any session state memories that were saved before compaction.
+3. Continue working based on the recovered context.
+EOF
+fi
+
+exit 0
diff --git a/mem0-plugin/scripts/on_stop.sh b/mem0-plugin/scripts/on_stop.sh
new file mode 100755
index 000000000..5dd088f69
--- /dev/null
+++ b/mem0-plugin/scripts/on_stop.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# Hook: Stop
+#
+# Fires when Claude finishes responding.
+# Reminds Claude to store any unsaved learnings, then spawns a background
+# process to capture transcript state via the Mem0 REST API directly.
+#
+# Input: JSON on stdin with stop_hook_active, transcript_path, cwd
+# Output: Text that becomes Claude's context (exit 0), or nothing
+#
+# IMPORTANT: Check stop_hook_active to avoid infinite loops.
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+
+INPUT=$(cat)
+STOP_HOOK_ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false' 2>/dev/null || echo "false")
+
+if [ "$STOP_HOOK_ACTIVE" = "true" ]; then
+ exit 0
+fi
+
+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
+
+# Capture transcript state in the background via Mem0 REST API
+echo "$INPUT" | python3 "$SCRIPT_DIR/on_pre_compact.py" --source=session-end 2>/dev/null &
+
+exit 0
diff --git a/mem0-plugin/scripts/on_task_completed.sh b/mem0-plugin/scripts/on_task_completed.sh
new file mode 100755
index 000000000..befc1b34a
--- /dev/null
+++ b/mem0-plugin/scripts/on_task_completed.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+# Hook: TaskCompleted
+#
+# Fires when a task is marked as completed. Reminds Claude to extract
+# and store learnings via the mem0 MCP tools.
+#
+# Input: JSON on stdin with task_id, task_subject, task_description
+# Output: Text that becomes feedback to the model (exit 0)
+
+set -euo pipefail
+
+INPUT=$(cat)
+TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject // "unknown task"' 2>/dev/null || echo "unknown task")
+
+cat < Store with metadata \`{"type": "task_learning"}\`
+2. Were there failed approaches before finding the solution? -> Store with metadata \`{"type": "anti_pattern"}\`
+3. Were there architectural decisions? -> Store with metadata \`{"type": "decision"}\`
+4. Any new conventions or patterns established? -> Store with metadata \`{"type": "convention"}\`
+
+Memories can be as detailed as needed — include full context, reasoning, code snippets, and examples.
+Only store genuinely useful learnings — skip if the task was trivial.
+EOF
+
+exit 0
diff --git a/mem0-plugin/scripts/on_user_prompt.sh b/mem0-plugin/scripts/on_user_prompt.sh
new file mode 100755
index 000000000..398ec7456
--- /dev/null
+++ b/mem0-plugin/scripts/on_user_prompt.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+# Hook: UserPromptSubmit
+#
+# Fires on every user message. Searches mem0 for relevant memories
+# and injects them into Claude's context before processing.
+#
+# Input: JSON on stdin with prompt, session_id, cwd, transcript_path
+# Output: Matching memories as context text (exit 0)
+#
+# Skips search for very short prompts (< 20 chars) and when
+# MEM0_API_KEY is not set. Uses a 3s timeout to minimize latency.
+
+# Intentionally omit -e so the script always exits 0 even if
+# curl or jq fail — must never block the user's prompt.
+set -uo pipefail
+
+INPUT=$(cat)
+PROMPT=$(echo "$INPUT" | jq -r '.prompt // ""' 2>/dev/null || echo "")
+
+# Skip trivial prompts — not worth a network call
+if [ ${#PROMPT} -lt 20 ]; then
+ exit 0
+fi
+
+API_KEY="${MEM0_API_KEY:-}"
+if [ -z "$API_KEY" ]; then
+ exit 0
+fi
+
+USER_ID="${MEM0_USER_ID:-${USER:-default}}"
+
+# Build request body safely via jq to avoid injection
+BODY=$(jq -n --arg query "$PROMPT" --arg user_id "$USER_ID" \
+ '{query: $query, filters: {user_id: $user_id}, top_k: 5}')
+
+# Search mem0 for memories relevant to this prompt
+RESPONSE=$(curl -s --max-time 3 \
+ -X POST "https://api.mem0.ai/v2/memories/search/" \
+ -H "Authorization: Token $API_KEY" \
+ -H "Content-Type: application/json" \
+ -d "$BODY" \
+ 2>/dev/null || echo "")
+
+if [ -z "$RESPONSE" ]; then
+ exit 0
+fi
+
+# Extract memories from response (API returns a flat array)
+MEMORIES=$(echo "$RESPONSE" | jq -r '
+ if type == "array" then . else .results // [] end |
+ if length == 0 then empty else
+ "## Relevant memories from mem0\n\n" +
+ (map(select(.memory != null) | "- " + .memory) | join("\n"))
+ end
+' 2>/dev/null || echo "")
+
+if [ -n "$MEMORIES" ]; then
+ echo "$MEMORIES"
+fi
+
+exit 0
diff --git a/mem0-plugin/skills/mem0/LICENSE b/mem0-plugin/skills/mem0/LICENSE
new file mode 100644
index 000000000..78c99ae28
--- /dev/null
+++ b/mem0-plugin/skills/mem0/LICENSE
@@ -0,0 +1,189 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but not
+ limited to compiled object code, generated documentation, and
+ conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work.
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to the Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by the Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding any notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ Copyright 2024 Mem0.ai
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/mem0-plugin/skills/mem0/README.md b/mem0-plugin/skills/mem0/README.md
new file mode 100644
index 000000000..f1cb13806
--- /dev/null
+++ b/mem0-plugin/skills/mem0/README.md
@@ -0,0 +1,73 @@
+# Mem0 Skill for Claude
+
+Add persistent memory to any AI application in minutes using [Mem0 Platform](https://app.mem0.ai).
+
+## What This Skill Does
+
+When installed, Claude can:
+
+- **Set up Mem0** in your Python or TypeScript project
+- **Integrate memory** into your existing AI app (LangChain, CrewAI, Vercel AI, OpenAI Agents, LangGraph, LlamaIndex, etc.)
+- **Generate working code** using real API references and tested patterns
+- **Search live docs** on demand for the latest Mem0 documentation
+
+## Installation
+
+This skill is included automatically when you install the Mem0 plugin:
+
+```
+/plugin marketplace add mem0ai/mem0
+/plugin install mem0@mem0-plugins
+```
+
+See the [plugin README](../../README.md) for full setup instructions.
+
+### Prerequisites
+
+- A Mem0 Platform API key ([Get one here](https://app.mem0.ai/dashboard/api-keys))
+- Python 3.10+ or Node.js 18+
+- Set the environment variable:
+
+ ```bash
+ export MEM0_API_KEY="m0-your-api-key"
+ ```
+
+## Quick Start
+
+After installing, just ask Claude:
+
+- "Set up mem0 in my project"
+- "Add memory to my chatbot"
+- "Help me search user memories with filters"
+- "Integrate mem0 with my LangChain app"
+- "Add graph memory to track entity relationships"
+
+## What's Inside
+
+```text
+skills/mem0/
+├── SKILL.md # Skill definition and instructions
+├── README.md # This file
+├── LICENSE # Apache-2.0
+├── scripts/
+│ └── mem0_doc_search.py # Search live Mem0 docs on demand
+└── references/ # Documentation (loaded on demand)
+ ├── quickstart.md # Full quickstart (Python, TS, cURL)
+ ├── sdk-guide.md # All SDK methods (Python + TypeScript)
+ ├── api-reference.md # REST endpoints, filters, memory object
+ ├── architecture.md # Processing pipeline, lifecycle, scoping, performance
+ ├── features.md # Retrieval, graph, categories, MCP, webhooks, multimodal
+ ├── integration-patterns.md # LangChain, CrewAI, Vercel AI, LangGraph, LlamaIndex, etc.
+ └── use-cases.md # 7 real-world patterns with Python + TypeScript code
+```
+
+## Links
+
+- [Mem0 Platform Dashboard](https://app.mem0.ai)
+- [Mem0 Documentation](https://docs.mem0.ai)
+- [Mem0 GitHub](https://github.com/mem0ai/mem0)
+- [API Reference](https://docs.mem0.ai/api-reference)
+
+## License
+
+Apache-2.0
diff --git a/mem0-plugin/skills/mem0/SKILL.md b/mem0-plugin/skills/mem0/SKILL.md
new file mode 100644
index 000000000..cec1311ce
--- /dev/null
+++ b/mem0-plugin/skills/mem0/SKILL.md
@@ -0,0 +1,156 @@
+---
+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.
+license: Apache-2.0
+metadata:
+ author: mem0ai
+ version: "0.1.0"
+ 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
+---
+
+# 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.
+
+## Step 1: Install and authenticate
+
+**Python:**
+```bash
+pip install mem0ai
+export MEM0_API_KEY="m0-your-api-key"
+```
+
+**TypeScript/JavaScript:**
+```bash
+npm install mem0ai
+export MEM0_API_KEY="m0-your-api-key"
+```
+
+Get an API key at: https://app.mem0.ai/dashboard/api-keys
+
+## Step 2: Initialize the client
+
+**Python:**
+```python
+from mem0 import MemoryClient
+client = MemoryClient(api_key="m0-xxx")
+```
+
+**TypeScript:**
+```typescript
+import MemoryClient from 'mem0ai';
+const client = new MemoryClient({ apiKey: 'm0-xxx' });
+```
+
+For async Python, use `AsyncMemoryClient`.
+
+## Step 3: Core operations
+
+Every Mem0 integration follows the same pattern: **retrieve → generate → store**.
+
+### Add memories
+```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")
+```
+
+### Search memories
+```python
+results = client.search("dietary preferences", user_id="alice")
+for mem in results.get("results", []):
+ print(mem["memory"])
+```
+
+### Get all memories
+```python
+all_memories = client.get_all(user_id="alice")
+```
+
+### Update a memory
+```python
+client.update("memory-uuid", text="Updated: vegetarian, nut allergy, prefers organic")
+```
+
+### Delete a memory
+```python
+client.delete("memory-uuid")
+client.delete_all(user_id="alice") # delete all for a user
+```
+
+## Common integration pattern
+
+```python
+from mem0 import MemoryClient
+from openai import OpenAI
+
+mem0 = MemoryClient()
+openai = OpenAI()
+
+def chat(user_input: str, user_id: str) -> str:
+ # 1. Retrieve relevant memories
+ memories = mem0.search(user_input, 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",
+ messages=[
+ {"role": "system", "content": f"User context:\n{context}"},
+ {"role": "user", "content": user_input},
+ ]
+ )
+ reply = response.choices[0].message.content
+
+ # 3. Store interaction for future context
+ mem0.add(
+ [{"role": "user", "content": user_input}, {"role": "assistant", "content": reply}],
+ user_id=user_id
+ )
+ return reply
+```
+
+## Common edge cases
+
+- **Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_id` matches exactly (case-sensitive).
+- **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.
+
+## Live documentation search
+
+For the latest docs beyond what's in the references, use the doc search tool:
+
+```bash
+python ${CLAUDE_SKILL_DIR}/scripts/mem0_doc_search.py --query "topic"
+python ${CLAUDE_SKILL_DIR}/scripts/mem0_doc_search.py --page "/platform/features/graph-memory"
+python ${CLAUDE_SKILL_DIR}/scripts/mem0_doc_search.py --index
+```
+
+No API key needed — searches docs.mem0.ai directly.
+
+## References
+
+Load these on demand for deeper detail:
+
+| Topic | File |
+|-------|------|
+| Quickstart (Python, TS, cURL) | [references/quickstart.md](references/quickstart.md) |
+| SDK guide (all methods, both languages) | [references/sdk-guide.md](references/sdk-guide.md) |
+| 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) |
+| Use cases & examples (real-world patterns with code) | [references/use-cases.md](references/use-cases.md) |
diff --git a/mem0-plugin/skills/mem0/references/api-reference.md b/mem0-plugin/skills/mem0/references/api-reference.md
new file mode 100644
index 000000000..e9fd20f24
--- /dev/null
+++ b/mem0-plugin/skills/mem0/references/api-reference.md
@@ -0,0 +1,140 @@
+# Mem0 Platform API Reference
+
+REST API endpoints for the Mem0 Platform. Base URL: `https://api.mem0.ai`
+
+All endpoints require: `Authorization: Token `
+
+## Endpoints
+
+| Operation | Method | URL |
+|-----------|--------|-----|
+| Add Memories | `POST` | `/v1/memories/` |
+| Search Memories | `POST` | `/v2/memories/search/` |
+| Get All Memories | `POST` | `/v2/memories/` |
+| Get Single Memory | `GET` | `/v1/memories/{memory_id}/` |
+| Update Memory | `PUT` | `/v1/memories/{memory_id}/` |
+| Delete Memory | `DELETE` | `/v1/memories/{memory_id}/` |
+
+## Memory Object Structure
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `id` | string (UUID) | Unique memory identifier |
+| `memory` | string | Text content of the memory |
+| `user_id` | string | Associated user |
+| `agent_id` | string (nullable) | Agent identifier |
+| `app_id` | string (nullable) | Application identifier |
+| `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 |
+
+Search results additionally include `score` (relevance metric).
+
+## Scoping Identifiers
+
+Memories can be scoped to different levels:
+
+| Scope | Parameter | Use Case |
+|-------|-----------|----------|
+| User | `user_id` | Per-user memory isolation |
+| Agent | `agent_id` | Per-agent memory partitioning |
+| Application | `app_id` | Cross-agent app-level memory |
+| Run/Session | `run_id` | Session-scoped temporary memory |
+
+**Critical:** Combining `user_id` and `agent_id` in a single AND filter yields empty results. Entities are stored separately. Use `OR` logic or separate queries.
+
+## 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
+
+## Filter System
+
+Filters use nested JSON with a logical operator at the root:
+
+```json
+{
+ "AND": [
+ {"user_id": "alice"},
+ {"categories": {"contains": "finance"}},
+ {"created_at": {"gte": "2024-01-01"}}
+ ]
+}
+```
+
+Root must be `AND`, `OR`, or `NOT`. Simple shorthand `{"user_id": "alice"}` also works.
+
+### Supported Operators
+
+| Operator | Description |
+|----------|-------------|
+| `eq` | Equal to (default) |
+| `ne` | Not equal to |
+| `in` | Matches any value in array |
+| `gt`, `gte` | Greater than / greater than or equal |
+| `lt`, `lte` | Less than / less than or equal |
+| `contains` | Case-sensitive containment |
+| `icontains` | Case-insensitive containment |
+| `*` | Wildcard -- matches any non-null value |
+
+### Filterable Fields
+
+| Field | Valid Operators |
+|-------|-----------------|
+| `user_id`, `agent_id`, `app_id`, `run_id` | `eq`, `ne`, `in`, `*` |
+| `created_at`, `updated_at`, `timestamp` | `gt`, `gte`, `lt`, `lte`, `eq`, `ne` |
+| `categories` | `eq`, `ne`, `in`, `contains` |
+| `metadata` | `eq`, `ne`, `contains` (top-level keys only) |
+| `keywords` | `contains`, `icontains` |
+| `memory_ids` | `in` |
+
+### Filter Constraints
+
+1. **Entity scope partitioning:** `user_id` AND `agent_id` in one `AND` block yields empty results.
+2. **Metadata limitations:** Only top-level keys. Only `eq`, `contains`, `ne`. No `in` or `gt`.
+3. **Operator syntax:** Use `gte`, `lt`, `ne`. SQL-style (`>=`, `!=`) rejected.
+4. **Entity filter required for get-all:** At least one of `user_id`, `agent_id`, `app_id`, or `run_id`.
+5. **Wildcard excludes null:** `*` matches only non-null values.
+6. **Date format:** ISO 8601 (`YYYY-MM-DDTHH:MM:SSZ`). Timezone-naive defaults to UTC.
+
+## Response Formats
+
+### Add Response
+
+```json
+[
+ {
+ "id": "mem_01JF8ZS4Y0R0SPM13R5R6H32CJ",
+ "event": "ADD",
+ "data": { "memory": "The user moved to Austin in 2025." }
+ }
+]
+```
+
+Event types: `ADD`, `UPDATE`, `DELETE`. A single add can trigger multiple events.
+
+### Search Response
+
+```json
+{
+ "results": [
+ {
+ "id": "ea925981-...",
+ "memory": "Is a vegetarian and allergic to nuts.",
+ "user_id": "user123",
+ "categories": ["food", "health"],
+ "score": 0.89,
+ "created_at": "2024-07-26T10:29:36.630547-07:00"
+ }
+ ]
+}
+```
+
+With `enable_graph=true`, includes additional `relations` array with entity relationships.
diff --git a/mem0-plugin/skills/mem0/references/architecture.md b/mem0-plugin/skills/mem0/references/architecture.md
new file mode 100644
index 000000000..f0c5c1bc8
--- /dev/null
+++ b/mem0-plugin/skills/mem0/references/architecture.md
@@ -0,0 +1,386 @@
+# Mem0 Platform Architecture
+
+How Mem0 processes, stores, and retrieves memories under the hood.
+
+## Table of Contents
+
+- [Core Concept](#core-concept)
+- [Memory Processing Pipeline](#memory-processing-pipeline)
+- [Retrieval Pipeline](#retrieval-pipeline)
+- [Memory Lifecycle](#memory-lifecycle)
+- [Memory Object Structure](#memory-object-structure)
+- [Scoping & Multi-Tenancy](#scoping--multi-tenancy)
+- [Memory Layers](#memory-layers)
+- [Performance Characteristics](#performance-characteristics)
+
+---
+
+## Core Concept
+
+Mem0 is a managed memory layer that sits between your AI application and users. Every integration follows the same 3-step loop:
+
+```
+User Input → Retrieve relevant memories → Enrich LLM prompt → Generate response → Store new memories
+```
+
+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:**
+- **Vector store**: Embeddings for semantic similarity search
+- **Graph store** (optional): Entity nodes and relationship edges for structured knowledge
+
+---
+
+## Memory Processing Pipeline
+
+### What happens when you call `client.add()`
+
+```
+Messages In
+ │
+ ▼
+┌─────────────────────┐
+│ 1. EXTRACTION │ LLM analyzes messages, extracts key 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
+└─────────┬───────────┘
+ │
+ ▼
+┌─────────────────────┐
+│ 3. STORAGE │ Generates embeddings → vector store
+│ │ Optional: entity extraction → graph store
+│ │ Indexes metadata, categories, timestamps
+└─────────┬───────────┘
+ │
+ ▼
+ Memory Object
+ (id, memory, categories, structured_attributes)
+```
+
+### Processing modes
+
+**Async (default, `async_mode=True`):**
+- API returns immediately: `{"status": "PENDING", "event_id": "..."}`
+- Processing happens in background
+- 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
+
+**Inferred (`infer=True`, default):**
+- LLM extracts structured facts from conversation
+- Conflict resolution deduplicates and resolves contradictions
+- Best for: natural conversation → memory
+
+**Raw (`infer=False`):**
+- Stores text exactly as provided, no LLM processing
+- Skips conflict resolution — same fact can be stored twice
+- Only `user` role messages are stored; `assistant` messages ignored
+- Best for: bulk imports, pre-structured data, migrations
+
+**Warning:** Don't mix `infer=True` and `infer=False` for the same data — the same fact will be stored twice.
+
+---
+
+## Retrieval Pipeline
+
+### What happens when you call `client.search()`
+
+```
+Query In
+ │
+ ▼
+┌─────────────────────┐
+│ 1. QUERY EMBEDDING │ Convert query to vector representation
+└─────────┬───────────┘
+ │
+ ▼
+┌─────────────────────┐
+│ 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
+└─────────┬───────────┘
+ │
+ ▼
+ Results + Relations
+```
+
+### Retrieval enhancement combinations
+
+| 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 |
+
+### 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.
+
+To include memories with non-null fields, use explicit filters:
+```python
+# Gets memories for alice regardless of agent/app/run
+filters={"OR": [{"user_id": "alice"}]}
+```
+
+---
+
+## Memory Lifecycle
+
+```
+CREATE ──→ ACTIVE ──→ UPDATE ──→ ACTIVE
+ │ │ │
+ │ ▼ ▼
+ │ EXPIRED EXPIRED
+ │ (still stored, (still stored,
+ │ not retrieved) not retrieved)
+ │ │ │
+ ▼ ▼ ▼
+DELETE DELETE DELETE
+(permanent)
+```
+
+### 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`
+
+### 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)
+
+### 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
+
+---
+
+## Memory Object Structure
+
+```json
+{
+ "id": "uuid-string",
+ "memory": "Extracted memory text",
+ "user_id": "user-identifier",
+ "agent_id": null,
+ "app_id": null,
+ "run_id": null,
+ "metadata": { "source": "chat", "priority": "high" },
+ "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,
+ "day_of_week": "wednesday",
+ "is_weekend": false,
+ "quarter": 1, "week_of_year": 11
+ },
+ "score": 0.85
+}
+```
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `id` | UUID | Unique identifier, used for update/delete |
+| `memory` | string | Extracted or stored text content |
+| `user_id` | string | Primary entity scope |
+| `agent_id` | string | Agent scope |
+| `app_id` | string | Application scope |
+| `run_id` | string | Session/run scope |
+| `metadata` | object | Custom key-value pairs for filtering |
+| `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) |
+
+---
+
+## Scoping & Multi-Tenancy
+
+Mem0 separates memories across four dimensions to prevent data mixing:
+
+| Dimension | Field | Purpose | Example |
+|-----------|-------|---------|---------|
+| User | `user_id` | Persistent persona or account | `"customer_6412"` |
+| Agent | `agent_id` | Distinct agent or tool | `"meal_planner"` |
+| App | `app_id` | Product surface or deployment | `"ios_retail_app"` |
+| Session | `run_id` | Short-lived flow or thread | `"ticket-9241"` |
+
+### Storage model
+
+Each entity combination creates separate records. A memory with `user_id="alice"` is stored separately from one with `user_id="alice"` + `agent_id="bot"`.
+
+### Critical: cross-entity queries
+
+```python
+# This returns NOTHING — user and agent memories are stored separately
+filters={"AND": [{"user_id": "alice"}, {"agent_id": "bot"}]}
+
+# Use OR to query multiple scopes
+filters={"OR": [{"user_id": "alice"}, {"agent_id": "bot"}]}
+
+# Use wildcard to include any non-null value
+filters={"AND": [{"user_id": "*"}]} # All users (excludes null)
+```
+
+### Recommended scoping patterns
+
+```python
+# User-level: persistent preferences
+client.add(messages, user_id="alice")
+
+# Session-level: temporary context
+client.add(messages, user_id="alice", run_id="session_123")
+# Clean up when done: client.delete_all(run_id="session_123")
+
+# Agent-level: agent-specific knowledge
+client.add(messages, agent_id="support_bot", app_id="helpdesk")
+
+# Multi-tenant: full isolation
+client.add(messages, user_id="alice", agent_id="bot", app_id="acme_corp", run_id="ticket_42")
+```
+
+---
+
+## Memory Layers
+
+Mem0 supports three layers of memory, from shortest to longest lived:
+
+### Conversation memory
+- In-flight messages within a single turn
+- Tool calls, chain-of-thought reasoning
+- **Lifetime:** Single response — lost after turn finishes
+- **Managed by:** Your application, not Mem0
+
+### Session memory
+- Short-lived facts for current task or channel
+- Multi-step flows (onboarding, debugging, support tickets)
+- **Lifetime:** Minutes to hours
+- **Managed by:** Mem0 via `run_id` parameter
+- Clean up with `client.delete_all(run_id="session_id")`
+
+### User memory
+- Long-lived knowledge tied to a person or account
+- Personal preferences, account state, compliance details
+- **Lifetime:** Weeks to forever
+- **Managed by:** Mem0 via `user_id` parameter
+- Persists across all sessions and interactions
+
+### How layering works in practice
+
+```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)
+
+ # 2. Retrieve session memories (current task context)
+ session_mems = mem0.search(user_input, filters={
+ "AND": [{"user_id": user_id}, {"run_id": session_id}]
+ })
+
+ # 3. Combine both layers for LLM context
+ context = format_memories(user_mems) + format_memories(session_mems)
+
+ # 4. Generate response
+ response = llm.generate(context=context, input=user_input)
+
+ # 5. Store in session scope (temporary) + user scope (persistent)
+ messages = [{"role": "user", "content": user_input}, {"role": "assistant", "content": response}]
+ mem0.add(messages, user_id=user_id, run_id=session_id)
+
+ return response
+```
+
+---
+
+## Performance Characteristics
+
+### Latency
+
+| Operation | Typical Latency |
+|-----------|----------------|
+| Base vector search | ~100ms |
+| + keyword_search | +10ms |
+| + 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 |
+
+### Processing
+
+- **Async mode (default):** Returns immediately, processes in background
+- **Sync mode:** Waits for full extraction + storage pipeline
+- **Batch operations:** Up to 1000 memories per batch_update/batch_delete
+- **Webhooks:** Real-time notifications when async processing completes
+
+### Scoping strategy for performance
+
+- Use `user_id` for all user-facing queries (most common, fastest)
+- Add `run_id` for session isolation (narrows search space)
+- Avoid wildcard `"*"` filters on large datasets (scans all non-null records)
+- Use `top_k` to limit result count when you only need a few memories
+
+---
+
+## Comparison with Alternatives
+
+| Approach | Pros | Cons |
+|----------|------|------|
+| **Raw vector DB** | Fast, full control | No extraction, no dedup, no conflict resolution |
+| **In-memory chat history** | Zero latency | Lost on restart, no cross-session, grows unbounded |
+| **RAG over documents** | Good for static knowledge | No personalization, no memory updates |
+| **Mem0 Platform** | Managed extraction + dedup + graph + scoping | External dependency, async processing delay |
+
+Mem0 combines the best of vector search (semantic retrieval) with automatic extraction (LLM-powered), conflict resolution (deduplication), and structured scoping (multi-tenancy) — in a single managed API.
diff --git a/mem0-plugin/skills/mem0/references/features.md b/mem0-plugin/skills/mem0/references/features.md
new file mode 100644
index 000000000..fa2130f47
--- /dev/null
+++ b/mem0-plugin/skills/mem0/references/features.md
@@ -0,0 +1,496 @@
+# Platform Features -- Mem0 Platform
+
+Additional platform capabilities beyond core CRUD operations.
+
+## Table of Contents
+
+- [Advanced Retrieval](#advanced-retrieval)
+- [Graph Memory](#graph-memory)
+- [Custom Categories](#custom-categories)
+- [Custom Instructions](#custom-instructions)
+- [Criteria Retrieval](#criteria-retrieval)
+- [Feedback Mechanism](#feedback-mechanism)
+- [Memory Export](#memory-export)
+- [Group Chat](#group-chat)
+- [MCP Integration](#mcp-integration)
+- [Webhooks](#webhooks)
+- [Multimodal Support](#multimodal-support)
+
+## Advanced Retrieval
+
+Three enhancement options for tuning search precision, recall, and latency.
+
+### Keyword Search (`keyword_search=True`)
+
+Expands results to include memories with specific terms, names, and technical keywords.
+
+- Latency: +10ms
+- Recall: Significantly increased
+- Best for: entity-heavy queries, comprehensive coverage
+
+### Reranking (`rerank=True`)
+
+Deep semantic reordering of results — most relevant first.
+
+- Latency: +150-200ms
+- Accuracy: Significantly improved
+- 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")
+```
+
+**TypeScript:**
+```typescript
+const results = await client.search(query, {
+ user_id: 'user123',
+ keyword_search: true,
+ rerank: true,
+});
+```
+
+---
+
+## Graph Memory
+
+Entity-level knowledge graph that creates relationships between 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
+
+Graph relations **augment** vector results without reordering them. Vector similarity always determines hit sequence.
+
+### Enabling Graph Memory
+
+**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)
+```
+
+**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
+
+---
+
+## Custom Categories
+
+Replace Mem0's default 15 labels with domain-specific categories. The system automatically tags memories to the closest matching category.
+
+### Default Categories (15)
+
+`personal_details`, `family`, `professional_details`, `sports`, `travel`, `food`, `music`, `health`, `technology`, `hobbies`, `fashion`, `entertainment`, `milestones`, `user_preferences`, `misc`
+
+### Configuration
+
+**Set project-level categories:**
+```python
+new_categories = [
+ {"lifestyle_management": "Tracks daily routines, habits, wellness activities"},
+ {"seeking_structure": "Documents goals around creating routines and systems"},
+ {"personal_information": "Basic information about the user"}
+]
+client.project.update(custom_categories=new_categories)
+```
+
+```javascript
+await client.updateProject({ custom_categories: new_categories });
+```
+
+**Retrieve active categories:**
+```python
+categories = client.project.get(fields=["custom_categories"])
+```
+
+### Key Constraint
+
+Per-request overrides (`custom_categories=...` on `client.add`) are **not supported** on the managed API. Only project-level configuration works. Workaround: store ad-hoc labels in `metadata` field.
+
+---
+
+## Custom Instructions
+
+Natural language filters that control what information Mem0 extracts when creating memories.
+
+### Set Instructions
+
+```python
+client.project.update(custom_instructions="Your guidelines here...")
+```
+
+```javascript
+await client.updateProject({ custom_instructions: "Your guidelines here..." });
+```
+
+### Template Structure
+
+1. **Task Description** -- brief extraction overview
+2. **Information Categories** -- numbered sections with specific details to capture
+3. **Processing Guidelines** -- quality and handling rules
+4. **Exclusion List** -- sensitive/irrelevant data to filter out
+
+### Domain Examples
+
+**E-commerce:** Capture product issues, preferences, service experience; exclude payment data.
+
+**Education:** Extract learning progress, student preferences, performance patterns; exclude specific grades.
+
+**Finance:** Track financial goals, life events, investment interests; exclude account numbers and SSNs.
+
+### Best Practices
+
+- Start simply, test with sample messages, iterate based on results
+- Avoid overly lengthy instructions
+- Be specific about what to include AND exclude
+
+---
+
+## Criteria Retrieval
+
+Custom attribute-based memory ranking using LLM-evaluated criteria with weights. Goes beyond semantic similarity to prioritize memories based on domain-specific signals.
+
+### Configuration
+
+```python
+# Define criteria at project level
+retrieval_criteria = [
+ {"name": "joy", "description": "Positive emotions like happiness and excitement", "weight": 3},
+ {"name": "curiosity", "description": "Inquisitiveness and desire to learn", "weight": 2},
+ {"name": "urgency", "description": "Time-sensitive or high-priority items", "weight": 4},
+]
+client.project.update(retrieval_criteria=retrieval_criteria)
+```
+
+```typescript
+await client.updateProject({
+ retrieval_criteria: [
+ { name: 'joy', description: 'Positive emotions', weight: 3 },
+ { name: 'urgency', description: 'Time-sensitive items', weight: 4 },
+ ],
+});
+```
+
+### Usage
+
+Once configured, `client.search()` automatically applies criteria ranking:
+
+```python
+# Criteria-weighted results returned automatically
+results = client.search("Why am I feeling happy?", filters={"user_id": "alice"})
+```
+
+**Best for:** Wellness assistants, tutoring platforms, productivity tools — any app needing intent-aware retrieval.
+
+---
+
+## Feedback Mechanism
+
+Provide feedback on extracted memories to improve system quality over time.
+
+### Feedback Types
+
+| Type | Meaning |
+|------|---------|
+| `POSITIVE` | Memory is useful and accurate |
+| `NEGATIVE` | Memory is not useful |
+| `VERY_NEGATIVE` | Memory is harmful or completely wrong |
+| `None` | Clear existing feedback |
+
+### Usage
+
+**Python:**
+```python
+client.feedback(
+ memory_id="mem-123",
+ feedback="POSITIVE",
+ feedback_reason="Accurately captured dietary preference"
+)
+
+# Bulk feedback
+for item in feedback_data:
+ client.feedback(**item)
+```
+
+**TypeScript:**
+```typescript
+await client.feedback('mem-123', {
+ feedback: 'POSITIVE',
+ feedback_reason: 'Accurately captured dietary preference',
+});
+```
+
+---
+
+## Memory Export
+
+Create structured exports of memories using customizable schemas with filters.
+
+### Usage
+
+```python
+import json
+
+# Define export schema
+schema = {
+ "type": "object",
+ "properties": {
+ "name": {"type": "string"},
+ "preferences": {"type": "array", "items": {"type": "string"}},
+ "health_info": {"type": "string"},
+ }
+}
+
+# Create export
+response = client.create_memory_export(
+ schema=json.dumps(schema),
+ filters={"user_id": "alice"},
+ export_instructions="Create comprehensive profile based on all memories"
+)
+
+# Retrieve export (may take a moment to process)
+result = client.get_memory_export(memory_export_id=response["id"])
+```
+
+**Best for:** Data analytics, user profile generation, compliance audits, CRM sync.
+
+---
+
+## Group Chat
+
+Process multi-participant conversations and automatically attribute memories to individual speakers.
+
+### Usage
+
+```python
+messages = [
+ {"role": "user", "name": "Alice", "content": "I think we should use React for the frontend"},
+ {"role": "user", "name": "Bob", "content": "I prefer Vue.js, it's simpler for our use case"},
+ {"role": "assistant", "content": "Both are great choices. Let me note your preferences."},
+]
+
+# Mem0 automatically attributes memories to each speaker
+response = client.add(messages, run_id="team_meeting_1")
+
+# Retrieve Alice's memories from that session
+alice_mems = client.get_all(
+ filters={"AND": [{"user_id": "alice"}, {"run_id": "team_meeting_1"}]}
+)
+```
+
+Use the `name` field in messages to identify speakers. Mem0 maps names to entity scopes automatically.
+
+---
+
+## MCP Integration
+
+Model Context Protocol integration enables AI clients (Claude Desktop, Cursor, custom agents) to manage Mem0 memory autonomously.
+
+### Configuration
+
+```json
+{
+ "mcpServers": {
+ "mem0": {
+ "command": "uvx",
+ "args": ["mem0-mcp-server"],
+ "env": {
+ "MEM0_API_KEY": "m0-your-api-key",
+ "MEM0_DEFAULT_USER_ID": "your-user-id"
+ }
+ }
+ }
+}
+```
+
+### Available MCP Tools
+
+The MCP server exposes 9 memory tools that AI agents can use autonomously:
+- Add, search, get, update, delete memories
+- Get history, list users, delete users
+- Search Mem0 documentation
+
+### How It Works
+
+1. Configure the MCP server in your AI client
+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
+
+**Best for:** Universal AI client integration — one protocol works everywhere.
+
+---
+
+## Webhooks
+
+Real-time event notifications for memory operations.
+
+### Supported Events
+
+| Event | Trigger |
+|-------|---------|
+| `memory_add` | Memory created |
+| `memory_update` | Memory modified |
+| `memory_delete` | Memory removed |
+| `memory_categorize` | Memory tagged |
+
+### Create Webhook
+
+Note: `project_id` here refers to the Mem0 dashboard project scope for webhooks — not the deprecated client init parameter.
+
+```python
+webhook = client.create_webhook(
+ url="https://your-app.com/webhook",
+ name="Memory Logger",
+ project_id="proj_123",
+ event_types=["memory_add", "memory_categorize"]
+)
+```
+
+### Manage Webhooks
+
+```python
+# Retrieve
+webhooks = client.get_webhooks(project_id="proj_123")
+
+# Update
+client.update_webhook(
+ name="Updated Logger",
+ url="https://your-app.com/new-webhook",
+ event_types=["memory_update", "memory_add"],
+ webhook_id="wh_123"
+)
+
+# Delete
+client.delete_webhook(webhook_id="wh_123")
+```
+
+### Payload Structure
+
+Memory events contain: ID, data object with memory content, event type (`ADD`/`UPDATE`/`DELETE`).
+Categorization events contain: memory ID, event type (`CATEGORIZE`), assigned category labels.
+
+---
+
+## Multimodal Support
+
+Mem0 can process images and documents alongside text.
+
+### Supported Media Types
+
+- Images: JPG, PNG
+- Documents: MDX, TXT, PDF
+
+### Image via URL
+
+```python
+image_message = {
+ "role": "user",
+ "content": {
+ "type": "image_url",
+ "image_url": {"url": "https://example.com/image.jpg"}
+ }
+}
+client.add([image_message], user_id="alice")
+```
+
+### Image via Base64
+
+```python
+import base64
+with open("photo.jpg", "rb") as f:
+ base64_image = base64.b64encode(f.read()).decode("utf-8")
+
+image_message = {
+ "role": "user",
+ "content": {
+ "type": "image_url",
+ "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}
+ }
+}
+client.add([image_message], user_id="alice")
+```
+
+### Document (MDX/TXT)
+
+```python
+doc_message = {
+ "role": "user",
+ "content": {"type": "mdx_url", "mdx_url": {"url": document_url}}
+}
+client.add([doc_message], user_id="alice")
+```
+
+### PDF Document
+
+```python
+pdf_message = {
+ "role": "user",
+ "content": {"type": "pdf_url", "pdf_url": {"url": pdf_url}}
+}
+client.add([pdf_message], user_id="alice")
+```
diff --git a/mem0-plugin/skills/mem0/references/integration-patterns.md b/mem0-plugin/skills/mem0/references/integration-patterns.md
new file mode 100644
index 000000000..e00d07ba7
--- /dev/null
+++ b/mem0-plugin/skills/mem0/references/integration-patterns.md
@@ -0,0 +1,444 @@
+# Mem0 Integration Patterns
+
+Working code examples for integrating Mem0 Platform with popular AI frameworks.
+All examples use `MemoryClient` (Platform API key).
+
+Code examples are sourced from official Mem0 integration docs at docs.mem0.ai, simplified for quick reference.
+
+---
+
+## Common Pattern
+
+Every integration follows the same 3-step loop:
+
+1. **Retrieve** -- search relevant memories before generating a response
+2. **Generate** -- include memories as context in the LLM prompt
+3. **Store** -- save the interaction back to Mem0 for future use
+
+---
+
+## LangChain
+
+Source: [docs.mem0.ai/integrations/langchain](https://docs.mem0.ai/integrations/langchain)
+
+```python
+from langchain_openai import ChatOpenAI
+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")
+mem0 = MemoryClient()
+
+prompt = ChatPromptTemplate.from_messages([
+ SystemMessage(content="You are a helpful travel agent AI. Use the provided context to personalize your responses."),
+ MessagesPlaceholder(variable_name="context"),
+ HumanMessage(content="{input}")
+])
+
+def retrieve_context(query: str, user_id: str):
+ """Retrieve relevant memories from Mem0"""
+ memories = mem0.search(query, user_id=user_id)
+ memory_list = memories['results']
+ serialized = ' '.join([m["memory"] for m in memory_list])
+ return [
+ {"role": "system", "content": f"Relevant information: {serialized}"},
+ {"role": "user", "content": query}
+ ]
+
+def chat_turn(user_input: str, user_id: str) -> str:
+ # 1. Retrieve
+ context = retrieve_context(user_input, user_id)
+ # 2. Generate
+ chain = prompt | llm
+ response = chain.invoke({"context": context, "input": user_input})
+ # 3. Store
+ mem0.add(
+ [{"role": "user", "content": user_input}, {"role": "assistant", "content": response.content}],
+ user_id=user_id
+ )
+ return response.content
+```
+
+---
+
+## CrewAI
+
+Source: [docs.mem0.ai/integrations/crewai](https://docs.mem0.ai/integrations/crewai)
+
+CrewAI has native Mem0 integration via `memory_config`:
+
+```python
+from crewai import Agent, Task, Crew, Process
+from mem0 import MemoryClient
+
+client = MemoryClient()
+
+# Store user preferences first
+messages = [
+ {"role": "user", "content": "I am more of a beach person than a mountain person."},
+ {"role": "assistant", "content": "Noted! I'll recommend beach destinations."},
+ {"role": "user", "content": "I like Airbnb more than hotels."},
+]
+client.add(messages, user_id="crew_user_1")
+
+# Create agent
+travel_agent = Agent(
+ role="Personalized Travel Planner",
+ goal="Plan personalized travel itineraries",
+ backstory="You are a seasoned travel planner.",
+ memory=True,
+)
+
+# Create task
+task = Task(
+ description="Find places to live, eat, and visit in San Francisco.",
+ expected_output="A detailed list of places to live, eat, and visit.",
+ agent=travel_agent,
+)
+
+# Setup crew with Mem0 memory
+crew = Crew(
+ agents=[travel_agent],
+ tasks=[task],
+ process=Process.sequential,
+ memory=True,
+ memory_config={
+ "provider": "mem0",
+ "config": {"user_id": "crew_user_1"},
+ }
+)
+
+result = crew.kickoff()
+```
+
+---
+
+## Vercel AI SDK
+
+Source: [docs.mem0.ai/integrations/vercel-ai-sdk](https://docs.mem0.ai/integrations/vercel-ai-sdk)
+
+Install: `npm install @mem0/vercel-ai-provider`
+
+### Basic Text Generation with 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" }),
+ 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`
+
+---
+
+## OpenAI Agents SDK
+
+Source: [docs.mem0.ai/integrations/openai-agents-sdk](https://docs.mem0.ai/integrations/openai-agents-sdk)
+
+```python
+from agents import Agent, Runner, function_tool
+from mem0 import MemoryClient
+
+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)
+ if memories and memories.get('results'):
+ return "\n".join([f"- {mem['memory']}" for mem in memories['results']])
+ return "No relevant memories found."
+
+@function_tool
+def save_memory(content: str, user_id: str) -> str:
+ """Save important information to memory"""
+ mem0.add([{"role": "user", "content": content}], user_id=user_id)
+ return "Information saved to memory."
+
+agent = Agent(
+ name="Personal Assistant",
+ instructions="""You are a helpful personal assistant with memory capabilities.
+ 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"
+)
+
+result = Runner.run_sync(agent, "I love Italian food and I'm planning a trip to Rome next month")
+print(result.final_output)
+```
+
+### Multi-Agent with Handoffs
+
+```python
+from agents import Agent, Runner, function_tool
+
+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"
+)
+
+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"
+)
+
+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"
+)
+
+result = Runner.run_sync(triage_agent, "Plan a healthy meal for my Italy trip")
+```
+
+---
+
+## Pipecat (Voice / Real-Time)
+
+Source: [docs.mem0.ai/integrations/pipecat](https://docs.mem0.ai/integrations/pipecat)
+
+```python
+from pipecat.services.mem0 import Mem0MemoryService
+
+memory = Mem0MemoryService(
+ api_key=os.getenv("MEM0_API_KEY"),
+ user_id="alice",
+ agent_id="voice_bot",
+ params={
+ "search_limit": 10,
+ "search_threshold": 0.1,
+ "system_prompt": "Here are your past memories:",
+ "add_as_system_message": True,
+ }
+)
+
+# Use in pipeline
+pipeline = Pipeline([
+ transport.input(),
+ stt,
+ user_context,
+ memory, # Memory enhances context automatically
+ llm,
+ transport.output(),
+ assistant_context
+])
+```
+
+
+
+---
+
+## LangGraph
+
+Source: [docs.mem0.ai/integrations/langgraph](https://docs.mem0.ai/integrations/langgraph)
+
+State-based agent workflows with memory persistence. Best for complex conversation flows with branching logic.
+
+```python
+from typing import Annotated, TypedDict, List
+from langgraph.graph import StateGraph, START
+from langgraph.graph.message import add_messages
+from langchain_openai import ChatOpenAI
+from mem0 import MemoryClient
+from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
+
+llm = ChatOpenAI(model="gpt-4")
+mem0 = MemoryClient()
+
+class State(TypedDict):
+ messages: Annotated[List[HumanMessage | AIMessage], add_messages]
+ mem0_user_id: str
+
+def chatbot(state: State):
+ messages = state["messages"]
+ user_id = state["mem0_user_id"]
+
+ # Retrieve relevant memories
+ memories = mem0.search(messages[-1].content, user_id=user_id)
+ context = "Relevant context:\n"
+ for memory in memories["results"]:
+ context += f"- {memory['memory']}\n"
+
+ system_message = SystemMessage(content=f"""You are a helpful support assistant.
+{context}""")
+
+ response = llm.invoke([system_message] + messages)
+
+ # Store the interaction
+ mem0.add(
+ [{"role": "user", "content": messages[-1].content},
+ {"role": "assistant", "content": response.content}],
+ user_id=user_id
+ )
+ return {"messages": [response]}
+
+graph = StateGraph(State)
+graph.add_node("chatbot", chatbot)
+graph.add_edge(START, "chatbot")
+app = graph.compile()
+
+# Usage
+result = app.invoke({
+ "messages": [HumanMessage(content="I need help with my order")],
+ "mem0_user_id": "customer_123"
+})
+```
+
+---
+
+## LlamaIndex
+
+Source: [docs.mem0.ai/integrations/llama-index](https://docs.mem0.ai/integrations/llama-index)
+
+Install: `pip install llama-index-core llama-index-memory-mem0`
+
+LlamaIndex has native Mem0 support via `Mem0Memory`. Works with ReAct and FunctionCalling agents.
+
+```python
+from llama_index.memory.mem0 import Mem0Memory
+
+context = {"user_id": "alice", "agent_id": "llama_agent_1"}
+memory = Mem0Memory.from_client(
+ context=context,
+ search_msg_limit=4, # messages from chat history used for retrieval (default: 5)
+)
+
+# Use with LlamaIndex agent
+from llama_index.core.agent import FunctionCallingAgent
+from llama_index.llms.openai import OpenAI
+
+llm = OpenAI(model="gpt-4")
+agent = FunctionCallingAgent.from_tools(
+ tools=[],
+ llm=llm,
+ memory=memory,
+ verbose=True,
+)
+
+response = agent.chat("I prefer vegetarian restaurants")
+# Memory automatically stores and retrieves context
+response = agent.chat("What kind of food do I like?")
+# Agent retrieves the vegetarian preference from Mem0
+```
+
+---
+
+## AutoGen
+
+Source: [docs.mem0.ai/integrations/autogen](https://docs.mem0.ai/integrations/autogen)
+
+Install: `pip install autogen mem0ai`
+
+Multi-agent conversational systems with memory persistence.
+
+```python
+from autogen import ConversableAgent
+from mem0 import MemoryClient
+
+memory_client = MemoryClient()
+USER_ID = "alice"
+
+agent = ConversableAgent(
+ "chatbot",
+ llm_config={"config_list": [{"model": "gpt-4", "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)
+ context = "\n".join([m["memory"] for m in relevant_memories.get("results", [])])
+
+ prompt = f"""Answer considering previous interactions:
+ Previous context: {context}
+ Question: {question}"""
+
+ reply = agent.generate_reply(messages=[{"content": prompt, "role": "user"}])
+
+ # Store the new interaction
+ memory_client.add(
+ [{"role": "user", "content": question}, {"role": "assistant", "content": reply}],
+ user_id=USER_ID
+ )
+ return reply
+```
+
+---
+
+## All Supported Frameworks
+
+Beyond the examples above, Mem0 integrates with:
+
+| Framework | Type | Install |
+|-----------|------|---------|
+| [Mastra](https://docs.mem0.ai/integrations/mastra) | TS agent framework | `npm install @mastra/mem0` |
+| [ElevenLabs](https://docs.mem0.ai/integrations/elevenlabs) | Voice AI | `pip install elevenlabs mem0ai` |
+| [LiveKit](https://docs.mem0.ai/integrations/livekit) | Real-time voice/video | `pip install livekit-agents mem0ai` |
+| [Camel AI](https://docs.mem0.ai/integrations/camel-ai) | Multi-agent framework | `pip install camel-ai[all] mem0ai` |
+| [AWS Bedrock](https://docs.mem0.ai/integrations/aws-bedrock) | Cloud LLM provider | `pip install boto3 mem0ai` |
+| [Dify](https://docs.mem0.ai/integrations/dify) | Low-code AI platform | Plugin-based |
+| [Google AI ADK](https://docs.mem0.ai/integrations/google-ai-adk) | Google agent framework | `pip install google-adk mem0ai` |
+
+For the general Python pattern (no framework), see the "Common integration pattern" in [SKILL.md](../SKILL.md).
diff --git a/mem0-plugin/skills/mem0/references/quickstart.md b/mem0-plugin/skills/mem0/references/quickstart.md
new file mode 100644
index 000000000..0954f0c88
--- /dev/null
+++ b/mem0-plugin/skills/mem0/references/quickstart.md
@@ -0,0 +1,119 @@
+# Mem0 Platform Quickstart
+
+Get running with Mem0 in 2 minutes. No infrastructure to deploy -- just an API key.
+
+## Prerequisites
+
+- Python 3.10+ or Node.js 18+
+- A Mem0 Platform API key ([Get one here](https://app.mem0.ai/dashboard/api-keys))
+
+## Python Setup
+
+```bash
+pip install mem0ai
+export MEM0_API_KEY="m0-your-api-key"
+```
+
+```python
+from mem0 import MemoryClient
+
+client = MemoryClient(api_key="your-api-key")
+
+# Add a memory
+messages = [
+ {"role": "user", "content": "I'm a vegetarian and allergic to nuts."},
+ {"role": "assistant", "content": "Got it! I'll remember your dietary preferences."}
+]
+client.add(messages, user_id="user123")
+
+# Search memories
+results = client.search("What are my dietary restrictions?", user_id="user123")
+print(results)
+```
+
+### Async Client
+
+```python
+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")
+```
+
+## TypeScript / JavaScript Setup
+
+```bash
+npm install mem0ai
+export MEM0_API_KEY="m0-your-api-key"
+```
+
+```javascript
+import MemoryClient from 'mem0ai';
+
+const client = new MemoryClient({ apiKey: 'your-api-key' });
+
+// Add a memory
+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" });
+
+// Search memories
+const results = await client.search("What are my dietary restrictions?", {
+ user_id: "user123"
+});
+console.log(results);
+```
+
+## cURL
+
+```bash
+export MEM0_API_KEY="m0-your-api-key"
+
+# Add memory
+curl -X POST https://api.mem0.ai/v1/memories/ \
+ -H "Authorization: Token $MEM0_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "messages": [
+ {"role": "user", "content": "I am a vegetarian and allergic to nuts."},
+ {"role": "assistant", "content": "Got it! I will remember your dietary preferences."}
+ ],
+ "user_id": "user123"
+ }'
+
+# Search memories
+curl -X POST https://api.mem0.ai/v2/memories/search/ \
+ -H "Authorization: Token $MEM0_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "query": "What are my dietary restrictions?",
+ "filters": {"user_id": "user123"}
+ }'
+```
+
+## Sample Response
+
+```json
+{
+ "results": [
+ {
+ "id": "14e1b28a-2014-40ad-ac42-69c9ef42193d",
+ "memory": "Allergic to nuts",
+ "user_id": "user123",
+ "categories": ["health"],
+ "created_at": "2025-10-22T04:40:22.864647-07:00",
+ "score": 0.30
+ }
+ ]
+}
+```
+
+## Next Steps
+
+- [SDK Guide](sdk-guide.md) -- all methods for Python and TypeScript
+- [API Reference](api-reference.md) -- REST endpoints and memory object structure
+- [Integration Patterns](integration-patterns.md) -- LangChain, CrewAI, Vercel AI, etc.
diff --git a/mem0-plugin/skills/mem0/references/sdk-guide.md b/mem0-plugin/skills/mem0/references/sdk-guide.md
new file mode 100644
index 000000000..dc744d625
--- /dev/null
+++ b/mem0-plugin/skills/mem0/references/sdk-guide.md
@@ -0,0 +1,308 @@
+# Mem0 SDK Guide
+
+Complete SDK reference for Python and TypeScript. All methods use `MemoryClient` (Platform API).
+
+## Initialization
+
+**Python:**
+```python
+from mem0 import MemoryClient
+client = MemoryClient(api_key="m0-your-api-key")
+```
+
+**Python (Async):**
+```python
+from mem0 import AsyncMemoryClient
+client = AsyncMemoryClient(api_key="m0-your-api-key")
+```
+
+**TypeScript:**
+```typescript
+import MemoryClient from 'mem0ai';
+const client = new MemoryClient({ apiKey: 'm0-your-api-key' });
+```
+
+Constructor accepts `apiKey` (required) and `host` (optional, default: `https://api.mem0.ai`).
+
+---
+
+## add() -- Store Memories
+
+**Python:**
+```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")
+
+# 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 });
+```
+
+### Parameters
+
+| Name | Type | Description |
+|------|------|-------------|
+| `messages` | array | `[{"role": "user", "content": "..."}]` |
+| `user_id` | string | User identifier (recommended) |
+| `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."}],
+ user_id="alice",
+ infer=False,
+)
+```
+
+---
+
+## search() -- Find Memories
+
+**Python:**
+```python
+results = client.search("dietary preferences?", user_id="alice")
+
+# With filters and reranking
+results = client.search(
+ query="work experience",
+ filters={"AND": [{"user_id": "alice"}, {"categories": {"contains": "professional_details"}}]},
+ top_k=5,
+ 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("work experience", {
+ filters: { AND: [{ user_id: "alice" }, { categories: { contains: "professional_details" } }] },
+ top_k: 5,
+ rerank: true,
+});
+```
+
+### Parameters
+
+| 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 |
+
+### Common Filter Patterns
+
+```python
+# Single user (shorthand)
+client.search("query", 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"]}}]}
+
+# Wildcard (match any non-null run)
+filters={"AND": [{"user_id": "alice"}, {"run_id": "*"}]}
+
+# Date range
+filters={"AND": [
+ {"user_id": "alice"},
+ {"created_at": {"gte": "2024-01-01T00:00:00Z"}},
+ {"created_at": {"lt": "2024-02-01T00:00:00Z"}}
+]}
+
+# Exclude categories with NOT
+filters={"AND": [{"user_id": "user_123"}, {"NOT": {"categories": {"in": ["spam", "test"]}}}]}
+
+# Multi-dimensional query
+filters={"AND": [
+ {"user_id": "user_123"},
+ {"keywords": {"icontains": "invoice"}},
+ {"categories": {"in": ["finance"]}},
+ {"created_at": {"gte": "2024-01-01T00:00:00Z"}}
+]}
+```
+
+---
+
+## get() / getAll() -- Retrieve Memories
+
+**Python:**
+```python
+# Single memory by ID
+memory = client.get(memory_id="ea925981-...")
+
+# All memories for a user
+memories = client.get_all(filters={"AND": [{"user_id": "alice"}]})
+
+# With date range
+memories = client.get_all(
+ filters={"AND": [
+ {"user_id": "alex"},
+ {"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" }] } });
+```
+
+**Note:** `get_all` requires at least one of `user_id`, `agent_id`, `app_id`, or `run_id` in filters.
+
+---
+
+## update() -- Modify Memories
+
+**Python:**
+```python
+client.update(memory_id="ea925981-...", text="Updated: vegan since 2024")
+client.update(memory_id="ea925981-...", text="Updated", metadata={"verified": True})
+```
+
+**TypeScript:**
+```typescript
+await client.update("ea925981-...", { text: "Updated: vegan since 2024" });
+```
+
+Cannot update immutable memories.
+
+---
+
+## delete() / deleteAll() -- Remove Memories
+
+**Python:**
+```python
+client.delete(memory_id="ea925981-...")
+client.delete_all(user_id="alice") # Irreversible bulk delete
+```
+
+**TypeScript:**
+```typescript
+await client.delete("ea925981-...");
+await client.deleteAll({ user_id: "alice" });
+```
+
+---
+
+## history() -- Track Changes
+
+**Python:**
+```python
+history = client.history(memory_id="ea925981-...")
+# Returns: [{previous_value, new_value, action, timestamps}]
+```
+
+**TypeScript:**
+```typescript
+const history = await client.history("ea925981-...");
+```
+
+---
+
+## Batch Operations (TypeScript)
+
+```typescript
+// Batch update
+await client.batchUpdate([
+ { memoryId: "uuid-1", text: "Updated text" },
+ { memoryId: "uuid-2", text: "Another updated text" },
+]);
+
+// Batch delete
+await client.batchDelete(["uuid-1", "uuid-2", "uuid-3"]);
+```
+
+---
+
+## Additional Methods
+
+```python
+# List all users/agents/sessions with memories
+users = client.users()
+
+# Delete a user/agent entity
+client.delete_users(user_id="alice")
+
+# Submit feedback on a memory
+client.feedback(memory_id="...", feedback="POSITIVE", feedback_reason="Accurate extraction")
+
+# Export memories
+export = client.create_memory_export(filters={"AND": [{"user_id": "alice"}]})
+data = client.get_memory_export(memory_export_id=export["id"])
+```
+
+---
+
+## Common Pitfalls
+
+1. **Entity cross-filtering fails silently** -- `AND` with `user_id` + `agent_id` returns empty. Use `OR`.
+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.
+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`).
diff --git a/mem0-plugin/skills/mem0/references/use-cases.md b/mem0-plugin/skills/mem0/references/use-cases.md
new file mode 100644
index 000000000..eaca88896
--- /dev/null
+++ b/mem0-plugin/skills/mem0/references/use-cases.md
@@ -0,0 +1,720 @@
+# Mem0 Use Cases & Examples
+
+Real-world implementation patterns for Mem0 Platform. Each use case includes complete, runnable code in both Python and TypeScript.
+
+## Table of Contents
+
+- [Personalized AI Companion](#1-personalized-ai-companion)
+- [Customer Support with Categories](#2-customer-support-with-categories)
+- [Healthcare Coach](#3-healthcare-coach)
+- [Content Creation Workflow](#4-content-creation-workflow)
+- [Multi-Agent / Multi-Tenant](#5-multi-agent--multi-tenant)
+- [Personalized Search](#6-personalized-search)
+- [Email Intelligence](#7-email-intelligence)
+- [Common Patterns Across Use Cases](#common-patterns-across-use-cases)
+
+---
+
+## 1. Personalized AI Companion
+
+A fitness coach that remembers goals, preferences, and progress across sessions. Mem0 persists context across app restarts — no session state needed.
+
+### Implementation (Python)
+
+```python
+from mem0 import MemoryClient
+from openai import OpenAI
+
+mem0 = MemoryClient()
+openai_client = OpenAI()
+
+def chat(user_input: str, user_id: str) -> str:
+ # 1. Retrieve relevant memories
+ memories = mem0.search(user_input, user_id=user_id)
+ context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])])
+
+ # 2. Generate response with memory context
+ system_prompt = f"""You are Ray, a personal fitness coach.
+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",
+ messages=[
+ {"role": "system", "content": system_prompt},
+ {"role": "user", "content": user_input},
+ ]
+ )
+ reply = response.choices[0].message.content
+
+ # 3. Store interaction for future context
+ mem0.add(
+ [{"role": "user", "content": user_input}, {"role": "assistant", "content": reply}],
+ user_id=user_id
+ )
+ return reply
+
+# Usage
+chat("I want to run a marathon in under 4 hours", user_id="max")
+# Next day, app restarted:
+chat("What should I focus on today?", user_id="max")
+# Ray remembers the sub-4 marathon goal
+```
+
+### Implementation (TypeScript)
+
+```typescript
+import MemoryClient from 'mem0ai';
+import OpenAI from 'openai';
+
+const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
+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 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',
+ messages: [
+ { role: 'system', content: `You are Ray, a personal fitness coach.\nUser context:\n${context}` },
+ { role: 'user', content: userInput },
+ ],
+ });
+ const reply = response.choices[0].message.content!;
+
+ // 3. Store interaction
+ await mem0.add(
+ [{ role: 'user', content: userInput }, { role: 'assistant', content: reply }],
+ { user_id: userId }
+ );
+ return reply;
+}
+```
+
+### Key Benefits
+
+- Context persists across app restarts — no session management needed
+- Memories are automatically deduplicated and updated
+- Works with any LLM provider (OpenAI, Anthropic, etc.)
+
+**Best for:** Fitness coaches, tutors, therapists — any assistant that needs to remember goals across sessions.
+
+---
+
+## 2. Customer Support with Categories
+
+Auto-categorize support data so teams retrieve the right facts fast. Uses custom categories for structured retrieval.
+
+### Implementation (Python)
+
+```python
+from mem0 import MemoryClient
+
+client = MemoryClient()
+
+# 1. Define categories at the project level (one-time setup)
+custom_categories = [
+ {"support_tickets": "Customer issues and resolutions"},
+ {"account_info": "Account details and preferences"},
+ {"billing": "Payment history and billing questions"},
+ {"product_feedback": "Feature requests and feedback"},
+]
+client.project.update(custom_categories=custom_categories)
+
+# 2. Store interactions — auto-classified into categories
+def log_support_interaction(user_id: str, message: str, priority: str = "normal"):
+ client.add(
+ [{"role": "user", "content": message}],
+ user_id=user_id,
+ metadata={"priority": priority, "source": "support_chat"}
+ )
+
+# 3. Retrieve by category
+def get_billing_issues(user_id: str):
+ return client.get_all(
+ filters={
+ "AND": [
+ {"user_id": user_id},
+ {"categories": {"in": ["billing"]}}
+ ]
+ }
+ )
+
+def search_support_history(user_id: str, query: str):
+ return client.search(
+ query,
+ filters={
+ "AND": [
+ {"user_id": user_id},
+ {"categories": {"contains": "support_tickets"}}
+ ]
+ },
+ top_k=5
+ )
+
+# Usage
+log_support_interaction("maria", "I was charged twice for last month's subscription", priority="high")
+log_support_interaction("maria", "The dashboard is loading slowly on mobile")
+billing = get_billing_issues("maria") # Returns only billing-related memories
+```
+
+### Implementation (TypeScript)
+
+```typescript
+import MemoryClient from 'mem0ai';
+
+const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
+
+// Setup categories (one-time)
+await client.updateProject({
+ custom_categories: [
+ { support_tickets: 'Customer issues and resolutions' },
+ { billing: 'Payment history and billing questions' },
+ { product_feedback: 'Feature requests and feedback' },
+ ],
+});
+
+async function logInteraction(userId: string, message: string, priority = 'normal') {
+ await client.add(
+ [{ role: 'user', content: message }],
+ { user_id: userId, metadata: { priority, source: 'support_chat' } }
+ );
+}
+
+async function getBillingIssues(userId: string) {
+ return client.getAll({
+ filters: { AND: [{ user_id: userId }, { categories: { in: ['billing'] } }] },
+ });
+}
+```
+
+### Key Benefits
+
+- Automatic categorization — no manual tagging
+- Filter by category for structured retrieval
+- Metadata (`priority`, `source`) enables multi-dimensional queries
+
+**Best for:** Help desks, SaaS support, e-commerce — structured retrieval by category eliminates manual scanning.
+
+---
+
+## 3. Healthcare Coach
+
+Guide patients with an assistant that remembers medical history. Uses high `threshold` for confident retrieval in safety-critical contexts.
+
+### Implementation (Python)
+
+```python
+from mem0 import MemoryClient
+from openai import OpenAI
+
+mem0 = MemoryClient()
+openai_client = OpenAI()
+
+def save_patient_info(user_id: str, information: str):
+ mem0.add(
+ [{"role": "user", "content": information}],
+ user_id=user_id,
+ run_id="healthcare_session",
+ metadata={"type": "patient_information"}
+ )
+
+def consult(user_id: str, question: str) -> str:
+ # High threshold for medical accuracy
+ memories = mem0.search(question, user_id=user_id, top_k=5, threshold=0.7)
+ 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",
+ messages=[
+ {"role": "system", "content": f"You are a health coach. Patient context:\n{context}"},
+ {"role": "user", "content": question},
+ ]
+ )
+ reply = response.choices[0].message.content
+
+ # Store the interaction
+ mem0.add(
+ [{"role": "user", "content": question}, {"role": "assistant", "content": reply}],
+ user_id=user_id,
+ run_id="healthcare_session",
+ )
+ return reply
+
+# Usage
+save_patient_info("alex", "I'm allergic to penicillin and take metformin for type 2 diabetes")
+consult("alex", "Can I take amoxicillin for my sore throat?")
+# Remembers penicillin allergy — amoxicillin is a penicillin-type antibiotic
+```
+
+### Implementation (TypeScript)
+
+```typescript
+import MemoryClient from 'mem0ai';
+import OpenAI from 'openai';
+
+const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
+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' } }
+ );
+}
+
+async function consult(userId: string, question: string): Promise {
+ const memories = await mem0.search(question, {
+ user_id: userId,
+ top_k: 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',
+ messages: [
+ { role: 'system', content: `You are a health coach. Patient context:\n${context}` },
+ { role: 'user', content: question },
+ ],
+ });
+ const reply = response.choices[0].message.content!;
+
+ await mem0.add(
+ [{ role: 'user', content: question }, { role: 'assistant', content: reply }],
+ { user_id: userId, run_id: 'healthcare_session' }
+ );
+ return reply;
+}
+```
+
+### Key Benefits
+
+- High threshold (0.7) ensures only confident matches for safety-critical retrieval
+- Session scoping via `run_id` groups related health interactions
+- Metadata tagging separates patient info from conversation history
+
+**Best for:** Telehealth, wellness apps, patient management — persistent health context across visits.
+
+---
+
+## 4. Content Creation Workflow
+
+Store voice guidelines once and apply them across every draft. Uses `run_id` and `metadata` to scope writing preferences per session.
+
+### Implementation (Python)
+
+```python
+from mem0 import MemoryClient
+from openai import OpenAI
+
+mem0 = MemoryClient()
+openai_client = OpenAI()
+
+def store_writing_preferences(user_id: str, preferences: str):
+ mem0.add(
+ [{"role": "user", "content": preferences}],
+ user_id=user_id,
+ run_id="editing_session",
+ metadata={"type": "preferences", "category": "writing_style"}
+ )
+
+def draft_content(user_id: str, topic: str) -> str:
+ # Retrieve writing preferences
+ prefs = mem0.search(
+ "writing style preferences",
+ filters={"AND": [{"user_id": user_id}, {"run_id": "editing_session"}]}
+ )
+ 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",
+ messages=[
+ {"role": "system", "content": f"Write content matching these style preferences:\n{style_context}"},
+ {"role": "user", "content": f"Write a blog post about: {topic}"},
+ ]
+ )
+ return response.choices[0].message.content
+
+# Usage
+store_writing_preferences("writer_01", "I prefer short sentences. Active voice. No jargon. Use analogies.")
+draft_content("writer_01", "Why AI memory matters for chatbots")
+# Drafts content matching the stored voice guidelines
+```
+
+### Implementation (TypeScript)
+
+```typescript
+import MemoryClient from 'mem0ai';
+import OpenAI from 'openai';
+
+const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
+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' } }
+ );
+}
+
+async function draftContent(userId: string, topic: string): Promise {
+ const prefs = await mem0.search('writing style preferences', {
+ filters: { AND: [{ user_id: userId }, { run_id: 'editing_session' }] },
+ });
+ 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',
+ messages: [
+ { role: 'system', content: `Write content matching these preferences:\n${styleContext}` },
+ { role: 'user', content: `Write a blog post about: ${topic}` },
+ ],
+ });
+ return response.choices[0].message.content!;
+}
+```
+
+### Key Benefits
+
+- Voice consistency across all content without repeating guidelines
+- Scoped sessions let you maintain different style profiles
+- Preferences update automatically as you refine them
+
+**Best for:** Marketing teams, technical writers, agencies — consistent voice across all content.
+
+---
+
+## 5. Multi-Agent / Multi-Tenant
+
+Keep memories separate using `user_id`, `agent_id`, `app_id`, and `run_id` scoping. Critical for multi-agent workflows and multi-tenant apps.
+
+### Implementation (Python)
+
+```python
+from mem0 import MemoryClient
+
+client = MemoryClient()
+
+# Store memories scoped to user + agent + session
+def store_scoped_memory(messages: list, user_id: str, agent_id: str, run_id: str, app_id: str):
+ client.add(
+ messages,
+ user_id=user_id,
+ agent_id=agent_id,
+ run_id=run_id,
+ app_id=app_id
+ )
+
+# Query within a specific scope
+def search_user_session(query: str, user_id: str, app_id: str, run_id: str):
+ """Search memories for a specific user within a specific session."""
+ return client.search(
+ query,
+ filters={
+ "AND": [
+ {"user_id": user_id},
+ {"app_id": app_id},
+ {"run_id": run_id}
+ ]
+ }
+ )
+
+def search_agent_knowledge(query: str, agent_id: str, app_id: str):
+ """Search all memories an agent has across all users."""
+ return client.search(
+ query,
+ filters={
+ "AND": [
+ {"agent_id": agent_id},
+ {"app_id": app_id}
+ ]
+ }
+ )
+
+# Usage: Travel concierge app with multiple agents
+store_scoped_memory(
+ [{"role": "user", "content": "I'm vegetarian and prefer window seats"}],
+ user_id="traveler_cam",
+ agent_id="travel_planner",
+ run_id="tokyo-2025",
+ app_id="concierge_app"
+)
+
+# User-scoped query: "What does Cam prefer?"
+user_mems = search_user_session("dietary restrictions?", "traveler_cam", "concierge_app", "tokyo-2025")
+
+# Agent-scoped query: "What do all travelers prefer?" (across users)
+agent_mems = search_agent_knowledge("common dietary restrictions?", "travel_planner", "concierge_app")
+```
+
+### Implementation (TypeScript)
+
+```typescript
+import MemoryClient from 'mem0ai';
+
+const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
+
+async function storeScopedMemory(
+ messages: Array<{ role: string; content: string }>,
+ userId: string, agentId: string, runId: string, appId: string
+) {
+ await client.add(messages, {
+ user_id: userId,
+ agent_id: agentId,
+ run_id: runId,
+ app_id: appId,
+ });
+}
+
+async function searchUserSession(query: string, userId: string, appId: string, runId: string) {
+ return client.search(query, {
+ filters: { AND: [{ user_id: userId }, { app_id: appId }, { run_id: runId }] },
+ });
+}
+
+async function searchAgentKnowledge(query: string, agentId: string, appId: string) {
+ return client.search(query, {
+ filters: { AND: [{ agent_id: agentId }, { app_id: appId }] },
+ });
+}
+```
+
+### Key Benefits
+
+- Full isolation between users, agents, sessions, and apps
+- Query at any scope level — user, agent, session, or app-wide
+- No memory leakage between tenants
+
+**Best for:** Multi-agent workflows, multi-tenant SaaS — proper isolation at every level.
+
+---
+
+## 6. Personalized Search
+
+Blend real-time search results with personal context. Uses `custom_instructions` to infer preferences from queries.
+
+### Implementation (Python)
+
+```python
+from mem0 import MemoryClient
+from openai import OpenAI
+
+mem0 = MemoryClient()
+openai_client = OpenAI()
+
+# One-time setup: configure Mem0 to infer from queries
+mem0.project.update(
+ custom_instructions="""Infer user preferences and facts from their search queries.
+Extract dietary preferences, location, interests, and purchase history."""
+)
+
+def personalized_search(user_id: str, query: str, search_results: list) -> str:
+ # Get user context from memory
+ memories = mem0.search(query, user_id=user_id, top_k=5)
+ 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",
+ 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}"},
+ ]
+ )
+ reply = response.choices[0].message.content
+
+ # Store the query to learn preferences over time
+ mem0.add(
+ [{"role": "user", "content": query}],
+ user_id=user_id
+ )
+ return reply
+
+# Usage
+personalized_search("user_42", "best restaurants nearby", ["Restaurant A", "Restaurant B"])
+# Over time, Mem0 learns: "user prefers vegetarian, lives in Austin"
+# Future searches are automatically personalized
+```
+
+### Implementation (TypeScript)
+
+```typescript
+import MemoryClient from 'mem0ai';
+import OpenAI from 'openai';
+
+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 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',
+ messages: [
+ { role: 'system', content: `Personalize results using user context:\n${context}` },
+ { role: 'user', content: `Query: ${query}\nResults: ${searchResults.join(', ')}` },
+ ],
+ });
+ const reply = response.choices[0].message.content!;
+
+ await mem0.add([{ role: 'user', content: query }], { user_id: userId });
+ return reply;
+}
+```
+
+### Key Benefits
+
+- Learns preferences from queries automatically via `custom_instructions`
+- Personalizes any search provider (Tavily, Google, Bing)
+- Zero manual preference setup — improves over time
+
+**Best for:** Personalized search engines, recommendation systems — search results tailored to individual users.
+
+---
+
+## 7. Email Intelligence
+
+Capture, categorize, and recall inbox threads using persistent memories with rich metadata.
+
+### Implementation (Python)
+
+```python
+from mem0 import MemoryClient
+
+client = MemoryClient()
+
+def store_email(user_id: str, sender: str, subject: str, body: str, date: str):
+ client.add(
+ [{"role": "user", "content": f"Email from {sender}: {subject}\n\n{body}"}],
+ user_id=user_id,
+ metadata={"email_type": "incoming", "sender": sender, "subject": subject, "date": date}
+ )
+
+def search_emails(user_id: str, query: str):
+ return client.search(
+ query,
+ filters={"AND": [{"user_id": user_id}, {"categories": {"contains": "email"}}]},
+ top_k=10
+ )
+
+def get_emails_from_sender(user_id: str, sender: str):
+ return client.get_all(
+ filters={
+ "AND": [
+ {"user_id": user_id},
+ {"metadata": {"contains": sender}}
+ ]
+ }
+ )
+
+# Usage
+store_email("alice", "bob@acme.com", "Q3 Budget Review", "Attached is the Q3 budget...", "2025-01-15")
+store_email("alice", "carol@acme.com", "Sprint Planning", "Here are the priorities...", "2025-01-16")
+
+results = search_emails("alice", "budget discussions")
+sender_emails = get_emails_from_sender("alice", "bob@acme.com")
+```
+
+### Implementation (TypeScript)
+
+```typescript
+import MemoryClient from 'mem0ai';
+
+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 } }
+ );
+}
+
+async function searchEmails(userId: string, query: string) {
+ return client.search(query, {
+ filters: { AND: [{ user_id: userId }, { categories: { contains: 'email' } }] },
+ top_k: 10,
+ });
+}
+```
+
+### Key Benefits
+
+- Rich metadata enables multi-dimensional queries (sender, date, subject)
+- Category filtering separates emails from other memory types
+- Semantic search across all email content
+
+**Best for:** Inbox management, email automation — searchable email memories with metadata filtering.
+
+---
+
+## Common Patterns Across Use Cases
+
+### Pattern 1: Retrieve → Generate → Store
+
+Every use case follows the same 3-step loop:
+
+```python
+# 1. Retrieve relevant context
+memories = mem0.search(user_input, user_id=user_id)
+context = "\n".join([m["memory"] for m in memories.get("results", [])])
+
+# 2. Generate with context
+response = llm.generate(system_prompt=f"Context:\n{context}", user_input=user_input)
+
+# 3. Store the interaction
+mem0.add(
+ [{"role": "user", "content": user_input}, {"role": "assistant", "content": response}],
+ user_id=user_id
+)
+```
+
+### Pattern 2: Scope with Entity Identifiers
+
+Use `user_id`, `agent_id`, `app_id`, and `run_id` to isolate memories:
+
+```python
+# User-level: personal preferences
+client.add(messages, user_id="alice")
+
+# Session-level: conversation within one session
+client.add(messages, user_id="alice", run_id="session_123")
+
+# Agent-level: agent-specific knowledge
+client.add(messages, agent_id="support_bot", app_id="helpdesk")
+```
+
+### Pattern 3: Rich Metadata for Filtering
+
+Attach structured metadata for multi-dimensional queries:
+
+```python
+# Store with metadata
+client.add(messages, user_id="alice", metadata={"priority": "high", "source": "phone_call"})
+
+# Filter by category + metadata
+client.search("billing issues", filters={
+ "AND": [{"user_id": "alice"}, {"categories": {"contains": "billing"}}]
+})
+```
+
+### Pattern 4: Custom Instructions for Domain-Specific Extraction
+
+Control what Mem0 extracts from conversations:
+
+```python
+client.project.update(
+ custom_instructions="Extract medical conditions, medications, and allergies. Exclude billing info."
+)
+```
+
+---
+
+## More Examples
+
+For 30+ cookbooks with complete working code: [docs.mem0.ai/cookbooks](https://docs.mem0.ai/cookbooks)
diff --git a/mem0-plugin/skills/mem0/scripts/mem0_doc_search.py b/mem0-plugin/skills/mem0/scripts/mem0_doc_search.py
new file mode 100755
index 000000000..1ff8de1c7
--- /dev/null
+++ b/mem0-plugin/skills/mem0/scripts/mem0_doc_search.py
@@ -0,0 +1,224 @@
+#!/usr/bin/env python3
+"""
+Mem0 Documentation Search Agent (Mintlify-based)
+On-demand search tool for querying Mem0 documentation without storing content locally.
+
+This tool leverages Mintlify's documentation structure to perform just-in-time
+retrieval of technical information from docs.mem0.ai.
+
+Usage:
+ python mem0_doc_search.py --query "how to add graph memory"
+ python mem0_doc_search.py --query "filter syntax for categories"
+ python mem0_doc_search.py --page "/platform/features/graph-memory"
+ python mem0_doc_search.py --index
+ python mem0_doc_search.py --query "webhook events" --section platform
+
+Purpose:
+ - Avoid bloating local context with full documentation
+ - Enable just-in-time retrieval of technical details
+ - Query specific documentation pages on demand
+ - Search across the full Mem0 documentation site
+"""
+
+import argparse
+import json
+import sys
+import urllib.error
+import urllib.parse
+import urllib.request
+
+DOCS_BASE = "https://docs.mem0.ai"
+SEARCH_ENDPOINT = f"{DOCS_BASE}/api/search"
+LLMS_INDEX = f"{DOCS_BASE}/llms.txt"
+
+# Known documentation sections for targeted retrieval
+SECTION_MAP = {
+ "platform": [
+ "/platform/overview",
+ "/platform/quickstart",
+ "/platform/features",
+ "/platform/features/graph-memory",
+ "/platform/features/selective-memory",
+ "/platform/features/custom-categories",
+ "/platform/features/v2-memory-filters",
+ "/platform/features/async-client",
+ "/platform/features/webhooks",
+ "/platform/features/multimodal-support",
+ ],
+ "api": [
+ "/api-reference/memory/add-memories",
+ "/api-reference/memory/v2-search-memories",
+ "/api-reference/memory/v2-get-memories",
+ "/api-reference/memory/get-memory",
+ "/api-reference/memory/update-memory",
+ "/api-reference/memory/delete-memory",
+ ],
+ "open-source": [
+ "/open-source/overview",
+ "/open-source/python-quickstart",
+ "/open-source/node-quickstart",
+ "/open-source/features",
+ "/open-source/features/graph-memory",
+ "/open-source/features/rest-api",
+ "/open-source/configure-components",
+ ],
+ "openmemory": [
+ "/openmemory/overview",
+ "/openmemory/quickstart",
+ ],
+ "sdks": [
+ "/sdks/python",
+ "/sdks/js",
+ ],
+ "integrations": [
+ "/integrations",
+ ],
+}
+
+
+def fetch_url(url: str) -> str:
+ """Fetch content from a URL."""
+ req = urllib.request.Request(url, headers={"User-Agent": "Mem0DocSearchAgent/1.0"})
+ try:
+ with urllib.request.urlopen(req, timeout=15) as resp:
+ return resp.read().decode("utf-8")
+ except urllib.error.HTTPError as e:
+ return f"HTTP Error {e.code}: {e.reason}"
+ except urllib.error.URLError as e:
+ return f"URL Error: {e.reason}"
+
+
+def search_docs(query: str, section: str | None = None) -> dict:
+ """
+ Search Mem0 documentation using Mintlify's search API.
+ Falls back to the llms.txt index for keyword matching if the API is unavailable.
+ """
+ # Try Mintlify search API first
+ params = urllib.parse.urlencode({"query": query})
+ search_url = f"{SEARCH_ENDPOINT}?{params}"
+
+ try:
+ result = fetch_url(search_url)
+ data = json.loads(result)
+ if isinstance(data, dict) and data.get("results"):
+ results = data["results"]
+ if section and section in SECTION_MAP:
+ section_paths = SECTION_MAP[section]
+ results = [r for r in results if any(r.get("url", "").startswith(p) for p in section_paths)]
+ return {"source": "mintlify_search", "results": results}
+ except (json.JSONDecodeError, Exception):
+ pass
+
+ # Fallback: search llms.txt index for matching URLs
+ index_content = fetch_url(LLMS_INDEX)
+ query_lower = query.lower()
+ matching_urls = []
+
+ for line in index_content.splitlines():
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ if query_lower in line.lower():
+ matching_urls.append(line)
+
+ if section and section in SECTION_MAP:
+ section_paths = SECTION_MAP[section]
+ matching_urls = [u for u in matching_urls if any(p in u for p in section_paths)]
+
+ return {
+ "source": "llms_txt_index",
+ "query": query,
+ "matching_urls": matching_urls[:20],
+ "suggestion": "Fetch specific URLs for detailed content",
+ }
+
+
+def fetch_page(page_path: str) -> dict:
+ """Fetch a specific documentation page."""
+ url = f"{DOCS_BASE}{page_path}" if page_path.startswith("/") else page_path
+ content = fetch_url(url)
+ return {"url": url, "content": content[:10000], "truncated": len(content) > 10000}
+
+
+def get_index() -> dict:
+ """Fetch the full documentation index from llms.txt."""
+ content = fetch_url(LLMS_INDEX)
+ urls = [line.strip() for line in content.splitlines() if line.strip() and not line.startswith("#")]
+ return {"total_pages": len(urls), "urls": urls, "sections": list(SECTION_MAP.keys())}
+
+
+def list_section(section: str) -> dict:
+ """List all known pages in a documentation section."""
+ if section not in SECTION_MAP:
+ return {"error": f"Unknown section: {section}", "available": list(SECTION_MAP.keys())}
+ return {
+ "section": section,
+ "pages": [f"{DOCS_BASE}{p}" for p in SECTION_MAP[section]],
+ }
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Search Mem0 documentation on demand")
+ parser.add_argument("--query", help="Search query for documentation")
+ parser.add_argument("--page", help="Fetch a specific page path (e.g., /platform/features/graph-memory)")
+ parser.add_argument("--index", action="store_true", help="Show full documentation index")
+ parser.add_argument("--section", help="Filter by section or list section pages")
+ parser.add_argument("--json", action="store_true", help="Output as JSON")
+
+ args = parser.parse_args()
+
+ if args.index:
+ result = get_index()
+ elif args.section and not args.query:
+ result = list_section(args.section)
+ elif args.page:
+ result = fetch_page(args.page)
+ elif args.query:
+ result = search_docs(args.query, section=args.section)
+ else:
+ parser.print_help()
+ sys.exit(1)
+
+ if args.json:
+ print(json.dumps(result, indent=2))
+ else:
+ if isinstance(result, dict):
+ if "results" in result:
+ print(f"Source: {result.get('source', 'unknown')}")
+ for r in result["results"]:
+ print(f" - {r.get('title', 'N/A')}: {r.get('url', 'N/A')}")
+ if r.get("description"):
+ print(f" {r['description'][:200]}")
+ elif "matching_urls" in result:
+ print(f"Source: {result['source']}")
+ print(f"Query: {result['query']}")
+ for url in result["matching_urls"]:
+ print(f" - {url}")
+ if result.get("suggestion"):
+ print(f"\n{result['suggestion']}")
+ elif "urls" in result:
+ print(f"Total documentation pages: {result['total_pages']}")
+ print(f"Sections: {', '.join(result['sections'])}")
+ for url in result["urls"][:30]:
+ print(f" - {url}")
+ if result["total_pages"] > 30:
+ print(f" ... and {result['total_pages'] - 30} more")
+ elif "pages" in result:
+ print(f"Section: {result['section']}")
+ for page in result["pages"]:
+ print(f" - {page}")
+ elif "content" in result:
+ print(f"URL: {result['url']}")
+ if result.get("truncated"):
+ print("[Content truncated to 10000 chars]")
+ print(result["content"])
+ elif "error" in result:
+ print(f"Error: {result['error']}")
+ if result.get("available"):
+ print(f"Available sections: {', '.join(result['available'])}")
+ else:
+ print(json.dumps(result, indent=2))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/pyproject.toml b/pyproject.toml
index 38a07433c..756f652a8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@ name = "mem0ai"
version = "1.0.7"
description = "Long-term memory for AI Agents"
authors = [
- { name = "Mem0", email = "founders@mem0.ai" }
+ { name = "Mem0", email = "support@mem0.ai" }
]
readme = "README.md"
license = "Apache-2.0"