[docs] Minor Docs fixes ( enhancements , restructure ) (#3748)
This commit is contained in:
@@ -3,10 +3,96 @@ title: 'Add Memories'
|
|||||||
openapi: post /v1/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>
|
- **Method**: `POST`
|
||||||
Learn more in the [Graph Memory documentation](/platform/features/graph-memory).
|
- **URL**: `/v1/memories/`
|
||||||
</Note>
|
- **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:
|
Run the basic loop for a week and check what's stored:
|
||||||
|
|
||||||
```python
|
```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"]])
|
print([m["memory"] for m in memories["results"]])
|
||||||
# Output: ["Max wants to run marathon under 4 hours", "hey", "lol ok", "cool thanks", "gtg bye"]
|
# 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("hey how's it going", user_id="max")
|
||||||
chat("I prefer trail running over roads", 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"]])
|
print([m["memory"] for m in memories["results"]])
|
||||||
# Output: ["Max wants to run marathon under 4 hours", "Max prefers trail running over roads"]
|
# 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
|
```python
|
||||||
# Find the old memory
|
# 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]
|
goal_memory = [m for m in memories["results"] if "sub-4" in m["memory"]][0]
|
||||||
|
|
||||||
# Update it
|
# Update it
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ async def get_all_memory(
|
|||||||
) -> str:
|
) -> str:
|
||||||
"""Retrieve all memories from Mem0"""
|
"""Retrieve all memories from Mem0"""
|
||||||
user_id = context.context.user_id or "default_user"
|
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"]])
|
results = '\n'.join([result["memory"] for result in memories["results"]])
|
||||||
return str(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.
|
Retrieve all memories for a user asynchronously.
|
||||||
|
|
||||||
|
<Callout type="warning" title="Filters Required">
|
||||||
|
`get_all()` now requires filters to be specified.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
|
|
||||||
```python Python
|
```python Python
|
||||||
await client.get_all(user_id="alice")
|
await client.get_all(filters={"AND": [{"user_id": "alice"}]})
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript JavaScript
|
```javascript JavaScript
|
||||||
await client.getAll({ user_id: "alice" });
|
await client.getAll({ filters: {"AND": [{"user_id": "alice"}]} });
|
||||||
```
|
```
|
||||||
|
|
||||||
</CodeGroup>
|
</CodeGroup>
|
||||||
|
|||||||
@@ -161,12 +161,14 @@ You can also retrieve all processed memories at any time:
|
|||||||
|
|
||||||
```python Python
|
```python Python
|
||||||
# Retrieve all memories for a user
|
# 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
|
```javascript JavaScript
|
||||||
// Retrieve all memories for a user
|
// 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>
|
</CodeGroup>
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ messages = [
|
|||||||
|
|
||||||
# Add the messages and check extracted memories
|
# Add the messages and check extracted memories
|
||||||
result = client.add(messages, user_id="test_user")
|
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
|
# Review if the right information was extracted
|
||||||
for memory in memories:
|
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.
|
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>
|
<CodeGroup>
|
||||||
|
|
||||||
```python Python
|
```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
|
```json Output
|
||||||
|
|||||||
@@ -187,12 +187,16 @@ console.log(results);
|
|||||||
|
|
||||||
When retrieving all memories, Graph Memory provides additional relationship context:
|
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>
|
<CodeGroup>
|
||||||
|
|
||||||
```python Python
|
```python Python
|
||||||
# Get all memories with graph context
|
# Get all memories with graph context
|
||||||
memories = client.get_all(
|
memories = client.get_all(
|
||||||
user_id="joseph",
|
filters={"AND": [{"user_id": "joseph"}]},
|
||||||
enable_graph=True
|
enable_graph=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -202,7 +206,7 @@ print(memories)
|
|||||||
```javascript JavaScript
|
```javascript JavaScript
|
||||||
// Get all memories with graph context
|
// Get all memories with graph context
|
||||||
const memories = await client.getAll({
|
const memories = await client.getAll({
|
||||||
user_id: "joseph",
|
filters: {"AND": [{"user_id": "joseph"}]},
|
||||||
enable_graph: true
|
enable_graph: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,515 +1,416 @@
|
|||||||
---
|
---
|
||||||
title: Memory Filters v2
|
title: Memory Filters
|
||||||
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.
|
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": [
|
"AND": [ # or "OR", "NOT"
|
||||||
{ "user_id": "u1" }
|
{ "field": "value" },
|
||||||
]
|
{ "field": { "operator": "value" } }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### User memories across all runs
|
## Available fields and operators
|
||||||
|
|
||||||
```json
|
### Entity fields
|
||||||
{
|
| Field | Operators | Example |
|
||||||
"AND": [
|
|-------|-----------|---------|
|
||||||
{ "user_id": "u1" },
|
| `user_id` | `=`, `!=`, `in`, `*` | `{"user_id": "user_123"}` |
|
||||||
{ "run_id": "*" }
|
| `agent_id` | `=`, `!=`, `in`, `*` | `{"agent_id": "*"}` |
|
||||||
]
|
| `app_id` | `=`, `!=`, `in`, `*` | `{"app_id": {"in": ["app1", "app2"]}}` |
|
||||||
}
|
| `run_id` | `=`, `!=`, `in`, `*` | `{"run_id": "*"}` |
|
||||||
```
|
|
||||||
|
### Time fields
|
||||||
<Note>
|
| Field | Operators | Example |
|
||||||
Excludes null run_id values
|
|-------|-----------|---------|
|
||||||
</Note>
|
| `created_at` | `>`, `>=`, `<`, `<=`, `=`, `!=` | `{"created_at": {"gte": "2024-01-01"}}` |
|
||||||
|
| `updated_at` | `>`, `>=`, `<`, `<=`, `=`, `!=` | `{"updated_at": {"lt": "2024-12-31"}}` |
|
||||||
|
| `timestamp` | `>`, `>=`, `<`, `<=`, `=`, `!=` | `{"timestamp": {"gt": "2024-01-01"}}` |
|
||||||
---
|
|
||||||
|
### Content fields
|
||||||
## Filter Structure
|
| Field | Operators | Example |
|
||||||
|
|-------|-----------|---------|
|
||||||
* Root must be **`AND`** or **`OR`** (or **`NOT`**) containing an **array** of conditions.
|
| `categories` | `=`, `!=`, `in`, `contains` | `{"categories": {"in": ["finance"]}}` |
|
||||||
* A **condition** is either a simple equality `{ "user_id": "u1" }` or an operator clause `{ "created_at": { "gte": "..." } }`.
|
| `metadata` | `=`, `!=` | `{"metadata": {"key": "value"}}` |
|
||||||
|
| `keywords` | `contains`, `icontains` | `{"keywords": {"icontains": "invoice"}}` |
|
||||||
```json
|
|
||||||
{
|
### Special fields
|
||||||
"AND": [
|
| Field | Operators | Example |
|
||||||
{ "user_id": "u1" },
|
|-------|-----------|---------|
|
||||||
{ "run_id": "*" },
|
| `memory_ids` | `in` | `{"memory_ids": ["id1", "id2"]}` |
|
||||||
{ "created_at": { "lt": "2025-06-01T00:00:00Z" } },
|
|
||||||
{ "categories": { "in": ["finance", "health"] } }
|
<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
|
||||||
**Accepted shapes**
|
|
||||||
|
Use these ready-made filters to target typical retrieval scenarios without rebuilding logic from scratch.
|
||||||
```json
|
|
||||||
{ "AND": [ /* conditions... */ ] }
|
<AccordionGroup>
|
||||||
{ "OR": [ /* conditions... */ ] }
|
<Accordion title="Single user">
|
||||||
{ "NOT": [ /* conditions... */ ] }
|
```python
|
||||||
```
|
# Narrow to one user's memories
|
||||||
|
filters = {"AND": [{"user_id": "user_123"}]}
|
||||||
---
|
memories = client.get_all(filters=filters)
|
||||||
|
```
|
||||||
## Available Fields
|
</Accordion>
|
||||||
|
|
||||||
Use these to scope memories to primary entities:
|
<Accordion title="All users">
|
||||||
|
```python
|
||||||
| Field | Meaning |
|
# Wildcard skips null user_id entries
|
||||||
| ---------- | ----------------------- |
|
filters = {"AND": [{"user_id": "*"}]}
|
||||||
| `user_id` | Filter by user/consumer |
|
memories = client.get_all(filters=filters)
|
||||||
| `agent_id` | Filter by AI agent |
|
```
|
||||||
| `app_id` | Filter by application |
|
</Accordion>
|
||||||
| `run_id` | Filter by session/run |
|
|
||||||
|
<Accordion title="User across all runs">
|
||||||
---
|
```python
|
||||||
|
# Pair a user filter with a run wildcard
|
||||||
## Wildcards
|
filters = {
|
||||||
|
"AND": [
|
||||||
Wildcards (`"*"`) match **any non-null** value of that field. This means if a field is null, it won't be included in the results.
|
{"user_id": "user_123"},
|
||||||
|
{"run_id": "*"}
|
||||||
<Note>
|
]
|
||||||
Asterisks (`*`) exclude null values - only non-null fields will be matched
|
}
|
||||||
</Note>
|
memories = client.get_all(filters=filters)
|
||||||
|
```
|
||||||
```json
|
</Accordion>
|
||||||
{ "AND": [ { "user_id": "*" } ] } // any record with a user_id
|
</AccordionGroup>
|
||||||
{ "AND": [ { "user_id": "*" }, { "run_id": "*" } ] } // require both non-null
|
|
||||||
{ "OR": [ { "user_id": "*" }, { "run_id": "*" } ] } // either non-null
|
### Content search
|
||||||
```
|
|
||||||
|
Find memories containing specific text, categories, or metadata values.
|
||||||
---
|
|
||||||
|
<AccordionGroup>
|
||||||
## Operators and Fields
|
<Accordion title="Text search">
|
||||||
|
```python
|
||||||
**Available Fields**
|
# Case-insensitive match
|
||||||
|
filters = {
|
||||||
* **Entities**: `user_id`, `agent_id`, `app_id`, `run_id`
|
"AND": [
|
||||||
* **Time**: `created_at`, `updated_at`, `timestamp`
|
{"user_id": "user_123"},
|
||||||
* **Content**: `categories`, `metadata`, `keywords`
|
{"keywords": {"icontains": "pizza"}}
|
||||||
* **Special**: `memory_ids` (array of IDs)
|
]
|
||||||
|
}
|
||||||
**Operators**
|
|
||||||
|
# Case-sensitive match
|
||||||
* `in`: Matches any of the values specified
|
filters = {
|
||||||
* `gte`: Greater than or equal to
|
"AND": [
|
||||||
* `lte`: Less than or equal to
|
{"user_id": "user_123"},
|
||||||
* `gt`: Greater than
|
{"keywords": {"contains": "Invoice_2024"}}
|
||||||
* `lt`: Less than
|
]
|
||||||
* `ne`: Not equal to
|
}
|
||||||
* `contains`: Case-sensitive containment check
|
```
|
||||||
* `icontains`: Case-insensitive containment check
|
</Accordion>
|
||||||
* `*`: Wildcard character that matches everything
|
|
||||||
|
<Accordion title="Categories">
|
||||||
**Field Structures**
|
```python
|
||||||
|
# Match against category list
|
||||||
```json
|
filters = {
|
||||||
// Entity fields
|
"AND": [
|
||||||
{ "user_id": "u1" }
|
{"user_id": "user_123"},
|
||||||
{ "agent_id": "a1" }
|
{"categories": {"in": ["finance", "health"]}}
|
||||||
{ "app_id": "app1" }
|
]
|
||||||
{ "run_id": "run1" }
|
}
|
||||||
|
|
||||||
// Time fields
|
# Partial category match
|
||||||
{ "created_at": { "gte": "2025-01-01T00:00:00Z" } }
|
filters = {
|
||||||
{ "updated_at": { "lt": "2025-02-01T00:00:00Z" } }
|
"AND": [
|
||||||
|
{"user_id": "user_123"},
|
||||||
// Categories (exact matching)
|
{"categories": {"contains": "finance"}}
|
||||||
{ "categories": { "in": ["personal_information", "finance"] } }
|
]
|
||||||
// Categories (partial matching)
|
}
|
||||||
{ "categories": { "contains": "finance" } }
|
```
|
||||||
|
</Accordion>
|
||||||
// Metadata (exact key-value match)
|
|
||||||
{ "metadata": { "key": "value" } }
|
<Accordion title="Metadata">
|
||||||
|
```python
|
||||||
// Keywords (text search)
|
# Pin to a metadata attribute
|
||||||
{ "keywords": { "icontains": "budget" } }
|
filters = {
|
||||||
|
"AND": [
|
||||||
// Memory IDs
|
{"user_id": "user_123"},
|
||||||
{ "memory_ids": ["m1", "m2", "m3"] }
|
{"metadata": {"source": "email"}}
|
||||||
```
|
]
|
||||||
|
}
|
||||||
**Notes**
|
```
|
||||||
|
</Accordion>
|
||||||
* `eq` is implied: `{ "user_id": "u1" }` ≡ `{ "user_id": { "eq": "u1" } }`
|
</AccordionGroup>
|
||||||
* `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
|
### Time-based filtering
|
||||||
|
|
||||||
---
|
Retrieve memories within specific date ranges using time operators.
|
||||||
|
|
||||||
## Examples
|
<AccordionGroup>
|
||||||
|
<Accordion title="Date range">
|
||||||
### User and Agent Filters
|
```python
|
||||||
|
# Created in January 2024
|
||||||
**All memories for a specific user**
|
filters = {
|
||||||
|
"AND": [
|
||||||
```json
|
{"user_id": "user_123"},
|
||||||
{ "AND": [ { "user_id": "u1" } ] }
|
{"created_at": {"gte": "2024-01-01T00:00:00Z"}},
|
||||||
```
|
{"created_at": {"lt": "2024-02-01T00:00:00Z"}}
|
||||||
|
]
|
||||||
**All memories across all users (no agent/app/run)**
|
}
|
||||||
|
|
||||||
```json
|
# Updated recently
|
||||||
{ "AND": [ { "user_id": "*" } ] }
|
filters = {
|
||||||
```
|
"AND": [
|
||||||
|
{"user_id": "user_123"},
|
||||||
<Note>
|
{"updated_at": {"gte": "2024-12-01T00:00:00Z"}}
|
||||||
Excludes null user_id values
|
]
|
||||||
</Note>
|
}
|
||||||
|
```
|
||||||
**User memories across all runs**
|
</Accordion>
|
||||||
|
</AccordionGroup>
|
||||||
```json
|
|
||||||
{ "AND": [ { "user_id": "u1" }, { "run_id": "*" } ] }
|
### Multiple criteria
|
||||||
```
|
|
||||||
|
Combine various filters for complex queries across different dimensions.
|
||||||
<Note>
|
|
||||||
Excludes null run_id values
|
<AccordionGroup>
|
||||||
</Note>
|
<Accordion title="Multiple users">
|
||||||
|
```python
|
||||||
**All memories for a specific agent**
|
# Expand scope to a short user list
|
||||||
|
filters = {
|
||||||
```json
|
"AND": [
|
||||||
{ "AND": [ { "agent_id": "a1" } ] }
|
{"user_id": {"in": ["user_1", "user_2", "user_3"]}}
|
||||||
```
|
]
|
||||||
|
}
|
||||||
**Agent memories across all runs**
|
```
|
||||||
|
</Accordion>
|
||||||
```json
|
|
||||||
{ "AND": [ { "agent_id": "a1" }, { "run_id": "*" } ] }
|
<Accordion title="OR logic">
|
||||||
```
|
```python
|
||||||
|
# Return matches on either condition
|
||||||
<Note>
|
filters = {
|
||||||
Excludes null run_id values
|
"OR": [
|
||||||
</Note>
|
{"user_id": "user_123"},
|
||||||
|
{"run_id": "run_456"}
|
||||||
### Content and Text Filters
|
]
|
||||||
|
}
|
||||||
**Search for text in user's memory content (case-insensitive)**
|
```
|
||||||
|
</Accordion>
|
||||||
```json
|
|
||||||
{ "AND": [
|
<Accordion title="Exclude categories">
|
||||||
{ "user_id": "u1" },
|
```python
|
||||||
{ "keywords": { "icontains": "pizza" } }
|
# Wrap negative logic with NOT
|
||||||
] }
|
filters = {
|
||||||
```
|
"AND": [
|
||||||
|
{"user_id": "user_123"},
|
||||||
**Search for text in user's memory content (case-sensitive)**
|
{"NOT": {
|
||||||
|
"categories": {"in": ["spam", "test"]}
|
||||||
```json
|
}}
|
||||||
{ "AND": [
|
]
|
||||||
{ "user_id": "u1" },
|
}
|
||||||
{ "keywords": { "contains": "BudgetQ1" } }
|
```
|
||||||
] }
|
</Accordion>
|
||||||
```
|
|
||||||
|
<Accordion title="Specific memory IDs">
|
||||||
**User memories with specific categories**
|
```python
|
||||||
|
# Fetch a fixed set of memory IDs
|
||||||
```json
|
filters = {
|
||||||
{ "AND": [
|
"AND": [
|
||||||
{ "user_id": "u1" },
|
{"user_id": "user_123"},
|
||||||
{ "categories": { "in": ["finance", "health"] } }
|
{"memory_ids": ["mem_1", "mem_2", "mem_3"]}
|
||||||
] }
|
]
|
||||||
```
|
}
|
||||||
|
```
|
||||||
**User memories with specific metadata**
|
</Accordion>
|
||||||
|
|
||||||
```json
|
<Accordion title="All entities populated">
|
||||||
{ "AND": [
|
```python
|
||||||
{ "user_id": "u1" },
|
# Require every entity field to be non-null
|
||||||
{ "metadata": { "foo": "bar" } }
|
filters = {
|
||||||
] }
|
"AND": [
|
||||||
```
|
{"user_id": "*"},
|
||||||
|
{"agent_id": "*"},
|
||||||
### Time-based Filters
|
{"run_id": "*"},
|
||||||
|
{"app_id": "*"}
|
||||||
**Memories created after a specific date**
|
]
|
||||||
|
}
|
||||||
```json
|
```
|
||||||
{ "AND": [
|
</Accordion>
|
||||||
{ "user_id": "u1" },
|
</AccordionGroup>
|
||||||
{ "created_at": { "gt": "2025-01-01T00:00:00Z" } }
|
|
||||||
] }
|
## 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.
|
||||||
**User memories within a date range**
|
|
||||||
|
<AccordionGroup>
|
||||||
```json
|
<Accordion title="Multi-dimensional filtering">
|
||||||
{ "AND": [
|
```python
|
||||||
{ "user_id": "u1" },
|
# Invoice memories in Q1 2024
|
||||||
{ "created_at": { "gte": "2025-01-01T00:00:00Z" } },
|
filters = {
|
||||||
{ "created_at": { "lt": "2025-02-01T00:00:00Z" } }
|
"AND": [
|
||||||
] }
|
{"user_id": "user_123"},
|
||||||
```
|
{"keywords": {"icontains": "invoice"}},
|
||||||
|
{"categories": {"in": ["finance"]}},
|
||||||
**Memories updated within a time window**
|
{"created_at": {"gte": "2024-01-01T00:00:00Z"}},
|
||||||
|
{"created_at": {"lt": "2024-04-01T00:00:00Z"}}
|
||||||
```json
|
]
|
||||||
{ "AND": [
|
}
|
||||||
{ "user_id": "u1" },
|
```
|
||||||
{ "updated_at": { "gte": "2025-05-01T00:00:00Z" } },
|
</Accordion>
|
||||||
{ "updated_at": { "lte": "2025-05-31T23:59:59Z" } }
|
|
||||||
] }
|
<Accordion title="Cross-entity relationships">
|
||||||
```
|
```python
|
||||||
|
# From specific agent, all users
|
||||||
### Advanced Filters
|
filters = {
|
||||||
|
"AND": [
|
||||||
**Memories from multiple users**
|
{"agent_id": "finance_bot"},
|
||||||
|
{"user_id": "*"}
|
||||||
```json
|
]
|
||||||
{ "AND": [ { "user_id": { "in": ["u1", "u2", "u3"] } } ] }
|
}
|
||||||
```
|
|
||||||
|
# Any entity populated
|
||||||
|
filters = {
|
||||||
**Memories from either user or run**
|
"OR": [
|
||||||
|
{"user_id": "*"},
|
||||||
```json
|
{"agent_id": "*"},
|
||||||
{ "OR": [ { "user_id": "u1" }, { "run_id": "run1" } ] }
|
{"run_id": "*"},
|
||||||
```
|
{"app_id": "*"}
|
||||||
|
]
|
||||||
**Memories that have both user and run (non-null)**
|
}
|
||||||
|
```
|
||||||
```json
|
</Accordion>
|
||||||
{ "AND": [ { "user_id": "*" }, { "run_id": "*" } ] }
|
|
||||||
```
|
<Accordion title="Nested NOT/OR logic">
|
||||||
|
```python
|
||||||
<Note>
|
# User memories from 2024, excluding spam and test
|
||||||
Excludes null user_id and run_id values
|
filters = {
|
||||||
</Note>
|
"AND": [
|
||||||
|
{"user_id": "user_123"},
|
||||||
**User memories excluding specific categories**
|
{"created_at": {"gte": "2024-01-01T00:00:00Z"}},
|
||||||
|
{"NOT": {
|
||||||
```json
|
"OR": [
|
||||||
{ "AND": [
|
{"categories": {"in": ["spam"]}},
|
||||||
{ "user_id": "u1" },
|
{"categories": {"in": ["test"]}}
|
||||||
{ "NOT": { "categories": { "in": ["spam", "test"] } } }
|
]
|
||||||
] }
|
}}
|
||||||
```
|
]
|
||||||
|
}
|
||||||
**User memories by specific IDs**
|
```
|
||||||
|
</Accordion>
|
||||||
```json
|
</AccordionGroup>
|
||||||
{ "AND": [
|
|
||||||
{ "user_id": "u1" },
|
## Best practices
|
||||||
{ "memory_ids": ["m1", "m2", "m3"] }
|
|
||||||
] }
|
<Callout type="tip" icon="lightbulb" color="#26A17B">
|
||||||
```
|
The root must be `AND`, `OR`, or `NOT` with an array of conditions.
|
||||||
|
</Callout>
|
||||||
**Complex filter: text + category + time**
|
|
||||||
|
<Callout type="tip" icon="lightbulb" color="#26A17B">
|
||||||
```json
|
Use `"*"` to match any non-null value for a field.
|
||||||
{ "AND": [
|
</Callout>
|
||||||
{ "user_id": "u1" },
|
|
||||||
{ "keywords": { "icontains": "invoice" } },
|
<Callout type="warning" icon="exclamation-triangle" color="#E74C3C">
|
||||||
{ "categories": { "in": ["finance"] } },
|
When you specify `user_id` only, other entity fields default to null. Use wildcards to include them.
|
||||||
{ "created_at": { "gte": "2025-03-01T00:00:00Z" } }
|
</Callout>
|
||||||
] }
|
|
||||||
```
|
|
||||||
|
|
||||||
### 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"] }
|
|
||||||
] }
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
## 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
|
<Accordion title="ne operator returns too much">
|
||||||
{ "AND": [ { "user_id": "u1" }, { "agent_id": "*" } ] }
|
**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
|
<Accordion title="Date range between two dates">
|
||||||
{ "AND": [ { "agent_id": "*" }, { "agent_id": { "ne": "a1" } } ] }
|
**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?"
|
<Accordion title="Metadata filter not working">
|
||||||
|
**Solution**: Match top-level metadata keys exactly:
|
||||||
Use `icontains`.
|
```python
|
||||||
|
{"metadata": {"source": "email"}}
|
||||||
```json
|
```
|
||||||
{ "AND": [ { "keywords": { "icontains": "receipt" } } ] }
|
</Accordion>
|
||||||
```
|
</AccordionGroup>
|
||||||
|
|
||||||
### "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": "*" } ] }
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## FAQ
|
## 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?**
|
<Accordion title="Can I nest AND/OR?">
|
||||||
|
```python
|
||||||
No—equality is the default. `{ "user_id": "u1" }` is enough.
|
{
|
||||||
|
"AND": [
|
||||||
**Q: Does `ne` include NULLs?**
|
{"user_id": "user_123"},
|
||||||
|
{"OR": [
|
||||||
Yes. Use `{ "field": "*" }` together with `ne` if you need "present and not equal".
|
{"categories": "finance"},
|
||||||
|
{"categories": "health"}
|
||||||
**Q: How do I search the memory text?**
|
]}
|
||||||
|
]
|
||||||
Use `keywords` with `contains` or `icontains`.
|
}
|
||||||
|
```
|
||||||
**Q: Can I filter nested metadata keys?**
|
</Accordion>
|
||||||
|
</AccordionGroup>
|
||||||
Currently target **top-level** keys as shown: `{ "metadata": { "foo": "bar" } }`.
|
|
||||||
|
|||||||
+1
-1
@@ -119,7 +119,7 @@ Walk through a real request/response. Include sample payloads and highlight nota
|
|||||||
## Best practices
|
## Best practices
|
||||||
|
|
||||||
- Keep criteria minimal—overfiltering hurts recall.
|
- 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 */}
|
{/* DEBUG: verify CTA targets */}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user