fix: update skills and docs (#4868)

This commit is contained in:
Kartik
2026-04-18 11:42:37 +05:30
committed by GitHub
parent c1c5bd62f6
commit 93da5ef8f7
23 changed files with 461 additions and 662 deletions
+29 -19
View File
@@ -8,13 +8,15 @@ All endpoints require: `Authorization: Token <MEM0_API_KEY>`
| Operation | Method | URL |
|-----------|--------|-----|
| Add Memories | `POST` | `/v1/memories/` |
| Search Memories | `POST` | `/v2/memories/search/` |
| Get All Memories | `POST` | `/v2/memories/` |
| Add Memories | `POST` | `/v3/memories/add/` |
| Search Memories | `POST` | `/v3/memories/search/` |
| Get All Memories | `POST` | `/v3/memories/` |
| Get Single Memory | `GET` | `/v1/memories/{memory_id}/` |
| Update Memory | `PUT` | `/v1/memories/{memory_id}/` |
| Delete Memory | `DELETE` | `/v1/memories/{memory_id}/` |
Note: v1/v2 endpoints still work (backward compatible).
## Memory Object Structure
| Field | Type | Description |
@@ -27,8 +29,6 @@ All endpoints require: `Authorization: Token <MEM0_API_KEY>`
| `run_id` | string (nullable) | Run/session identifier |
| `metadata` | object | Custom key-value pairs |
| `categories` | array of strings | Auto-assigned category tags |
| `immutable` | boolean | If true, prevents modification |
| `expiration_date` | datetime (nullable) | Auto-expiry date |
| `hash` | string | Content hash |
| `created_at` | datetime | Creation timestamp |
| `updated_at` | datetime | Last modification timestamp |
@@ -50,10 +50,9 @@ Memories can be scoped to different levels:
## Processing Model
- Memories are processed **asynchronously by default** (`async_mode=true`)
- Add responses return queued events (`ADD`, `UPDATE`, `DELETE`) for tracking
- Set `async_mode=false` for synchronous processing when needed
- Graph metadata is processed asynchronously -- use `get_all()` for complete graph data
- Memories are processed **asynchronously** (v3 default)
- Add responses return queued `ADD` events only (v3 is ADD-only, no UPDATE/DELETE)
- Poll status via `GET /v1/event/{event_id}/`
## Filter System
@@ -106,19 +105,17 @@ Root must be `AND`, `OR`, or `NOT`. Simple shorthand `{"user_id": "alice"}` also
## Response Formats
### Add Response
### Add Response (v3)
```json
[
{
"id": "mem_01JF8ZS4Y0R0SPM13R5R6H32CJ",
"event": "ADD",
"data": { "memory": "The user moved to Austin in 2025." }
}
]
{
"message": "Memory processing has been queued for background execution",
"status": "PENDING",
"event_id": "evt-uuid"
}
```
Event types: `ADD`, `UPDATE`, `DELETE`. A single add can trigger multiple events.
v3 is ADD-only. No UPDATE or DELETE events.
### Search Response
@@ -137,4 +134,17 @@ Event types: `ADD`, `UPDATE`, `DELETE`. A single add can trigger multiple events
}
```
With `enable_graph=true`, includes additional `relations` array with entity relationships.
In v3, `score` is a combined multi-signal relevance score.
### Get All Response (v3)
```json
{
"count": 123,
"next": "https://api.mem0.ai/v3/memories/?page=2&page_size=50",
"previous": null,
"results": [...]
}
```
v3 returns paginated envelope. Use `page` and `page_size` query params.
+44 -100
View File
@@ -25,9 +25,9 @@ User Input → Retrieve relevant memories → Enrich LLM prompt → Generate res
Mem0 handles the complexity of extraction, deduplication, conflict resolution, and semantic retrieval so your application only needs to call `search()` and `add()`.
**Dual storage architecture:**
**Storage architecture:**
- **Vector store**: Embeddings for semantic similarity search
- **Graph store** (optional): Entity nodes and relationship edges for structured knowledge
- **Entity store**: Automatic entity linking for relationship-aware retrieval
---
@@ -40,41 +40,32 @@ Messages In
│
▼
┌─────────────────────┐
│ 1. EXTRACTION │ LLM analyzes messages, extracts key facts
│ 1. EXTRACTION │ Single LLM call extracts all distinct new facts
│ (infer=True) │ If infer=False, stores raw text as-is
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ 2. CONFLICT │ Checks existing memories for duplicates
│ RESOLUTION │ Latest truth wins (newer overrides older)
│ │ Only runs when infer=True
│ 2. DEDUPLICATION │ Hash-based dedup (MD5 prevents exact duplicates)
│ │ No UPDATE/DELETE - v3 is ADD-only
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ 3. STORAGE │ Generates embeddings → vector store
│ │ Optional: entity extraction → graph store
│ │ Indexes metadata, categories, timestamps
│ 3. STORAGE │ Batch embed → vector store
│ │ Entity extraction → entity store
└─────────┬───────────┘
│
▼
Memory Object
(id, memory, categories, structured_attributes)
```
### Processing modes
### Processing (v3)
**Async (default, `async_mode=True`):**
- API returns immediately: `{"status": "PENDING", "event_id": "..."}`
- Processing happens in background
v3 processes memories asynchronously by default:
- API returns immediately: `{"status": "PENDING", "event_id": "evt-..."}`
- Poll status via `GET /v1/event/{event_id}/`
- Use webhooks for completion notifications
- Best for: high-throughput, non-blocking workflows
**Sync (`async_mode=False`):**
- API waits for full processing
- Returns complete memory object with `id`, `event`, `memory`
- Best for: real-time access immediately after add
### Extraction modes
@@ -93,7 +84,7 @@ Messages In
---
## Retrieval Pipeline
## Retrieval Pipeline (v3)
### What happens when you call `client.search()`
@@ -102,45 +93,37 @@ Query In
│
▼
┌─────────────────────┐
│ 1. QUERY EMBEDDING │ Convert query to vector representation
│ 1. PREPROCESSING │ Lemmatize keywords, extract entities
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ 2. VECTOR SEARCH │ Cosine similarity across stored embeddings
│ │ Scoped by filters (user_id, agent_id, etc.)
└─────────┬───────────┘
│
▼ (optional enhancements)
┌─────────────────────┐
│ 3a. KEYWORD SEARCH │ Expands results with specific terms (+10ms)
│ 3b. RERANKING │ Deep semantic reordering (+150-200ms)
│ 3c. FILTER MEMORIES │ Precision filtering, removes low-relevance (+200-300ms)
└─────────┬───────────┘
│
▼ (if enable_graph=True)
┌─────────────────────┐
│ 4. GRAPH LOOKUP │ Finds entity relationships
│ │ Appends relations WITHOUT reranking vector results
│ 2. PARALLEL SCORING │ Semantic search (vector similarity)
│ │ BM25 keyword search (term matching)
│ │ Entity matching (entity graph boost)
└─────────┬───────────┘
│
▼
Results + Relations
┌─────────────────────┐
│ 3. SCORE FUSION │ Combine signals into single score
│ │ Optional: rerank=True for deep reordering
└─────────┬───────────┘
│
▼
Results (combined score per memory)
```
### Retrieval enhancement combinations
### v3 Search Defaults
| Configuration | Latency | Best for |
|--------------|---------|----------|
| Base search only | ~100ms | Simple lookups |
| `keyword_search=True` | ~110ms | Entity-heavy queries, broad coverage |
| `rerank=True` | ~250-300ms | User-facing results, top-N precision |
| `keyword_search=True` + `rerank=True` | ~310ms | Balanced (recommended for most apps) |
| `rerank=True` + `filter_memories=True` | ~400-500ms | Safety-critical, production systems |
| Parameter | Default | Notes |
|-----------|---------|-------|
| `top_k` | 20 | Was 100 in v2 |
| `threshold` | 0.1 | Was None in v2 |
| `rerank` | False | Was True in v2 |
### Implicit null scoping
When you search with `user_id="alice"` only, Mem0 returns memories where `agent_id`, `app_id`, and `run_id` are all null. This prevents cross-scope leakage by default.
When you search with `filters={"user_id": "alice"}` only, Mem0 returns memories where `agent_id`, `app_id`, and `run_id` are all null. This prevents cross-scope leakage by default.
To include memories with non-null fields, use explicit filters:
```python
@@ -150,53 +133,23 @@ filters={"OR": [{"user_id": "alice"}]}
---
## Memory Lifecycle
## Memory Lifecycle (v3)
```
CREATE ──→ ACTIVE ──→ UPDATE ──→ ACTIVE
│ │ │
│ ▼ ▼
│ EXPIRED EXPIRED
│ (still stored, (still stored,
│ not retrieved) not retrieved)
│ │ │
▼ ▼ ▼
DELETE DELETE DELETE
(permanent)
```
v3 uses ADD-only extraction. Memories accumulate over time rather than being consolidated.
### Creation
- Triggered by `client.add(messages, user_id="...")`
- Messages processed through extraction → conflict resolution → storage
- Gets unique UUID, `created_at` timestamp
- Optional: custom `timestamp`, `expiration_date`, `metadata`, `immutable`
- `client.add(messages, user_id="...")`
- Single-pass extraction → deduplication → storage
- Returns `{"event_id": "...", "status": "PENDING"}`
### Updates
- `client.update(memory_id, text="...")` replaces text and reindexes
- `client.batch_update([...])` for up to 1000 memories at once
- Immutable memories (`immutable=True`) cannot be updated — must delete and re-add
### Deduplication
- Automatic during `add()` with `infer=True`
- Conflict resolution merges duplicate facts
- Latest truth wins when contradictions detected
- Prevents memory bloat from repeated information
### Expiration
- Optional `expiration_date` parameter (ISO 8601 or `YYYY-MM-DD`)
- After expiration: memory NOT returned in searches but remains in storage
- Useful for time-sensitive info (events, temporary preferences, session state)
- `client.update(memory_id, text="...")` replaces text
- Batch: `client.batch_update([...])`
### Deletion
- Single: `client.delete(memory_id)` — permanent, no recovery
- Batch: `client.batch_delete([memory_ids])` — up to 1000
- Bulk: `client.delete_all(user_id="alice")` — all memories for entity
- `delete_all()` without filters raises error to prevent accidental data loss
### History tracking
- `client.history(memory_id)` returns version timeline
- Shows all changes: `{previous_value, new_value, action, timestamps}`
- Useful for audit trails and debugging
- Single: `client.delete(memory_id)`
- Batch: `client.batch_delete([...])`
- Bulk: `client.delete_all(filters={"user_id": "alice"})`
---
@@ -214,8 +167,6 @@ DELETE DELETE DELETE
"categories": ["health", "preferences"],
"created_at": "2025-03-12T12:34:56Z",
"updated_at": "2025-03-12T12:34:56Z",
"expiration_date": null,
"immutable": false,
"structured_attributes": {
"day": 12, "month": 3, "year": 2025,
"hour": 12, "minute": 34,
@@ -239,8 +190,6 @@ DELETE DELETE DELETE
| `categories` | array | Auto-assigned or custom category tags |
| `created_at` | datetime | Creation timestamp |
| `updated_at` | datetime | Last modification timestamp |
| `expiration_date` | datetime | Auto-expiry date (stops retrieval, data persists) |
| `immutable` | boolean | If true, prevents modification |
| `structured_attributes` | object | Temporal breakdown for time-based queries |
| `score` | float | Semantic similarity (search results only, 0-1) |
@@ -322,7 +271,7 @@ Mem0 supports three layers of memory, from shortest to longest lived:
```python
def chat(user_input: str, user_id: str, session_id: str) -> str:
# 1. Retrieve user memories (long-term preferences)
user_mems = mem0.search(user_input, user_id=user_id)
user_mems = mem0.search(user_input, filters={"user_id": user_id})
# 2. Retrieve session memories (current task context)
session_mems = mem0.search(user_input, filters={
@@ -350,18 +299,13 @@ def chat(user_input: str, user_id: str, session_id: str) -> str:
| Operation | Typical Latency |
|-----------|----------------|
| Base vector search | ~100ms |
| + keyword_search | +10ms |
| Hybrid search (v3 default) | ~100-150ms |
| + reranking | +150-200ms |
| + filter_memories | +200-300ms |
| Add (async, default) | < 50ms response, background processing |
| Add (sync) | 500ms-2s depending on extraction complexity |
| Graph operations | Slight overhead for large stores |
| Add (async) | < 50ms response |
### Processing
- **Async mode (default):** Returns immediately, processes in background
- **Sync mode:** Waits for full extraction + storage pipeline
- **Async (default):** Returns immediately, processes in background
- **Batch operations:** Up to 1000 memories per batch_update/batch_delete
- **Webhooks:** Real-time notifications when async processing completes
+26 -92
View File
@@ -5,7 +5,7 @@ Additional platform capabilities beyond core CRUD operations.
## Table of Contents
- [Advanced Retrieval](#advanced-retrieval)
- [Graph Memory](#graph-memory)
- [Entity Linking](#entity-linking)
- [Custom Categories](#custom-categories)
- [Custom Instructions](#custom-instructions)
- [Criteria Retrieval](#criteria-retrieval)
@@ -18,124 +18,58 @@ Additional platform capabilities beyond core CRUD operations.
## Advanced Retrieval
Three enhancement options for tuning search precision, recall, and latency.
### Hybrid Search (v3 Default)
### Keyword Search (`keyword_search=True`)
v3 uses multi-signal hybrid search combining:
- **Semantic search** (vector similarity)
- **BM25 keyword search** (normalized term matching)
- **Entity matching** (entity graph boost)
Expands results to include memories with specific terms, names, and technical keywords.
- Latency: +10ms
- Recall: Significantly increased
- Best for: entity-heavy queries, comprehensive coverage
This is automatic — no configuration needed.
### Reranking (`rerank=True`)
Deep semantic reordering of results — most relevant first.
- Latency: +150-200ms
- Accuracy: Significantly improved
- Default: `False` (was `True` in v2)
- Best for: user-facing results, top-N precision
### Filter Memories (`filter_memories=True`)
Precision filtering — removes low-relevance results entirely.
- Latency: +200-300ms
- Precision: Maximized
- Best for: safety-critical applications, production systems
### Recommended Combinations
**Python:**
```python
# Fast & broad
results = client.search(query, keyword_search=True, user_id="user123")
# Balanced (recommended for most apps)
results = client.search(query, keyword_search=True, rerank=True, user_id="user123")
# High precision (critical apps)
results = client.search(query, rerank=True, filter_memories=True, user_id="user123")
results = client.search(query, filters={"user_id": "user123"}, rerank=True)
```
**TypeScript:**
```typescript
const results = await client.search(query, {
user_id: 'user123',
keyword_search: true,
filters: { user_id: 'user123' },
rerank: true,
});
```
---
## Graph Memory
## Entity Linking
Entity-level knowledge graph that creates relationships between memories.
v3 replaces graph memory with built-in entity linking. Entities (proper nouns, quoted text, compound noun phrases) are automatically extracted and linked across memories.
### How It Works
1. **Extraction**: LLM analyzes conversation and identifies entities and relationships
2. **Storage**: Embeddings go to vector store; entity nodes and edges go to graph store
3. **Retrieval**: Vector search returns semantic matches; graph relations are appended to results
1. **Extraction**: During `add()`, entities are automatically extracted from memory text
2. **Storage**: Entities are stored in a parallel collection (`{collection}_entities`)
3. **Retrieval**: During `search()`, query entities are matched and used to boost relevant memories
Graph relations **augment** vector results without reordering them. Vector similarity always determines hit sequence.
Entity linking is automatic — no configuration required. The boost is folded into the combined `score` on each result.
### Enabling Graph Memory
### v2 Migration Note
**Per request:**
```python
client.add(messages, user_id="alice", enable_graph=True)
client.search("query", user_id="alice", enable_graph=True)
client.get_all(filters={"AND": [{"user_id": "alice"}]}, enable_graph=True)
```
If you were using `enable_graph=True` in v2:
- Remove `enable_graph` from all API calls
- Remove `graph_store` from OSS configuration
- Entity relationships are now consumed through retrieval ranking, not exposed as a separate `relations` array
**Project-level (default for all operations):**
```python
client.project.update(enable_graph=True)
```
```javascript
await client.updateProject({ enable_graph: true });
```
### Relation Structure
Each relation in the response contains:
| Field | Type | Description |
|-------|------|-------------|
| `source` | string | Source entity name |
| `source_type` | string | Source entity type (e.g., "Person") |
| `relationship` | string | Relationship label (e.g., "lives_in") |
| `target` | string | Target entity name |
| `target_type` | string | Target entity type (e.g., "City") |
| `score` | number | Confidence score |
**Example:**
```json
{
"relations": [
{
"source": "Joseph",
"source_type": "Person",
"relationship": "lives_in",
"target": "Seattle",
"target_type": "City",
"score": 0.92
}
]
}
```
### Technical Notes
- Graph Memory adds processing time; see docs for current plan availability
- Works optimally with rich conversation histories containing entity relationships
- Best suited for long-running assistants tracking evolving information
- Graph writes and reads toggle independently per request
- Multi-agent context supported via `user_id`, `agent_id`, `run_id` scoping
- Add operations are asynchronous; graph metadata may not be immediately available
See the [v2 to v3 migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for details.
---
@@ -160,7 +94,7 @@ client.project.update(custom_categories=new_categories)
```
```javascript
await client.updateProject({ custom_categories: new_categories });
await client.updateProject({ customCategories: newCategories });
```
**Retrieve active categories:**
@@ -185,7 +119,7 @@ client.project.update(custom_instructions="Your guidelines here...")
```
```javascript
await client.updateProject({ custom_instructions: "Your guidelines here..." });
await client.updateProject({ customInstructions: "Your guidelines here..." });
```
### Template Structure
@@ -229,7 +163,7 @@ client.project.update(retrieval_criteria=retrieval_criteria)
```typescript
await client.updateProject({
retrieval_criteria: [
retrievalCriteria: [
{ name: 'joy', description: 'Positive emotions', weight: 3 },
{ name: 'urgency', description: 'Time-sensitive items', weight: 4 },
],
@@ -281,7 +215,7 @@ for item in feedback_data:
```typescript
await client.feedback('mem-123', {
feedback: 'POSITIVE',
feedback_reason: 'Accurately captured dietary preference',
feedbackReason: 'Accurately captured dietary preference',
});
```
@@ -27,7 +27,7 @@ from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from mem0 import MemoryClient
llm = ChatOpenAI(model="gpt-4.1-nano-2025-04-14")
llm = ChatOpenAI(model="gpt-5-mini")
mem0 = MemoryClient()
prompt = ChatPromptTemplate.from_messages([
@@ -128,7 +128,7 @@ import { createMem0 } from "@mem0/vercel-ai-provider";
const mem0 = createMem0();
const { text } = await generateText({
model: mem0("gpt-4-turbo", { user_id: "borat" }),
model: mem0("gpt-5-mini", { user_id: "borat" }),
prompt: "Suggest me a good car to buy!",
});
```
@@ -167,7 +167,7 @@ agent = Agent(
Use search_memory to recall past conversations.
Use save_memory to store important information.""",
tools=[search_memory, save_memory],
model="gpt-4.1-nano-2025-04-14"
model="gpt-5-mini"
)
result = Runner.run_sync(agent, "I love Italian food and I'm planning a trip to Rome next month")
@@ -183,21 +183,21 @@ travel_agent = Agent(
name="Travel Planner",
instructions="You are a travel planning specialist. Use search_memory and save_memory tools.",
tools=[search_memory, save_memory],
model="gpt-4.1-nano-2025-04-14"
model="gpt-5-mini"
)
health_agent = Agent(
name="Health Advisor",
instructions="You are a health and wellness advisor. Use search_memory and save_memory tools.",
tools=[search_memory, save_memory],
model="gpt-4.1-nano-2025-04-14"
model="gpt-5-mini"
)
triage_agent = Agent(
name="Personal Assistant",
instructions="""Route travel questions to Travel Planner, health questions to Health Advisor.""",
handoffs=[travel_agent, health_agent],
model="gpt-4.1-nano-2025-04-14"
model="gpt-5-mini"
)
result = Runner.run_sync(triage_agent, "Plan a healthy meal for my Italy trip")
@@ -254,7 +254,7 @@ from langchain_openai import ChatOpenAI
from mem0 import MemoryClient
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
llm = ChatOpenAI(model="gpt-4")
llm = ChatOpenAI(model="gpt-5-mini")
mem0 = MemoryClient()
class State(TypedDict):
@@ -319,7 +319,7 @@ memory = Mem0Memory.from_client(
from llama_index.core.agent import FunctionCallingAgent
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-4")
llm = OpenAI(model="gpt-5-mini")
agent = FunctionCallingAgent.from_tools(
tools=[],
llm=llm,
@@ -352,7 +352,7 @@ USER_ID = "alice"
agent = ConversableAgent(
"chatbot",
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
llm_config={"config_list": [{"model": "gpt-5-mini", "api_key": os.environ["OPENAI_API_KEY"]}]},
code_execution_config=False,
human_input_mode="NEVER",
)
+2 -2
View File
@@ -59,11 +59,11 @@ const messages = [
{"role": "user", "content": "I'm a vegetarian and allergic to nuts."},
{"role": "assistant", "content": "Got it! I'll remember your dietary preferences."}
];
await client.add(messages, { user_id: "user123" });
await client.add(messages, { userId: "user123" });
// Search memories
const results = await client.search("What are my dietary restrictions?", {
user_id: "user123"
filters: { user_id: "user123" }
});
console.log(results);
```
+96 -53
View File
@@ -40,16 +40,12 @@ client.add(messages, user_id="alice")
# With metadata
client.add(messages, user_id="alice", metadata={"source": "onboarding"})
# With graph memory
client.add(messages, user_id="alice", enable_graph=True)
```
**TypeScript:**
```typescript
await client.add(messages, { user_id: "alice" });
await client.add(messages, { user_id: "alice", metadata: { source: "onboarding" } });
await client.add(messages, { user_id: "alice", enable_graph: true });
await client.add(messages, { userId: "alice" });
await client.add(messages, { userId: "alice", metadata: { source: "onboarding" } });
```
### Parameters
@@ -61,32 +57,14 @@ await client.add(messages, { user_id: "alice", enable_graph: true });
| `agent_id` | string | Agent identifier |
| `run_id` | string | Session identifier |
| `metadata` | object | Custom key-value pairs |
| `enable_graph` | boolean | Activate knowledge graph |
| `infer` | boolean | If `false`, store raw text without inference (default: `true`) |
| `immutable` | boolean | Prevents modification after creation |
| `expiration_date` | string | Auto-expiry date (`YYYY-MM-DD`) |
| `includes` | string | Preference filters for inclusion |
| `excludes` | string | Preference filters for exclusion |
| `async_mode` | boolean | Async processing (default: `true`). Set `false` to wait |
### Advanced Add Options
```python
# Immutable -- cannot be modified or overwritten
client.add(messages, user_id="alice", immutable=True)
# Expiring memory
client.add(messages, user_id="alice", expiration_date="2025-12-31")
# Selective extraction
client.add(messages, user_id="alice", includes="dietary preferences", excludes="payment info")
# Agent + session scoping
client.add(messages, user_id="alice", agent_id="nutrition-agent", run_id="session-456")
# Synchronous processing (wait for completion)
client.add(messages, user_id="alice", async_mode=False)
# Raw text -- skip LLM inference
client.add(
[{"role": "user", "content": "User prefers dark mode."}],
@@ -101,7 +79,7 @@ client.add(
**Python:**
```python
results = client.search("dietary preferences?", user_id="alice")
results = client.search("dietary preferences?", filters={"user_id": "alice"})
# With filters and reranking
results = client.search(
@@ -111,20 +89,14 @@ results = client.search(
rerank=True,
threshold=0.5
)
# With graph relations
results = client.search("colleagues", user_id="alice", enable_graph=True)
# Keyword search
results = client.search("vegetarian", user_id="alice", keyword_search=True)
```
**TypeScript:**
```typescript
const results = await client.search("dietary preferences", { user_id: "alice" });
const results = await client.search("dietary preferences", { filters: { user_id: "alice" } });
const results = await client.search("work experience", {
filters: { AND: [{ user_id: "alice" }, { categories: { contains: "professional_details" } }] },
top_k: 5,
topK: 5,
rerank: true,
});
```
@@ -134,19 +106,17 @@ const results = await client.search("work experience", {
| Name | Type | Description |
|------|------|-------------|
| `query` | string | Natural language search query |
| `user_id` | string | Filter by user |
| `filters` | object | V2 filter object (AND/OR operators) |
| `top_k` | number | Number of results (default: 10) |
| `rerank` | boolean | Enable reranking for better relevance |
| `threshold` | number | Minimum similarity score (default: 0.3) |
| `keyword_search` | boolean | Use keyword-based search |
| `enable_graph` | boolean | Include graph relations |
| `filters` | object | Filter object (AND/OR operators). Use `{"user_id": "..."}` to filter by user |
| `top_k` | number | Number of results (default: 10 for Platform) |
| `rerank` | boolean | Enable reranking for better relevance (default: `false`) |
| `threshold` | number | Minimum similarity score (default: 0.1) |
### Common Filter Patterns
**Python:**
```python
# Single user (shorthand)
client.search("query", user_id="alice")
# Single user filter
filters={"user_id": "alice"}
# OR across agents
filters={"OR": [{"user_id": "alice"}, {"agent_id": {"in": ["travel-agent", "sports-agent"]}}]}
@@ -179,6 +149,21 @@ filters={"AND": [
]}
```
**TypeScript:**
```typescript
// Single user filter
filters: { user_id: "alice" }
// OR across agents
filters: { OR: [{ user_id: "alice" }, { agent_id: { in: ["travel-agent", "sports-agent"] } }] }
// Category filtering (partial match)
filters: { AND: [{ user_id: "alice" }, { categories: { contains: "finance" } }] }
// Category filtering (exact match)
filters: { AND: [{ user_id: "alice" }, { categories: { in: ["personal_information"] } }] }
```
---
## get() / getAll() -- Retrieve Memories
@@ -189,7 +174,7 @@ filters={"AND": [
memory = client.get(memory_id="ea925981-...")
# All memories for a user
memories = client.get_all(filters={"AND": [{"user_id": "alice"}]})
memories = client.get_all(filters={"user_id": "alice"})
# With date range
memories = client.get_all(
@@ -198,15 +183,12 @@ memories = client.get_all(
{"created_at": {"gte": "2024-07-01", "lte": "2024-07-31"}}
]}
)
# With graph data
memories = client.get_all(filters={"AND": [{"user_id": "alice"}]}, enable_graph=True)
```
**TypeScript:**
```typescript
const memory = await client.get("ea925981-...");
const memories = await client.getAll({ filters: { AND: [{ user_id: "alice" }] } });
const memories = await client.getAll({ filters: { user_id: "alice" } });
```
**Note:** `get_all` requires at least one of `user_id`, `agent_id`, `app_id`, or `run_id` in filters.
@@ -226,8 +208,6 @@ client.update(memory_id="ea925981-...", text="Updated", metadata={"verified": Tr
await client.update("ea925981-...", { text: "Updated: vegan since 2024" });
```
Cannot update immutable memories.
---
## delete() / deleteAll() -- Remove Memories
@@ -241,7 +221,7 @@ client.delete_all(user_id="alice") # Irreversible bulk delete
**TypeScript:**
```typescript
await client.delete("ea925981-...");
await client.deleteAll({ user_id: "alice" });
await client.deleteAll({ userId: "alice" });
```
---
@@ -301,10 +281,73 @@ data = client.get_memory_export(memory_export_id=export["id"])
2. **SQL operators rejected** -- use `gte`, `lt`, etc. Not `>=`, `<`.
3. **Metadata filtering is limited** -- only top-level keys with `eq`, `contains`, `ne`.
4. **Wildcard `*` excludes null** -- only matches non-null values.
5. **Default threshold is 0.3** -- increase for stricter matching.
5. **Default threshold is 0.1** -- increase for stricter matching.
6. **Async processing** -- memories process asynchronously. Wait 2-3s after `add()` before searching.
7. **Immutable memories** -- cannot be updated or deleted once created.
## Naming Conventions
Python uses `snake_case` (`user_id`, `memory_id`, `get_all`). TypeScript uses `camelCase` for methods (`getAll`, `deleteAll`, `batchUpdate`) but `snake_case` for API parameters (`user_id`, `agent_id`).
Python uses `snake_case` everywhere (`user_id`, `memory_id`, `get_all`). TypeScript uses `camelCase` for methods (`getAll`, `deleteAll`, `batchUpdate`) and top-level parameters (`userId`, `topK`, `pageSize`), but filter keys use `snake_case` (`user_id`, `agent_id`).
---
## v2 to v3 Migration
### Breaking Changes in v3
**1. Entity IDs in search() and getAll()**
v3 requires entity IDs (`user_id`, `agent_id`, `run_id`) inside `filters` instead of as top-level parameters:
```python
# v2 (deprecated)
client.search("query", user_id="alice")
client.get_all(user_id="alice")
# v3
client.search("query", filters={"user_id": "alice"})
client.get_all(filters={"user_id": "alice"})
```
```typescript
// v2 (deprecated)
await client.search("query", { user_id: "alice" });
await client.getAll({ user_id: "alice" });
// v3
await client.search("query", { filters: { user_id: "alice" } });
await client.getAll({ filters: { user_id: "alice" } });
```
**2. TypeScript Parameter Naming**
v3 TypeScript uses camelCase for all parameters:
| v2 | v3 |
|----|-----|
| `user_id` | `userId` |
| `agent_id` | `agentId` |
| `run_id` | `runId` |
| `top_k` | `topK` |
| `page_size` | `pageSize` |
**3. Default Values Changed**
| Parameter | v2 Default | v3 Default |
|-----------|------------|------------|
| `threshold` | 0.3 | 0.1 |
| `rerank` | (not specified) | `false` |
**4. Removed Parameters**
The following parameters are no longer supported:
| Parameter | Status |
|-----------|--------|
| `enable_graph` | Removed from add/search/getAll |
| `keyword_search` | Removed from search |
| `filter_memories` | Removed |
| `immutable` | Removed from add |
| `expiration_date` | Removed from add |
| `includes` | Removed from add |
| `excludes` | Removed from add |
| `async_mode` | Removed from add |
+24 -24
View File
@@ -39,7 +39,7 @@ Use these known facts about the user to personalize your response:
{context if context else 'No prior context yet.'}"""
response = openai_client.chat.completions.create(
model="gpt-4.1-nano-2025-04-14",
model="gpt-5-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_input},
@@ -72,14 +72,14 @@ const openai = new OpenAI();
async function chat(userInput: string, userId: string): Promise<string> {
// 1. Retrieve relevant memories
const memories = await mem0.search(userInput, { user_id: userId });
const memories = await mem0.search(userInput, { filters: { user_id: userId } });
const context = memories.results
?.map((m: any) => `- ${m.memory}`)
.join('\n') || 'No prior context yet.';
// 2. Generate response with memory context
const response = await openai.chat.completions.create({
model: 'gpt-4.1-nano-2025-04-14',
model: 'gpt-5-mini',
messages: [
{ role: 'system', content: `You are Ray, a personal fitness coach.\nUser context:\n${context}` },
{ role: 'user', content: userInput },
@@ -90,7 +90,7 @@ async function chat(userInput: string, userId: string): Promise<string> {
// 3. Store interaction
await mem0.add(
[{ role: 'user', content: userInput }, { role: 'assistant', content: reply }],
{ user_id: userId }
{ userId: userId }
);
return reply;
}
@@ -182,7 +182,7 @@ await client.updateProject({
async function logInteraction(userId: string, message: string, priority = 'normal') {
await client.add(
[{ role: 'user', content: message }],
{ user_id: userId, metadata: { priority, source: 'support_chat' } }
{ userId: userId, metadata: { priority, source: 'support_chat' } }
);
}
@@ -230,7 +230,7 @@ def consult(user_id: str, question: str) -> str:
context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])])
response = openai_client.chat.completions.create(
model="gpt-4.1-nano-2025-04-14",
model="gpt-5-mini",
messages=[
{"role": "system", "content": f"You are a health coach. Patient context:\n{context}"},
{"role": "user", "content": question},
@@ -264,20 +264,20 @@ const openai = new OpenAI();
async function savePatientInfo(userId: string, info: string) {
await mem0.add(
[{ role: 'user', content: info }],
{ user_id: userId, run_id: 'healthcare_session', metadata: { type: 'patient_information' } }
{ userId: userId, runId: 'healthcare_session', metadata: { type: 'patient_information' } }
);
}
async function consult(userId: string, question: string): Promise<string> {
const memories = await mem0.search(question, {
user_id: userId,
top_k: 5,
filters: { user_id: userId },
topK: 5,
threshold: 0.7,
});
const context = memories.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
const response = await openai.chat.completions.create({
model: 'gpt-4.1-nano-2025-04-14',
model: 'gpt-5-mini',
messages: [
{ role: 'system', content: `You are a health coach. Patient context:\n${context}` },
{ role: 'user', content: question },
@@ -287,7 +287,7 @@ async function consult(userId: string, question: string): Promise<string> {
await mem0.add(
[{ role: 'user', content: question }, { role: 'assistant', content: reply }],
{ user_id: userId, run_id: 'healthcare_session' }
{ userId: userId, runId: 'healthcare_session' }
);
return reply;
}
@@ -333,7 +333,7 @@ def draft_content(user_id: str, topic: str) -> str:
style_context = "\n".join([f"- {m['memory']}" for m in prefs.get("results", [])])
response = openai_client.chat.completions.create(
model="gpt-4.1-nano-2025-04-14",
model="gpt-5-mini",
messages=[
{"role": "system", "content": f"Write content matching these style preferences:\n{style_context}"},
{"role": "user", "content": f"Write a blog post about: {topic}"},
@@ -359,7 +359,7 @@ const openai = new OpenAI();
async function storePreferences(userId: string, preferences: string) {
await mem0.add(
[{ role: 'user', content: preferences }],
{ user_id: userId, run_id: 'editing_session', metadata: { type: 'preferences' } }
{ userId: userId, runId: 'editing_session', metadata: { type: 'preferences' } }
);
}
@@ -370,7 +370,7 @@ async function draftContent(userId: string, topic: string): Promise<string> {
const styleContext = prefs.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
const response = await openai.chat.completions.create({
model: 'gpt-4.1-nano-2025-04-14',
model: 'gpt-5-mini',
messages: [
{ role: 'system', content: `Write content matching these preferences:\n${styleContext}` },
{ role: 'user', content: `Write a blog post about: ${topic}` },
@@ -465,10 +465,10 @@ async function storeScopedMemory(
userId: string, agentId: string, runId: string, appId: string
) {
await client.add(messages, {
user_id: userId,
agent_id: agentId,
run_id: runId,
app_id: appId,
userId: userId,
agentId: agentId,
runId: runId,
appId: appId,
});
}
@@ -520,7 +520,7 @@ def personalized_search(user_id: str, query: str, search_results: list) -> str:
user_context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])])
response = openai_client.chat.completions.create(
model="gpt-4.1-nano-2025-04-14",
model="gpt-5-mini",
messages=[
{"role": "system", "content": f"Personalize search results using user context:\n{user_context}"},
{"role": "user", "content": f"Query: {query}\n\nSearch results:\n{search_results}"},
@@ -551,11 +551,11 @@ const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
const openai = new OpenAI();
async function personalizedSearch(userId: string, query: string, searchResults: string[]): Promise<string> {
const memories = await mem0.search(query, { user_id: userId, top_k: 5 });
const memories = await mem0.search(query, { filters: { user_id: userId }, topK: 5 });
const context = memories.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
const response = await openai.chat.completions.create({
model: 'gpt-4.1-nano-2025-04-14',
model: 'gpt-5-mini',
messages: [
{ role: 'system', content: `Personalize results using user context:\n${context}` },
{ role: 'user', content: `Query: ${query}\nResults: ${searchResults.join(', ')}` },
@@ -563,7 +563,7 @@ async function personalizedSearch(userId: string, query: string, searchResults:
});
const reply = response.choices[0].message.content!;
await mem0.add([{ role: 'user', content: query }], { user_id: userId });
await mem0.add([{ role: 'user', content: query }], { userId: userId });
return reply;
}
```
@@ -631,14 +631,14 @@ const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
async function storeEmail(userId: string, sender: string, subject: string, body: string, date: string) {
await client.add(
[{ role: 'user', content: `Email from ${sender}: ${subject}\n\n${body}` }],
{ user_id: userId, metadata: { email_type: 'incoming', sender, subject, date } }
{ userId: userId, metadata: { email_type: 'incoming', sender, subject, date } }
);
}
async function searchEmails(userId: string, query: string) {
return client.search(query, {
filters: { AND: [{ user_id: userId }, { categories: { contains: 'email' } }] },
top_k: 10,
topK: 10,
});
}
```