[docs] Minor Docs fixes ( enhancements , restructure ) (#3748)
This commit is contained in:
@@ -3,10 +3,96 @@ title: 'Add Memories'
|
||||
openapi: post /v1/memories/
|
||||
---
|
||||
|
||||
## Graph Memory
|
||||
Add new facts, messages, or metadata to a user’s memory store. The Add Memories endpoint accepts either raw text or conversational turns and commits them asynchronously so the memory is ready for later search, retrieval, and graph queries.
|
||||
|
||||
To enable graph-based memory relationships, pass the `enable_graph=True` parameter. This creates relationships between entities in your memories for more contextual retrieval.
|
||||
## Endpoint
|
||||
|
||||
<Note>
|
||||
Learn more in the [Graph Memory documentation](/platform/features/graph-memory).
|
||||
</Note>
|
||||
- **Method**: `POST`
|
||||
- **URL**: `/v1/memories/`
|
||||
- **Content-Type**: `application/json`
|
||||
|
||||
Memories are processed asynchronously by default. The response contains queued events you can track while the platform finalizes enrichment.
|
||||
|
||||
## Required headers
|
||||
|
||||
| Header | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `Authorization: Bearer <MEM0_API_KEY>` | Yes | API key scoped to your workspace. |
|
||||
| `Accept: application/json` | Yes | Ensures a JSON response. |
|
||||
|
||||
## Request body
|
||||
|
||||
Provide at least one message or direct memory string. Most callers supply `messages` so Mem0 can infer structured memories as part of ingestion.
|
||||
|
||||
<CodeGroup>
|
||||
```json Basic request
|
||||
{
|
||||
"user_id": "alice",
|
||||
"messages": [
|
||||
{ "role": "user", "content": "I moved to Austin last month." }
|
||||
],
|
||||
"metadata": {
|
||||
"source": "onboarding_form"
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Common fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `user_id` | string | No* | Associates the memory with a user. Provide when you want the memory scoped to a specific identity. |
|
||||
| `messages` | array | No* | Conversation turns for Mem0 to infer memories from. Each object should include `role` and `content`. |
|
||||
| `memory` | string | No* | Direct memory text when you do not need inference. |
|
||||
| `metadata` | object | Optional | Custom key/value metadata (e.g., `{"topic": "preferences"}`). |
|
||||
| `infer` | boolean (default `true`) | Optional | Set to `false` to skip inference and store the provided text as-is. |
|
||||
| `async_mode` | boolean (default `true`) | Optional | Controls asynchronous processing. Most clients leave this enabled. |
|
||||
| `output_format` | string (default `v1.1`) | Optional | Response format. `v1.1` wraps results in a `results` array. |
|
||||
|
||||
> \* Provide either `messages` or `memory` to describe what you are storing. For scoped memories, include `user_id`. You can also attach `agent_id`, `app_id`, `run_id`, `project_id`, or `org_id` to refine ownership.
|
||||
|
||||
## Response
|
||||
|
||||
Successful requests return an array of events queued for processing. Each event includes the generated memory text and an identifier you can persist for auditing.
|
||||
|
||||
<CodeGroup>
|
||||
```json 200 response
|
||||
[
|
||||
{
|
||||
"id": "mem_01JF8ZS4Y0R0SPM13R5R6H32CJ",
|
||||
"event": "ADD",
|
||||
"data": {
|
||||
"memory": "The user moved to Austin in 2025."
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json 400 response
|
||||
{
|
||||
"error": "400 Bad Request",
|
||||
"details": {
|
||||
"message": "Invalid input data. Please refer to the memory creation documentation at https://docs.mem0.ai/platform/quickstart#4-1-create-memories for correct formatting and required fields."
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Graph relationships
|
||||
|
||||
Add Memories can enrich the knowledge graph on write. Set `enable_graph: true` to create entity nodes and relationships for the stored memory. Use this when you want downstream `get_all` or search calls to traverse connected entities.
|
||||
|
||||
<CodeGroup>
|
||||
```json Graph-aware request
|
||||
{
|
||||
"user_id": "alice",
|
||||
"messages": [
|
||||
{ "role": "user", "content": "I met with Dr. Lee at General Hospital." }
|
||||
],
|
||||
"enable_graph": true
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
The response follows the same format, and related entities become available in [Graph Memory](/platform/features/graph-memory) queries.
|
||||
|
||||
@@ -164,7 +164,7 @@ Ray can plan workouts that avoid aggravating Max's knee, without pulling in race
|
||||
Run the basic loop for a week and check what's stored:
|
||||
|
||||
```python
|
||||
memories = mem0_client.get_all(user_id="max")
|
||||
memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]})
|
||||
print([m["memory"] for m in memories["results"]])
|
||||
# Output: ["Max wants to run marathon under 4 hours", "hey", "lol ok", "cool thanks", "gtg bye"]
|
||||
|
||||
@@ -202,7 +202,7 @@ Now chat again:
|
||||
chat("hey how's it going", user_id="max")
|
||||
chat("I prefer trail running over roads", user_id="max")
|
||||
|
||||
memories = mem0_client.get_all(user_id="max")
|
||||
memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]})
|
||||
print([m["memory"] for m in memories["results"]])
|
||||
# Output: ["Max wants to run marathon under 4 hours", "Max prefers trail running over roads"]
|
||||
|
||||
@@ -411,7 +411,7 @@ Max changes his goal from sub-4 to sub-3:45:
|
||||
|
||||
```python
|
||||
# Find the old memory
|
||||
memories = mem0_client.get_all(user_id="max")
|
||||
memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]})
|
||||
goal_memory = [m for m in memories["results"] if "sub-4" in m["memory"]][0]
|
||||
|
||||
# Update it
|
||||
|
||||
@@ -126,7 +126,7 @@ async def get_all_memory(
|
||||
) -> str:
|
||||
"""Retrieve all memories from Mem0"""
|
||||
user_id = context.context.user_id or "default_user"
|
||||
memories = await client.get_all(user_id=user_id)
|
||||
memories = await client.get_all(filters={"AND": [{"user_id": user_id}]})
|
||||
results = '\n'.join([result["memory"] for result in memories["results"]])
|
||||
return str(results)
|
||||
```
|
||||
|
||||
@@ -75,14 +75,18 @@ await client.search("What is Alice's favorite sport?", { user_id: "alice" });
|
||||
|
||||
Retrieve all memories for a user asynchronously.
|
||||
|
||||
<Callout type="warning" title="Filters Required">
|
||||
`get_all()` now requires filters to be specified.
|
||||
</Callout>
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
await client.get_all(user_id="alice")
|
||||
await client.get_all(filters={"AND": [{"user_id": "alice"}]})
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
await client.getAll({ user_id: "alice" });
|
||||
await client.getAll({ filters: {"AND": [{"user_id": "alice"}]} });
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
@@ -161,12 +161,14 @@ You can also retrieve all processed memories at any time:
|
||||
|
||||
```python Python
|
||||
# Retrieve all memories for a user
|
||||
memories = client.get_all(user_id="user-123")
|
||||
# Note: get_all now requires filters
|
||||
memories = client.get_all(filters={"AND": [{"user_id": "user-123"}]})
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
// Retrieve all memories for a user
|
||||
const memories = await client.getAll({ user_id: "user-123" });
|
||||
// Note: getAll now requires filters
|
||||
const memories = await client.getAll({ filters: {"AND": [{"user_id": "user-123"}]} });
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
@@ -302,7 +302,7 @@ messages = [
|
||||
|
||||
# Add the messages and check extracted memories
|
||||
result = client.add(messages, user_id="test_user")
|
||||
memories = client.get_all(user_id="test_user")
|
||||
memories = client.get_all(filters={"AND": [{"user_id": "test_user"}]})
|
||||
|
||||
# Review if the right information was extracted
|
||||
for memory in memories:
|
||||
|
||||
@@ -67,10 +67,14 @@ client.search("What is Alice's favorite sport?", user_id="alice")
|
||||
|
||||
You can retrieve all memories using the `get_all` method.
|
||||
|
||||
<Callout type="warning" title="Filters Required">
|
||||
`get_all()` now requires filters to be specified.
|
||||
</Callout>
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
client.get_all(query="What is Alice's favorite sport?", user_id="alice")
|
||||
client.get_all(filters={"AND": [{"user_id": "alice"}]})
|
||||
```
|
||||
|
||||
```json Output
|
||||
|
||||
@@ -187,12 +187,16 @@ console.log(results);
|
||||
|
||||
When retrieving all memories, Graph Memory provides additional relationship context:
|
||||
|
||||
<Callout type="warning" title="Filters Required">
|
||||
`get_all()` now requires filters to be specified.
|
||||
</Callout>
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
# Get all memories with graph context
|
||||
memories = client.get_all(
|
||||
user_id="joseph",
|
||||
filters={"AND": [{"user_id": "joseph"}]},
|
||||
enable_graph=True
|
||||
)
|
||||
|
||||
@@ -202,7 +206,7 @@ print(memories)
|
||||
```javascript JavaScript
|
||||
// Get all memories with graph context
|
||||
const memories = await client.getAll({
|
||||
user_id: "joseph",
|
||||
filters: {"AND": [{"user_id": "joseph"}]},
|
||||
enable_graph: true
|
||||
});
|
||||
|
||||
|
||||
@@ -1,515 +1,416 @@
|
||||
---
|
||||
title: Memory Filters v2
|
||||
description: This guide covers the filtering system for retrieving and searching memories. You can filter by user sessions, agents, applications, content categories, and time ranges.
|
||||
title: Memory Filters
|
||||
description: Query and retrieve memories with powerful filtering capabilities. Filter by users, agents, content, time ranges, and more.
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
> Memory filters provide a flexible way to query and retrieve specific memories from your memory store. You can filter by users, agents, content categories, time ranges, and combine multiple conditions using logical operators.
|
||||
|
||||
### Memories for a specific user
|
||||
## When to use filters
|
||||
|
||||
```json
|
||||
When working with large-scale memory stores, you need precise control over which memories to retrieve. Filters help you:
|
||||
|
||||
* **Isolate user data**: Retrieve memories for specific users while maintaining privacy
|
||||
* **Debug and audit**: Export specific memory subsets for analysis
|
||||
* **Target content**: Find memories with specific categories or metadata
|
||||
* **Time-based queries**: Retrieve memories within specific date ranges
|
||||
* **Performance optimization**: Reduce query complexity by pre-filtering
|
||||
|
||||
<Callout type="info" icon="info-circle" color="#7A5DFF">
|
||||
Filters were introduced in v1.0.0 to provide precise control over memory retrieval.
|
||||
</Callout>
|
||||
|
||||
## Filter structure
|
||||
|
||||
Filters use a nested JSON structure with logical operators at the root:
|
||||
|
||||
```python
|
||||
# Basic structure
|
||||
{
|
||||
"AND": [
|
||||
{ "user_id": "u1" }
|
||||
]
|
||||
"AND": [ # or "OR", "NOT"
|
||||
{ "field": "value" },
|
||||
{ "field": { "operator": "value" } }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### User memories across all runs
|
||||
|
||||
```json
|
||||
{
|
||||
"AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "run_id": "*" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
Excludes null run_id values
|
||||
</Note>
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Filter Structure
|
||||
|
||||
* Root must be **`AND`** or **`OR`** (or **`NOT`**) containing an **array** of conditions.
|
||||
* A **condition** is either a simple equality `{ "user_id": "u1" }` or an operator clause `{ "created_at": { "gte": "..." } }`.
|
||||
|
||||
```json
|
||||
{
|
||||
"AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "run_id": "*" },
|
||||
{ "created_at": { "lt": "2025-06-01T00:00:00Z" } },
|
||||
{ "categories": { "in": ["finance", "health"] } }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Accepted shapes**
|
||||
|
||||
```json
|
||||
{ "AND": [ /* conditions... */ ] }
|
||||
{ "OR": [ /* conditions... */ ] }
|
||||
{ "NOT": [ /* conditions... */ ] }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Available Fields
|
||||
|
||||
Use these to scope memories to primary entities:
|
||||
|
||||
| Field | Meaning |
|
||||
| ---------- | ----------------------- |
|
||||
| `user_id` | Filter by user/consumer |
|
||||
| `agent_id` | Filter by AI agent |
|
||||
| `app_id` | Filter by application |
|
||||
| `run_id` | Filter by session/run |
|
||||
|
||||
---
|
||||
|
||||
## Wildcards
|
||||
|
||||
Wildcards (`"*"`) match **any non-null** value of that field. This means if a field is null, it won't be included in the results.
|
||||
|
||||
<Note>
|
||||
Asterisks (`*`) exclude null values - only non-null fields will be matched
|
||||
</Note>
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "*" } ] } // any record with a user_id
|
||||
{ "AND": [ { "user_id": "*" }, { "run_id": "*" } ] } // require both non-null
|
||||
{ "OR": [ { "user_id": "*" }, { "run_id": "*" } ] } // either non-null
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Operators and Fields
|
||||
|
||||
**Available Fields**
|
||||
|
||||
* **Entities**: `user_id`, `agent_id`, `app_id`, `run_id`
|
||||
* **Time**: `created_at`, `updated_at`, `timestamp`
|
||||
* **Content**: `categories`, `metadata`, `keywords`
|
||||
* **Special**: `memory_ids` (array of IDs)
|
||||
|
||||
**Operators**
|
||||
|
||||
* `in`: Matches any of the values specified
|
||||
* `gte`: Greater than or equal to
|
||||
* `lte`: Less than or equal to
|
||||
* `gt`: Greater than
|
||||
* `lt`: Less than
|
||||
* `ne`: Not equal to
|
||||
* `contains`: Case-sensitive containment check
|
||||
* `icontains`: Case-insensitive containment check
|
||||
* `*`: Wildcard character that matches everything
|
||||
|
||||
**Field Structures**
|
||||
|
||||
```json
|
||||
// Entity fields
|
||||
{ "user_id": "u1" }
|
||||
{ "agent_id": "a1" }
|
||||
{ "app_id": "app1" }
|
||||
{ "run_id": "run1" }
|
||||
|
||||
// Time fields
|
||||
{ "created_at": { "gte": "2025-01-01T00:00:00Z" } }
|
||||
{ "updated_at": { "lt": "2025-02-01T00:00:00Z" } }
|
||||
|
||||
// Categories (exact matching)
|
||||
{ "categories": { "in": ["personal_information", "finance"] } }
|
||||
// Categories (partial matching)
|
||||
{ "categories": { "contains": "finance" } }
|
||||
|
||||
// Metadata (exact key-value match)
|
||||
{ "metadata": { "key": "value" } }
|
||||
|
||||
// Keywords (text search)
|
||||
{ "keywords": { "icontains": "budget" } }
|
||||
|
||||
// Memory IDs
|
||||
{ "memory_ids": ["m1", "m2", "m3"] }
|
||||
```
|
||||
|
||||
**Notes**
|
||||
|
||||
* `eq` is implied: `{ "user_id": "u1" }` ≡ `{ "user_id": { "eq": "u1" } }`
|
||||
* `ne` includes **NULLs**: results where the field is either **not equal** or **missing**
|
||||
* For `categories`, use `contains` for partial matching or `in` for exact matching
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### User and Agent Filters
|
||||
|
||||
**All memories for a specific user**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "u1" } ] }
|
||||
```
|
||||
|
||||
**All memories across all users (no agent/app/run)**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "*" } ] }
|
||||
```
|
||||
|
||||
<Note>
|
||||
Excludes null user_id values
|
||||
</Note>
|
||||
|
||||
**User memories across all runs**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "u1" }, { "run_id": "*" } ] }
|
||||
```
|
||||
|
||||
<Note>
|
||||
Excludes null run_id values
|
||||
</Note>
|
||||
|
||||
**All memories for a specific agent**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "agent_id": "a1" } ] }
|
||||
```
|
||||
|
||||
**Agent memories across all runs**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "agent_id": "a1" }, { "run_id": "*" } ] }
|
||||
```
|
||||
|
||||
<Note>
|
||||
Excludes null run_id values
|
||||
</Note>
|
||||
|
||||
### Content and Text Filters
|
||||
|
||||
**Search for text in user's memory content (case-insensitive)**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "keywords": { "icontains": "pizza" } }
|
||||
] }
|
||||
```
|
||||
|
||||
**Search for text in user's memory content (case-sensitive)**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "keywords": { "contains": "BudgetQ1" } }
|
||||
] }
|
||||
```
|
||||
|
||||
**User memories with specific categories**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "categories": { "in": ["finance", "health"] } }
|
||||
] }
|
||||
```
|
||||
|
||||
**User memories with specific metadata**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "metadata": { "foo": "bar" } }
|
||||
] }
|
||||
```
|
||||
|
||||
### Time-based Filters
|
||||
|
||||
**Memories created after a specific date**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "created_at": { "gt": "2025-01-01T00:00:00Z" } }
|
||||
] }
|
||||
```
|
||||
|
||||
**User memories within a date range**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "created_at": { "gte": "2025-01-01T00:00:00Z" } },
|
||||
{ "created_at": { "lt": "2025-02-01T00:00:00Z" } }
|
||||
] }
|
||||
```
|
||||
|
||||
**Memories updated within a time window**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "updated_at": { "gte": "2025-05-01T00:00:00Z" } },
|
||||
{ "updated_at": { "lte": "2025-05-31T23:59:59Z" } }
|
||||
] }
|
||||
```
|
||||
|
||||
### Advanced Filters
|
||||
|
||||
**Memories from multiple users**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": { "in": ["u1", "u2", "u3"] } } ] }
|
||||
```
|
||||
|
||||
|
||||
**Memories from either user or run**
|
||||
|
||||
```json
|
||||
{ "OR": [ { "user_id": "u1" }, { "run_id": "run1" } ] }
|
||||
```
|
||||
|
||||
**Memories that have both user and run (non-null)**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "*" }, { "run_id": "*" } ] }
|
||||
```
|
||||
|
||||
<Note>
|
||||
Excludes null user_id and run_id values
|
||||
</Note>
|
||||
|
||||
**User memories excluding specific categories**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "NOT": { "categories": { "in": ["spam", "test"] } } }
|
||||
] }
|
||||
```
|
||||
|
||||
**User memories by specific IDs**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "memory_ids": ["m1", "m2", "m3"] }
|
||||
] }
|
||||
```
|
||||
|
||||
**Complex filter: text + category + time**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "keywords": { "icontains": "invoice" } },
|
||||
{ "categories": { "in": ["finance"] } },
|
||||
{ "created_at": { "gte": "2025-03-01T00:00:00Z" } }
|
||||
] }
|
||||
```
|
||||
|
||||
### Comprehensive Filters
|
||||
|
||||
**All memories with non-null entities**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "*" },
|
||||
{ "agent_id": "*" },
|
||||
{ "run_id": "*" },
|
||||
{ "app_id": "*" }
|
||||
] }
|
||||
```
|
||||
|
||||
<Note>
|
||||
Excludes null values for all entity fields
|
||||
</Note>
|
||||
|
||||
**All memories (including null entities)**
|
||||
|
||||
```json
|
||||
{ "OR": [
|
||||
{ "user_id": "*" },
|
||||
{ "agent_id": "*" },
|
||||
{ "run_id": "*" },
|
||||
{ "app_id": "*" }
|
||||
] }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
**Single user memories**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "u1" } ] }
|
||||
```
|
||||
|
||||
**User memories across all runs**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "u1" }, { "run_id": "*" } ] }
|
||||
```
|
||||
|
||||
<Note>
|
||||
Excludes null run_id values
|
||||
</Note>
|
||||
|
||||
**All user memories (no agent/app/run)**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "*" } ] }
|
||||
```
|
||||
|
||||
<Note>
|
||||
Excludes null user_id values
|
||||
</Note>
|
||||
|
||||
**Agent with specific users**
|
||||
|
||||
```json
|
||||
{ "AND": [ { "agent_id": "a1" }, { "user_id": { "in": ["u1", "u2"] } } ] }
|
||||
```
|
||||
|
||||
**Search user's memory content (case-insensitive)**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "keywords": { "icontains": "budget" } }
|
||||
] }
|
||||
```
|
||||
|
||||
**Memories within date range**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "created_at": { "gte": "<from>" } },
|
||||
{ "created_at": { "lt": "<to>" } }
|
||||
] }
|
||||
```
|
||||
|
||||
**Exclude specific categories**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "NOT": { "categories": { "in": ["spam", "test"] } } }
|
||||
] }
|
||||
```
|
||||
|
||||
**Get user's specific memories by ID**
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "memory_ids": ["id1", "id2"] }
|
||||
] }
|
||||
```
|
||||
|
||||
---
|
||||
## Available fields and operators
|
||||
|
||||
### Entity fields
|
||||
| Field | Operators | Example |
|
||||
|-------|-----------|---------|
|
||||
| `user_id` | `=`, `!=`, `in`, `*` | `{"user_id": "user_123"}` |
|
||||
| `agent_id` | `=`, `!=`, `in`, `*` | `{"agent_id": "*"}` |
|
||||
| `app_id` | `=`, `!=`, `in`, `*` | `{"app_id": {"in": ["app1", "app2"]}}` |
|
||||
| `run_id` | `=`, `!=`, `in`, `*` | `{"run_id": "*"}` |
|
||||
|
||||
### Time fields
|
||||
| Field | Operators | Example |
|
||||
|-------|-----------|---------|
|
||||
| `created_at` | `>`, `>=`, `<`, `<=`, `=`, `!=` | `{"created_at": {"gte": "2024-01-01"}}` |
|
||||
| `updated_at` | `>`, `>=`, `<`, `<=`, `=`, `!=` | `{"updated_at": {"lt": "2024-12-31"}}` |
|
||||
| `timestamp` | `>`, `>=`, `<`, `<=`, `=`, `!=` | `{"timestamp": {"gt": "2024-01-01"}}` |
|
||||
|
||||
### Content fields
|
||||
| Field | Operators | Example |
|
||||
|-------|-----------|---------|
|
||||
| `categories` | `=`, `!=`, `in`, `contains` | `{"categories": {"in": ["finance"]}}` |
|
||||
| `metadata` | `=`, `!=` | `{"metadata": {"key": "value"}}` |
|
||||
| `keywords` | `contains`, `icontains` | `{"keywords": {"icontains": "invoice"}}` |
|
||||
|
||||
### Special fields
|
||||
| Field | Operators | Example |
|
||||
|-------|-----------|---------|
|
||||
| `memory_ids` | `in` | `{"memory_ids": ["id1", "id2"]}` |
|
||||
|
||||
<Callout type="warning" icon="exclamation-triangle" color="#F7B731">
|
||||
The `*` wildcard matches any non-null value. Records with null values for that field are excluded.
|
||||
</Callout>
|
||||
|
||||
## Common filter patterns
|
||||
|
||||
Use these ready-made filters to target typical retrieval scenarios without rebuilding logic from scratch.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Single user">
|
||||
```python
|
||||
# Narrow to one user's memories
|
||||
filters = {"AND": [{"user_id": "user_123"}]}
|
||||
memories = client.get_all(filters=filters)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="All users">
|
||||
```python
|
||||
# Wildcard skips null user_id entries
|
||||
filters = {"AND": [{"user_id": "*"}]}
|
||||
memories = client.get_all(filters=filters)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="User across all runs">
|
||||
```python
|
||||
# Pair a user filter with a run wildcard
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"run_id": "*"}
|
||||
]
|
||||
}
|
||||
memories = client.get_all(filters=filters)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Content search
|
||||
|
||||
Find memories containing specific text, categories, or metadata values.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Text search">
|
||||
```python
|
||||
# Case-insensitive match
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"keywords": {"icontains": "pizza"}}
|
||||
]
|
||||
}
|
||||
|
||||
# Case-sensitive match
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"keywords": {"contains": "Invoice_2024"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Categories">
|
||||
```python
|
||||
# Match against category list
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"categories": {"in": ["finance", "health"]}}
|
||||
]
|
||||
}
|
||||
|
||||
# Partial category match
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"categories": {"contains": "finance"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Metadata">
|
||||
```python
|
||||
# Pin to a metadata attribute
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"metadata": {"source": "email"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Time-based filtering
|
||||
|
||||
Retrieve memories within specific date ranges using time operators.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Date range">
|
||||
```python
|
||||
# Created in January 2024
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"created_at": {"gte": "2024-01-01T00:00:00Z"}},
|
||||
{"created_at": {"lt": "2024-02-01T00:00:00Z"}}
|
||||
]
|
||||
}
|
||||
|
||||
# Updated recently
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"updated_at": {"gte": "2024-12-01T00:00:00Z"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Multiple criteria
|
||||
|
||||
Combine various filters for complex queries across different dimensions.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Multiple users">
|
||||
```python
|
||||
# Expand scope to a short user list
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": {"in": ["user_1", "user_2", "user_3"]}}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="OR logic">
|
||||
```python
|
||||
# Return matches on either condition
|
||||
filters = {
|
||||
"OR": [
|
||||
{"user_id": "user_123"},
|
||||
{"run_id": "run_456"}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Exclude categories">
|
||||
```python
|
||||
# Wrap negative logic with NOT
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"NOT": {
|
||||
"categories": {"in": ["spam", "test"]}
|
||||
}}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Specific memory IDs">
|
||||
```python
|
||||
# Fetch a fixed set of memory IDs
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"memory_ids": ["mem_1", "mem_2", "mem_3"]}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="All entities populated">
|
||||
```python
|
||||
# Require every entity field to be non-null
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "*"},
|
||||
{"agent_id": "*"},
|
||||
{"run_id": "*"},
|
||||
{"app_id": "*"}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Advanced examples
|
||||
|
||||
Level up foundational patterns with compound filters that coordinate entity scope, tighten time windows, and weave in exclusion rules for high-precision retrievals.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Multi-dimensional filtering">
|
||||
```python
|
||||
# Invoice memories in Q1 2024
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"keywords": {"icontains": "invoice"}},
|
||||
{"categories": {"in": ["finance"]}},
|
||||
{"created_at": {"gte": "2024-01-01T00:00:00Z"}},
|
||||
{"created_at": {"lt": "2024-04-01T00:00:00Z"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Cross-entity relationships">
|
||||
```python
|
||||
# From specific agent, all users
|
||||
filters = {
|
||||
"AND": [
|
||||
{"agent_id": "finance_bot"},
|
||||
{"user_id": "*"}
|
||||
]
|
||||
}
|
||||
|
||||
# Any entity populated
|
||||
filters = {
|
||||
"OR": [
|
||||
{"user_id": "*"},
|
||||
{"agent_id": "*"},
|
||||
{"run_id": "*"},
|
||||
{"app_id": "*"}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Nested NOT/OR logic">
|
||||
```python
|
||||
# User memories from 2024, excluding spam and test
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"created_at": {"gte": "2024-01-01T00:00:00Z"}},
|
||||
{"NOT": {
|
||||
"OR": [
|
||||
{"categories": {"in": ["spam"]}},
|
||||
{"categories": {"in": ["test"]}}
|
||||
]
|
||||
}}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Best practices
|
||||
|
||||
<Callout type="tip" icon="lightbulb" color="#26A17B">
|
||||
The root must be `AND`, `OR`, or `NOT` with an array of conditions.
|
||||
</Callout>
|
||||
|
||||
<Callout type="tip" icon="lightbulb" color="#26A17B">
|
||||
Use `"*"` to match any non-null value for a field.
|
||||
</Callout>
|
||||
|
||||
<Callout type="warning" icon="exclamation-triangle" color="#E74C3C">
|
||||
When you specify `user_id` only, other entity fields default to null. Use wildcards to include them.
|
||||
</Callout>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "I filtered by `user_id`, but I don't see items that have an `agent_id`."
|
||||
<AccordionGroup>
|
||||
<Accordion title="Missing results with agent_id">
|
||||
**Problem**: Filtered by `user_id` but don't see agent memories.
|
||||
|
||||
This is the **implicit null-scoping** rule. When you write only `{ "user_id": "u1" }`, the system also enforces `agent_id = NULL`, `run_id = NULL`, `app_id = NULL`. If you want any agent, add `{ "agent_id": "*" }`.
|
||||
**Solution**: Add a wildcard for `agent_id` so non-null entries return:
|
||||
```python
|
||||
{"AND": [{"user_id": "user_123"}, {"agent_id": "*"}]}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "u1" }, { "agent_id": "*" } ] }
|
||||
```
|
||||
<Accordion title="ne operator returns too much">
|
||||
**Problem**: `ne` comparison pulls in records with null values.
|
||||
|
||||
### "My `ne` seems to return more than I expect."
|
||||
**Solution**: Pair `ne` with a wildcard guard:
|
||||
```python
|
||||
{"AND": [{"agent_id": "*"}, {"agent_id": {"ne": "old_agent"}}]}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
`ne` returns rows where the field is **not equal OR NULL**. If you need "not equal and **definitely present**", combine with a wildcard.
|
||||
<Accordion title="Case-insensitive search">
|
||||
**Solution**: Swap to `icontains` to normalize casing.
|
||||
</Accordion>
|
||||
|
||||
```json
|
||||
{ "AND": [ { "agent_id": "*" }, { "agent_id": { "ne": "a1" } } ] }
|
||||
```
|
||||
<Accordion title="Date range between two dates">
|
||||
**Solution**: Use `gte` for the start and `lt` for the end boundary:
|
||||
```python
|
||||
{"AND": [
|
||||
{"created_at": {"gte": "2024-01-01"}},
|
||||
{"created_at": {"lt": "2024-02-01"}}
|
||||
]}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
### "Case-insensitive search?"
|
||||
|
||||
Use `icontains`.
|
||||
|
||||
```json
|
||||
{ "AND": [ { "keywords": { "icontains": "receipt" } } ] }
|
||||
```
|
||||
|
||||
### "Between two dates?"
|
||||
|
||||
Use `gte` and `lt` (or `lte`) together.
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "created_at": { "gte": "2025-01-01T00:00:00Z" } },
|
||||
{ "created_at": { "lt": "2025-02-01T00:00:00Z" } }
|
||||
] }
|
||||
```
|
||||
|
||||
### "Complex logic with NOT"
|
||||
|
||||
`NOT` can wrap a single condition or an array. Example: user `u1` but not category `spam` or `test`.
|
||||
|
||||
```json
|
||||
{ "AND": [
|
||||
{ "user_id": "u1" },
|
||||
{ "NOT": { "categories": { "in": ["spam", "test"] } } }
|
||||
] }
|
||||
```
|
||||
|
||||
### "Metadata matching isn't working."
|
||||
|
||||
Ensure you match the **exact JSON shape** at the top level.
|
||||
|
||||
```json
|
||||
{ "AND": [ { "metadata": { "foo": "bar" } } ] }
|
||||
```
|
||||
|
||||
### "I want all users, all agents, all runs."
|
||||
|
||||
Be explicit with wildcards for **each** entity dimension.
|
||||
|
||||
```json
|
||||
{ "AND": [ { "user_id": "*" }, { "agent_id": "*" }, { "run_id": "*" } ] }
|
||||
```
|
||||
|
||||
---
|
||||
<Accordion title="Metadata filter not working">
|
||||
**Solution**: Match top-level metadata keys exactly:
|
||||
```python
|
||||
{"metadata": {"source": "email"}}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: Do I have to wrap my filter in `AND` or `OR`?**
|
||||
<AccordionGroup>
|
||||
<Accordion title="Do I need AND/OR/NOT?">
|
||||
Yes. The root must be a logical operator with an array.
|
||||
</Accordion>
|
||||
|
||||
Yes. The root must be one of `AND`, `OR`, or `NOT`.
|
||||
<Accordion title="What does * match?">
|
||||
Any non-null value. Nulls are excluded.
|
||||
</Accordion>
|
||||
|
||||
**Q: What does the wildcard `"*"` match?**
|
||||
<Accordion title="Why use wildcards?">
|
||||
Unspecified fields default to NULL. Use `"*"` to include non-null values.
|
||||
</Accordion>
|
||||
|
||||
Any **non-null** value for that field.
|
||||
<Accordion title="Is = required?">
|
||||
No. Equality is the default: `{"user_id": "u1"}` works.
|
||||
</Accordion>
|
||||
|
||||
**Q: Why are results "missing" unless I add wildcards?**
|
||||
<Accordion title="Can I filter nested metadata?">
|
||||
Only top-level keys are supported.
|
||||
</Accordion>
|
||||
|
||||
Because unspecified entity fields default to **`NULL`** due to restrictive scoping.
|
||||
<Accordion title="How to search text?">
|
||||
Use `keywords` with `contains` (case-sensitive) or `icontains` (case-insensitive).
|
||||
</Accordion>
|
||||
|
||||
**Q: Is `eq` required?**
|
||||
|
||||
No—equality is the default. `{ "user_id": "u1" }` is enough.
|
||||
|
||||
**Q: Does `ne` include NULLs?**
|
||||
|
||||
Yes. Use `{ "field": "*" }` together with `ne` if you need "present and not equal".
|
||||
|
||||
**Q: How do I search the memory text?**
|
||||
|
||||
Use `keywords` with `contains` or `icontains`.
|
||||
|
||||
**Q: Can I filter nested metadata keys?**
|
||||
|
||||
Currently target **top-level** keys as shown: `{ "metadata": { "foo": "bar" } }`.
|
||||
<Accordion title="Can I nest AND/OR?">
|
||||
```python
|
||||
{
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"OR": [
|
||||
{"categories": "finance"},
|
||||
{"categories": "health"}
|
||||
]}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ Walk through a real request/response. Include sample payloads and highlight nota
|
||||
## Best practices
|
||||
|
||||
- Keep criteria minimal—overfiltering hurts recall.
|
||||
- Pair with Memory Filters v2 for hybrid scoring.
|
||||
- Pair with Memory Filters for hybrid scoring.
|
||||
|
||||
{/* DEBUG: verify CTA targets */}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user