[doc] Partition Memories by Entity , features doc and cookbook (#3735)

This commit is contained in:
Parth Sharma
2025-11-13 23:56:41 +05:30
committed by GitHub
parent 61e2a40d55
commit 3297ec1a46
14 changed files with 544 additions and 621 deletions
@@ -130,8 +130,8 @@ As users interact with the system, Mem0's memory system continuously learns and
---
<CardGroup cols={2}>
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
Separate user and agent memories to keep your companion's personality consistent.
<Card title="Partition Memories by Entity" icon="layers" href="/cookbooks/essentials/entity-partitioning-playbook">
Separate user, agent, and session context to keep your companion consistent.
</Card>
<Card title="Quickstart Demo with Mem0" icon="rocket" href="/cookbooks/companions/quickstart-demo">
Run the full showcase app to see memory-powered companions in action.
@@ -516,8 +516,8 @@ Before launching:
---
<CardGroup cols={2}>
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
Separate user and agent memories so companions stay consistent across sessions.
<Card title="Partition Memories by Entity" icon="layers" href="/cookbooks/essentials/entity-partitioning-playbook">
Keep companions from leaking context by combining user, agent, and session scopes.
</Card>
<Card title="Tag Support Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
Organize customer context to keep assistants responsive at scale.
@@ -1,603 +0,0 @@
---
title: Scope User vs Agent Memories
description: "Use **user_id** and **agent_id** to balance personalization with consistent assistant behavior."
---
# Build AI with Distinct Personalities
While building memory systems for AI apps, you need to juggle between agent and user memories. The user delivers information from their side, but there's often value inside the agent's responses as well.
Unlike other memory APIs, we built one that allows you the flexibility to store memory from all sources. User and agent memories in Mem0 are handled by:
- **user_id** - Memories about specific users
- **agent_id** - Memories from the agent itself
In this guide, you'll see how these parameters work together, along with practical examples to help you build a fitness coach that remembers user workouts while maintaining a consistent coaching personality.
---
## User Memories
Let's start by tracking individual user workouts. We'll use **`user_id`** to keep each person's data separate.
```python
from openai import OpenAI
from mem0 import MemoryClient
import os
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
mem0_client = MemoryClient()
# Sarah logs her workout
mem0_client.add(
"Completed 5K run in 28 minutes - felt great!",
user_id="sarah"
)
# Mike logs his workout
mem0_client.add(
"Bench press: 185 lbs x 10 reps, 3 sets",
user_id="mike"
)
```
Now when we coach Sarah, we retrieve only her workout history:
```python
# Get Sarah's workout history
sarah_history = mem0_client.search(
"What exercises has Sarah done recently?",
filters={"user_id": "sarah"}
)
# Generate coaching advice
response = openai_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You're a supportive fitness coach."},
{"role": "user", "content": f"Based on this history: {sarah_history}, suggest the next workout."}
]
)
print(response.choices[0].message.content)
```
**Output:**
```
Great job on that 5K! Your endurance is building nicely. Let's add some
strength work to complement your running. Try 3 sets of bodyweight squats
(15 reps each) to strengthen your legs and improve your running power.
```
<Info>
**Expected output:** Sarah gets running advice based on her 5K, not Mike's bench press data. The **`user_id`** filter ensures memories are isolated—each user only sees their own workout history.
</Info>
This works perfectly! Each user has private workout history, and Sarah never sees Mike's data.
---
## Adding Coach Personality
Our fitness coach needs a consistent personality - supportive, motivational, and celebrates small wins. Let's see what happens if we try storing this with **`user_id`**:
```python
# Adding coach personality for Sarah
mem0_client.add(
"I'm a supportive fitness coach who celebrates every achievement and uses athlete-focused language",
user_id="sarah"
)
# Adding the same personality for Mike
mem0_client.add(
"I'm a supportive fitness coach who celebrates every achievement and uses athlete-focused language",
user_id="mike"
)
# For 1,000 users, we'd repeat this 1,000 times...
```
This approach has some limitations:
1. **Duplication**: We're storing the same coaching personality 1,000 times for 1,000 users
2. **Hard to update**: Want to change the coaching style? Update 1,000 memories
3. **Mixed with user data**: Coach personality and user workouts are stored together, making queries complex
<Warning>
Storing agent personality with **`user_id`** doesn't scale. For 10,000 users, you'd duplicate the same personality 10,000 times. Updating the coaching style means updating 10,000 separate memories. This wastes storage and makes maintenance impossible.
</Warning>
What if the coach could have a personality that's shared across all users?
---
## Agent Memories
Here's where **`agent_id`** comes in. We can store the coach's personality once and share it across all users:
```python
# Store coach personality ONCE with agent_id
mem0_client.add(
"I'm FitCoach - a supportive fitness coach who celebrates every achievement. "
"I use motivational language, focus on progress over perfection, and help users build sustainable habits.",
agent_id="fitcoach_v1"
)
# Sarah's workout (still private)
mem0_client.add(
"Completed 5K run in 28 minutes",
user_id="sarah"
)
# Mike's workout (still private)
mem0_client.add(
"Bench press: 185 lbs x 10 reps, 3 sets",
user_id="mike"
)
```
Now when coaching Sarah, we retrieve both the agent's personality AND her workout history:
```python
# Get both coach personality and Sarah's workouts
coaching_context = mem0_client.search(
"coaching context for Sarah",
filters={
"OR": [
{"agent_id": "fitcoach_v1"}, # Coach personality
{"user_id": "sarah"} # Sarah's workout history
]
}
)
# Generate personalized coaching
response = openai_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": str(coaching_context)},
{"role": "user", "content": "What should I focus on in my next workout?"}
]
)
print(response.choices[0].message.content)
```
**Output:**
```
Amazing work on that 5K! 🎉 You're crushing your running goals!
Now let's build some complementary strength. I recommend adding bodyweight
squats to your routine - they'll make you an even stronger runner. Start
with 3 sets of 15 reps, and remember: progress over perfection!
```
Notice how the response has the motivational tone (from **`agent_id`**) combined with personalized advice based on Sarah's 5K run (from **`user_id`**).
The coach personality is now:
- ✅ Stored once, shared by all users
- ✅ Easy to update (change one memory, affects all users)
- ✅ Cleanly separated from user workout data
<Info>
**Expected behavior:** The response combines the motivational tone (from **`agent_id`**) with Sarah's specific 5K progress (from **`user_id`**). One agent personality, infinite users—update the agent once, and all users get the new coaching style.
</Info>
---
## Combining Both: Relationship Memories
There's a third type of memory - one that captures the relationship between a specific user and the coach. To store these, use `metadata` to track which agent the relationship is with:
```python
# Coach personality (shared across all users)
mem0_client.add(
"I'm FitCoach - supportive and motivational",
agent_id="fitcoach_v1"
)
# Sarah's workout data (private to Sarah)
mem0_client.add(
"Goal: Run a half marathon by June. Currently runs 5K comfortably.",
user_id="sarah"
)
# Sarah-Coach relationship (stored as user memory with agent context in metadata)
mem0_client.add(
"Sarah and I have an inside joke: 'No pain, no protein shake!' "
"She responds best to gentle encouragement after tough workouts.",
user_id="sarah",
metadata={"agent_id": "fitcoach_v1", "type": "relationship"}
)
# Mike-Coach relationship (different from Sarah's)
mem0_client.add(
"Mike prefers data-driven feedback with specific numbers and percentages. "
"Less motivational talk, more concrete metrics.",
user_id="mike",
metadata={"agent_id": "fitcoach_v1", "type": "relationship"}
)
```
Now when coaching Sarah, retrieve her data including relationship with this specific coach:
```python
# Get Sarah's memories including relationship with fitcoach_v1
sarah_context = mem0_client.search(
"How should I coach Sarah today?",
user_id="sarah",
filters={"metadata": {"agent_id": "fitcoach_v1"}}
)
# Get coach personality
coach_personality = mem0_client.search(
"coaching personality",
agent_id="fitcoach_v1"
)
# Combine both contexts
full_context = str(coach_personality) + "\\n" + str(sarah_context)
response = openai_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": full_context},
{"role": "user", "content": "Just finished today's workout!"}
]
)
print(response.choices[0].message.content)
```
**Output:**
```
Awesome work today! 💪 No pain, no protein shake, right? 😄
You're making real progress toward that half marathon goal. Keep this
momentum going - your consistency is your superpower!
```
When coaching Mike with the same approach:
```python
# Get Mike's memories including relationship with fitcoach_v1
mike_context = mem0_client.search(
"How should I coach Mike today?",
user_id="mike",
filters={"metadata": {"agent_id": "fitcoach_v1"}}
)
coach_personality = mem0_client.search(
"coaching personality",
agent_id="fitcoach_v1"
)
full_context = str(coach_personality) + "\\n" + str(mike_context)
# ... same coaching code ...
```
**Output:**
```
Solid session. Your bench press shows 8% improvement over last week
(171 lbs avg to 185 lbs). Target: 200 lbs by end of month.
On track at current rate (+3.2% weekly).
```
Same coach, completely different experience based on each user's relationship preferences stored in metadata.
<Note>
**Relationship memories** are stored with **`user_id`** (they're private to each user) but include `agent_id` in metadata to track which agent the relationship is with. This lets you retrieve the user's preferences for how this specific agent should interact with them.
</Note>
---
## Putting It All Together
Here's a complete example showing all three memory layers working together:
```python
from openai import OpenAI
from mem0 import MemoryClient
import os
# Initialize clients
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
mem0_client = MemoryClient()
# Layer 1: Agent personality (shared)
mem0_client.add(
"I'm FitCoach - supportive, motivational, celebrates small wins",
agent_id="fitcoach_v1",
metadata={"type": "personality"}
)
# Layer 2: User profile (private)
mem0_client.add(
"Sarah's goal: Run half marathon by June. Currently comfortable at 5K distance.",
user_id="sarah",
metadata={"type": "profile"}
)
# Layer 3: Relationship (stored as user memory with agent context in metadata)
mem0_client.add(
"Sarah responds best to encouragement. Inside joke: 'No pain, no protein shake!'",
user_id="sarah",
metadata={"agent_id": "fitcoach_v1", "type": "relationship"}
)
# Log today's workout
mem0_client.add(
"Completed 8K run in 45 minutes - new personal record!",
user_id="sarah",
metadata={"type": "workout", "date": "2025-01-23"}
)
# Generate coaching response
# Get Sarah's context (includes all her memories)
sarah_context = mem0_client.search(
"Generate coaching advice for Sarah",
user_id="sarah"
)
# Get coach personality
coach_personality = mem0_client.search(
"coaching personality",
agent_id="fitcoach_v1"
)
# Combine contexts
full_context = str(coach_personality) + "\\n" + str(sarah_context)
response = openai_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": full_context},
{"role": "user", "content": "Just finished my run today!"}
]
)
print(response.choices[0].message.content)
```
**Output:**
```
🎉 YES! 8K is a HUGE milestone! You just crushed your previous distance!
Remember when you could barely do 5K? Look at you now! That half marathon
in June is looking more achievable every single day. No pain, no protein
shake - and today, you EARNED that shake! 💪
Next week, let's aim for 9K. You're ready for it!
```
The response combines:
- ✅ Motivational tone (agent personality)
- ✅ Specific goal reference (Sarah's profile)
- ✅ Inside joke (relationship memory)
- ✅ Progress tracking (workout history)
---
![image.png](building_ai_with_personality 295f22c70c908182affdfc87ec79f2db/image.png)
**Three memory layers:**
1. **Agent memories** (blue) - Shared personality and capabilities
2. **User memories** (red) - Private workout data and goals
3. **Relationship memories** (purple) - User memories with agent context stored in metadata
---
## When to Use What
### Use **`user_id`** only (most apps)
**Best for:** Apps that just need to track user-specific data without AI personality
**Examples:**
- Todo lists
- Note-taking apps
- Personal finance trackers
- Support ticket history
```python
mem0_client.add(
"Bought groceries for $127.43",
user_id="sarah"
)
```
---
### Use **`agent_id`** only (rare)
**Best for:** AI tools that work the same for everyone, no user-specific data
**Examples:**
- Calculator bots
- Language translators
- Company policy assistants (same policies for all)
```python
mem0_client.add(
"I can calculate: arithmetic, algebra, basic calculus. I cannot solve differential equations.",
agent_id="calculator_v1"
)
```
---
### Use both **`user_id`** and **`agent_id`** (AI with personality)
**Best for:** AI agents with persistent personalities that remember individual users
**Examples:**
- Fitness coaches (this guide!)
- Educational tutors
- AI companions
- Therapy/mental health bots
- Game NPCs with character development
```python
# Agent personality (shared across all users)
mem0_client.add(
"Coaching personality and style",
agent_id="agent_name"
)
# User data (private)
mem0_client.add(
"User's goals and progress",
user_id="user_name"
)
# Relationship (user memory with agent context in metadata)
mem0_client.add(
"User's relationship with this specific agent",
user_id="user_name",
metadata={"agent_id": "agent_name", "type": "relationship"}
)
```
---
<Tip>
**When to combine user_id + agent_id:** Use both when your AI has a consistent personality that should work the same for everyone (agent_id), while also tracking individual user data (user_id). Most personal AI assistants, coaches, and tutors fit this pattern.
</Tip>
---
## Best Practices
### 1. Use clear naming conventions
```python
# Good: Descriptive and versioned
agent_id="fitcoach_v1"
user_id="sarah_123"
# Bad: Generic and unclear
agent_id="agent1"
user_id="user_abc"
```
### 2. Tag memories with metadata
```python
# For relationship memories, store agent context in metadata
mem0_client.add(
content,
user_id="sarah",
metadata={
"agent_id": "fitcoach_v1",
"type": "relationship",
"version": "v1"
}
)
```
### 3. Test data isolation
Ensure users never see each other's data:
```python
# Get Mike's memories
mike_memories = mem0_client.get_all(filters={"user_id": "mike"})
# Get Sarah's memories
sarah_memories = mem0_client.get_all(filters={"user_id": "sarah"})
# Verify no overlap
assert len(set(mike_memories) & set(sarah_memories)) == 0, "Data leak detected!"
```
### 4. Version your agents
Allows A/B testing different coaching styles:
```python
# Version 1: Gentle and encouraging
mem0_client.add(
"I'm supportive and celebrate small wins",
agent_id="fitcoach_v1"
)
# Version 2: Data-driven and metric-focused
mem0_client.add(
"I provide concrete metrics and percentage improvements",
agent_id="fitcoach_v2"
)
# Assign users to different versions by storing version in metadata
mem0_client.add(
"Sarah's workout preferences and relationship with coach",
user_id="sarah",
metadata={"agent_id": "fitcoach_v1"}
)
mem0_client.add(
"Mike's workout preferences and relationship with coach",
user_id="mike",
metadata={"agent_id": "fitcoach_v2"}
)
```
---
## What You Built
A fitness coach with three-layer memory architecture:
- **Agent personality (agent_id)** - Shared coaching style across all users, updated once
- **User profiles (user_id)** - Private workout history, goals, and progress for each person
- **Relationship memories (user_id + metadata)** - Personalized interaction preferences per user-agent pair
- **Data isolation** - Sarah never sees Mike's workouts, guaranteed by user_id filtering
This pattern scales from 10 to 10,000 users without duplicating agent personality.
---
## Summary
With Mem0's **`user_id`** and **`agent_id`** parameters, you can build AI agents that maintain consistent personalities across all users while remembering individual user data privately. Store relationship preferences with **`user_id`** and track agent context in metadata.
Most apps only need **`user_id`**. Add **`agent_id`** when your AI needs a consistent personality that evolves independently from user data—fitness coaches, tutors, therapy bots, and game NPCs all fit this pattern.
<CardGroup cols={2}>
<Card title="Control What Gets Stored" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
Filter low-signal conversations before they pollute long-term memory.
</Card>
<Card title="Organize Support Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
Categorize customer context so teams can retrieve the right facts fast.
</Card>
</CardGroup>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

@@ -352,8 +352,8 @@ Vector stores handle most memory operations efficiently—semantic search works
The key is knowing which tool fits your query pattern: direct questions work with vectors, multi-hop relationship queries need graphs.
<CardGroup cols={2}>
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
Scope memories across user and agent IDs to balance personalization and reuse.
<Card title="Partition Memories by Entity" icon="layers" href="/cookbooks/essentials/entity-partitioning-playbook">
Scope memories across users, agents, apps, and sessions to balance personalization and reuse.
</Card>
<Card title="Export Everything Safely" icon="download" href="/cookbooks/essentials/exporting-memories">
Learn how to migrate or audit stored memories with structured exports.
@@ -0,0 +1,332 @@
---
title: Partition Memories by Entity
description: Keep memories separate by tagging each write and query with user, agent, app, and session identifiers.
---
Nora runs a travel service. When she stored all memories in one bucket, a recruiter's nut allergy accidentally appeared in a traveler's dinner reservation. Let's fix this by properly separating memories for different users, agents, and applications.
<Info icon="clock">
**Time to complete:** ~15 minutes · **Languages:** Python
</Info>
## Setup
```python
from mem0 import MemoryClient
client = MemoryClient(api_key="m0-...")
```
Grab an API key from the <Link href="https://app.mem0.ai/">Mem0 dashboard</Link> to get started.
## Store and Retrieve Scoped Memories
Let's start by storing Cam's travel preferences and retrieving them:
```python
cam_messages = [
{"role": "user", "content": "I'm Cam. Keep in mind I avoid shellfish and prefer boutique hotels."},
{"role": "assistant", "content": "Noted! I'll use those preferences in future itineraries."}
]
result = client.add(
cam_messages,
user_id="traveler_cam",
agent_id="travel_planner",
run_id="tokyo-2025-weekend",
app_id="concierge_app",
version="v2"
)
```
The memory is now stored. Let's retrieve those memories with the same identifiers:
```python
user_scope = {
"AND": [
{"user_id": "traveler_cam"},
{"app_id": "concierge_app"},
{"run_id": "tokyo-2025-weekend"}
]
}
user_memories = client.search("Any dietary restrictions?", filters=user_scope)
print(user_memories)
agent_scope = {
"AND": [
{"agent_id": "travel_planner"},
{"app_id": "concierge_app"}
]
}
agent_memories = client.search("Any dietary restrictions?", filters=agent_scope)
print(agent_memories)
```
**Output:**
```
{'results': [{'memory': 'avoids shellfish and prefers boutique hotels', ...}]}
{'results': [{'memory': 'avoids shellfish and prefers boutique hotels', ...}]}
```
<Tip icon="compass">
Memories can be written with several identifiers, but each search resolves one entity boundary at a time. Run separate queries for user and agent scopes—just like above—rather than combining both in a single filter.
</Tip>
## When Memories Leak
When Nora adds a chef agent, Cam's travel preferences leak into food recommendations:
```python
chef_filters = {"AND": [{"user_id": "traveler_cam"}]}
collision = client.search("What should I cook?", filters=chef_filters)
print(collision)
```
**Output:**
```
['avoids shellfish and prefers boutique hotels', 'prefers Kyoto kaiseki dining experiences']
```
The travel preferences appear because we only filtered by `user_id`. The chef agent shouldn't see hotel preferences.
## Fix the Leak with Proper Filters
First, let's add a memory specifically for the chef agent:
```python
chef_memory = [
{"role": "user", "content": "I'd like to try some authentic Kyoto cuisine."},
{"role": "assistant", "content": "I'll remember that you prefer Kyoto kaiseki dining experiences."}
]
client.add(
chef_memory,
user_id="traveler_cam",
agent_id="chef_recommender",
run_id="menu-planning-2025-04",
app_id="concierge_app",
version="v2"
)
```
Now search within the chef's scope:
```python
safe_filters = {
"AND": [
{"agent_id": "chef_recommender"},
{"app_id": "concierge_app"},
{"run_id": "menu-planning-2025-04"}
]
}
chef_memories = client.search("Any food alerts?", filters=safe_filters)
print(chef_memories)
```
**Output:**
```
{'results': [{'memory': 'prefers Kyoto kaiseki dining experiences', ...}]}
```
Now the chef agent only sees its own food preferences. The hotel preferences stay with the travel agent.
## Separate Apps with app_id
Nora white-labels her travel service for a sports brand. Use `app_id` to keep enterprise data separate:
```python
enterprise_filters = {
"AND": [
{"app_id": "sports_brand_portal"},
{"user_id": "*"},
{"agent_id": "*"}
]
}
page = client.get_all(filters=enterprise_filters, page=1, page_size=10)
print([row["user_id"] for row in page["results"]])
```
**Output:**
```
['athlete_jane', 'coach_mike', 'team_admin']
```
<Info>
Wildcards (`"*"` ) only match non-null values. Make sure you write memories with explicit `app_id` values.
</Info>
<Tip icon="sparkles">
Need a deeper tour of AND vs OR, nested filters, or wildcard tricks? Check the <Link href="/platform/features/v2-memory-filters">Memory Filters v2 guide</Link> for full examples you can copy into this flow.
</Tip>
When the sports brand offboards, delete all their data:
```python
client.delete_all(app_id="sports_brand_portal")
```
**Output:**
```
{'message': 'Memories deleted successfully!'}
```
## Production Patterns
```python
# Nightly audits - check all data for an app
def audit_app(app_id: str):
filters = {"AND": [{"app_id": app_id}, {"user_id": "*"}, {"agent_id": "*"}]}
return client.get_all(filters=filters, page=1, page_size=50)
# Session cleanup - delete temporary conversations
def close_ticket(ticket_id: str, user_id: str):
client.delete_all(user_id=user_id, run_id=ticket_id)
# Compliance exports - get all data for one tenant
export = client.get_memory_export(filters={"AND": [{"app_id": "sports_brand_portal"}]})
```
## Complete Example
Putting it all together - here's how to properly scope memories:
```python
# Store memories with all identifiers
client.add(
[{"role": "user", "content": "I need a hotel near the conference center."}],
user_id="exec_123",
agent_id="booking_assistant",
app_id="enterprise_portal",
run_id="trip-2025-03",
version="v2"
)
# Retrieve with the same scope
filters = {
"AND": [
{"user_id": "exec_123"},
{"app_id": "enterprise_portal"},
{"run_id": "trip-2025-03"}
]
}
# Alternative: Use wildcards if you're not sure about some fields
# filters = {
# "AND": [
# {"user_id": "exec_123"},
# {"agent_id": "*"}, # Match any agent
# {"app_id": "enterprise_portal"},
# {"run_id": "*"} # Match any run
# ]
# }
results = client.search("Hotels near conference", filters=filters)
# Debug: Print the filter you're using
print(f"Searching with filters: {filters}")
# If no results, try a broader search to see what's stored
if not results["results"]:
print("No results found! Trying broader search...")
broader = client.get_all(filters={"user_id": "exec_123"})
print(broader)
print(results["results"][0]["memory"])
```
**Output:**
```
I need a hotel near the conference center.
```
## When to Use Each Identifier
| Identifier | When to Use | Example Values |
|------------|-------------|----------------|
| `user_id` | Individual preferences that persist across all interactions | `cam_traveler`, `sarah_exec`, `team_alpha` |
| `agent_id` | Different AI roles need separate context | `travel_agent`, `concierge`, `customer_support` |
| `app_id` | White-label deployments or separate products | `travel_app_ios`, `enterprise_portal`, `partner_integration` |
| `run_id` | Temporary sessions that should be isolated | `support_ticket_9234`, `chat_session_456`, `booking_flow_789` |
## Troubleshooting Common Issues
### My search returns empty results!
**Problem**: Using `AND` with exact matches but some fields might be `null`.
**Solution**:
```python
# If this returns nothing:
filters = {"AND": [{"user_id": "u1"}, {"agent_id": "a1"}]}
# Try using wildcards:
filters = {"AND": [{"user_id": "u1"}, {"agent_id": "*"}]}
# Or don't include fields you don't need:
filters = {"AND": [{"user_id": "u1"}]}
```
### OR gives results but AND doesn't
This confirms you have a **field mismatch**. The memory exists but some identifier values don't match exactly.
**Always check what's actually stored:**
```python
# Get all memories for the user to see the actual field values
all_mems = client.get_all(filters={"user_id": "your_user_id"})
print(json.dumps(all_mems, indent=2))
```
## Best Practices
1. **Use consistent identifier formats**
```python
# Good: consistent patterns
user_id = "cam_traveler"
agent_id = "travel_agent_v1"
app_id = "nora_concierge_app"
run_id = "tokyo_trip_2025_03"
# Avoid: mixed patterns
# user_id = "123", agent_id = "agent2", app_id = "app"
```
2. **Print filters when debugging**
```python
filters = {"AND": [{"user_id": "cam", "agent_id": "chef"}]}
print(f"Searching with filters: {filters}") # Helps catch typos
```
3. **Clean up temporary sessions**
```python
# After a support ticket closes
client.delete_all(user_id="customer_123", run_id="ticket_456")
```
## Summary
You learned how to:
- Store memories with proper entity scoping using `user_id`, `agent_id`, `app_id`, and `run_id`
- Prevent memory leaks between different agents and applications
- Clean up data for specific tenants or sessions
- Use wildcards to query across scoped memories
## Next Steps
<CardGroup cols={2}>
<Card
title="Deep Dive: Memory Filters v2"
description="Layer entity filters with JSON logic to answer complex queries."
icon="sliders"
href="/platform/features/v2-memory-filters"
/>
<Card
title="Control Memory Ingestion"
description="Pair scoped storage with rules that block low-quality facts."
icon="shield-check"
href="/cookbooks/essentials/controlling-memory-ingestion"
/>
</CardGroup>
@@ -76,8 +76,8 @@ This is a simple example of how to use Mem0 to create a personalized AI agent. Y
---
<CardGroup cols={2}>
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
Separate agent and user memories to maintain consistent character personalities.
<Card title="Partition Memories by Entity" icon="layers" href="/cookbooks/essentials/entity-partitioning-playbook">
Keep character personas isolated by tagging user, agent, and session identifiers.
</Card>
<Card title="AI Tutor with Mem0" icon="graduation-cap" href="/cookbooks/companions/ai-tutor">
Build another type of personalized companion with memory capabilities.
@@ -365,7 +365,7 @@ Based on our previous session, I remember we covered Vision Language Models and
<Card title="LlamaIndex ReAct with Mem0" icon="brain" href="/cookbooks/frameworks/llamaindex-react">
Start with single-agent patterns before scaling to multi-agent systems.
</Card>
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
Learn how to scope memories across multiple agents and users.
<Card title="Partition Memories by Entity" icon="layers" href="/cookbooks/essentials/entity-partitioning-playbook">
Learn how to scope memories across multiple agents, users, and sessions.
</Card>
</CardGroup>
+2 -2
View File
@@ -129,8 +129,8 @@ In the example above:
---
<CardGroup cols={2}>
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
Separate agent and user memories to maintain consistent personalities.
<Card title="Partition Memories by Entity" icon="layers" href="/cookbooks/essentials/entity-partitioning-playbook">
Separate user, agent, and app memories to keep multi-agent flows clean.
</Card>
<Card title="Agents SDK Tool with Mem0" icon="robot" href="/cookbooks/integrations/agents-sdk-tool">
Explore tool-calling patterns with the OpenAI Agents SDK.
@@ -127,8 +127,8 @@ Mem0 enables fast, transparent collaboration for teams and agents, with full att
---
<CardGroup cols={2}>
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
Learn how to scope memories across users and agents for team workflows.
<Card title="Partition Memories by Entity" icon="layers" href="/cookbooks/essentials/entity-partitioning-playbook">
Learn how to scope memories across users, agents, and runs for team workflows.
</Card>
<Card title="Support Inbox with Mem0" icon="headset" href="/cookbooks/operations/support-inbox">
Apply collaborative memory patterns to customer support scenarios.
+2 -2
View File
@@ -19,8 +19,8 @@ Here are some examples of how Mem0 can be integrated into various applications:
<Card title="Build a Companion with Mem0" icon="users" href="/cookbooks/essentials/building-ai-companion">
Learn core memory lifecycle patterns.
</Card>
<Card title="Scope User vs Agent Memories" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
Balance personalization with consistent behavior.
<Card title="Partition Memories by Entity" icon="layers" href="/cookbooks/essentials/entity-partitioning-playbook">
Balance personalization with consistent behavior across users, agents, and apps.
</Card>
<Card title="Control Memory Ingestion" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
Filter speculation and low-confidence data.
+2 -1
View File
@@ -63,6 +63,7 @@
"icon": "circle-check",
"pages": [
"platform/features/v2-memory-filters",
"platform/features/entity-scoped-memory",
"platform/features/async-client",
"platform/features/async-mode-default-change",
"platform/features/multimodal-support",
@@ -315,7 +316,7 @@
"icon": "flag",
"pages": [
"cookbooks/essentials/building-ai-companion",
"cookbooks/essentials/building-ai-with-personality",
"cookbooks/essentials/entity-partitioning-playbook",
"cookbooks/essentials/controlling-memory-ingestion",
"cookbooks/essentials/memory-expiration-short-and-long-term",
"cookbooks/essentials/tagging-and-organizing-memories",
+1 -1
View File
@@ -163,7 +163,7 @@ Key differentiators:
### Essential Guides
- [Building AI Companion](https://docs.mem0.ai/cookbooks/essentials/building-ai-companion): Core patterns for building AI agents with memory
- [Building AI with Personality](https://docs.mem0.ai/cookbooks/essentials/building-ai-with-personality): Creating AI agents that have distinct personalities and behaviors
- [Partition Memories by Entity](https://docs.mem0.ai/cookbooks/essentials/entity-partitioning-playbook): Keep multi-tenant assistants isolated by tagging user, agent, app, and session identifiers
- [Controlling Memory Ingestion](https://docs.mem0.ai/cookbooks/essentials/controlling-memory-ingestion): Fine-tune what gets stored in memory and when
- [Memory Expiration](https://docs.mem0.ai/cookbooks/essentials/memory-expiration-short-and-long-term): Implement short-term and long-term memory strategies
- [Tagging and Organizing Memories](https://docs.mem0.ai/cookbooks/essentials/tagging-and-organizing-memories): Advanced memory organization and categorization
@@ -0,0 +1,193 @@
---
title: Entity-Scoped Memory
description: Scope conversations by user, agent, app, and session so memories land exactly where they belong.
---
Mem0's Platform API lets you separate memories for different users, agents, and apps. By tagging each write and query with the right identifiers, you can prevent data from mixing between them, maintain clear audit trails, and control data retention.
<Tip icon="layers">
Want the long-form tutorial? The <Link href="/cookbooks/essentials/entity-partitioning-playbook">Partition Memories by Entity</Link> cookbook walks through multi-agent storage, debugging, and cleanup step by step.
</Tip>
<Info>
**You'll use this when…**
- You run assistants for multiple customers who each need private memory spaces
- Different agents (like a planner and a critic) need separate context for the same user
- Sessions should expire on their own schedule, making debugging and data removal more precise
</Info>
## Configure access
```python
from mem0 import MemoryClient
client = MemoryClient(api_key="m0-...")
```
Call `client.project.get()` to verify your connection. It should return your project details including `org_id` and `project_id`. If you get a 401 error, generate a new API key in the Mem0 dashboard.
## Feature anatomy
| Dimension | Field | When to use it | Example value |
| ----------- | ---------- | ------------------------------------------------ | ------------------- |
| User | `user_id` | Persistent persona or account | `"customer_6412"` |
| Agent | `agent_id` | Distinct agent persona or tool | `"meal_planner"` |
| Application | `app_id` | White-label app or product surface | `"ios_retail_demo"` |
| Session | `run_id` | Short-lived flow, ticket, or conversation thread | `"ticket-9241"` |
- **Writes** (`client.add`) accept any combination of these fields. Absent fields default to `null`.
- **Reads** (`client.search`, `client.get_all`, exports, deletes) accept the same identifiers inside the `filters` JSON object.
- **Implicit null scoping**: Passing only `{"user_id": "alice"}` automatically restricts results to records where `agent_id`, `app_id`, and `run_id` are `null`. Add wildcards (`"*"`), explicit lists, or additional filters when you need broader joins.
<Warning>
**Common Pitfall**: If you create a memory with `user_id="alice"` but the other fields default to `null`, then search with `{"AND": [{"user_id": "alice"}, {"agent_id": "bot"}]}` will return nothing because you're looking for a memory where `agent_id="bot"`, not `null`.
</Warning>
## Choose the right identifier
| Identifier | Purpose | Example Use Cases |
|------------|---------|-------------------|
| `user_id` | Store preferences, profile details, and historical actions that follow a person everywhere | Dietary restrictions, seat preferences, meeting habits |
| `agent_id` | Keep an agent's personality, operating modes, or brand voice in one place | Travel agent vs concierge vs customer support personas |
| `app_id` | Tag every write from a partner app or deployment for tenant separation | White-label deployments, partner integrations |
| `run_id` | Isolate temporary flows that should reset or expire independently | Support tickets, chat sessions, experiments |
For more detailed examples, see the Partition Memories by Entity cookbook.
## Configure it
The example below adds memories with entity tags:
```python
messages = [
{"role": "user", "content": "I teach ninth-grade algebra."},
{"role": "assistant", "content": "I'll tailor study plans to algebra topics."}
]
client.add(
messages,
user_id="teacher_872",
agent_id="study_planner",
app_id="district_dashboard",
run_id="prep-period-2025-09-02",
version="v2"
)
```
The response will include one or more memory IDs. Check the dashboard → Memories to confirm the entry appears under the correct user, agent, app, and run.
The HTTP equivalent uses `POST /v1/memories/` with the same identifiers in the JSON body. See the Add Memories API reference for REST details.
## See it in action
**1. Store scoped memories**
```python
traveler_messages = [
{"role": "user", "content": "I prefer boutique hotels and avoid shellfish."},
{"role": "assistant", "content": "Logged your travel preferences for future itineraries."}
]
client.add(
traveler_messages,
user_id="customer_6412",
agent_id="travel_planner",
app_id="concierge_portal",
run_id="itinerary-2025-apr",
metadata={"category": "preferences"},
version="v2"
)
```
**2. Retrieve by user scope**
```python
user_scope = {
"AND": [
{"user_id": "customer_6412"},
{"app_id": "concierge_portal"},
{"run_id": "itinerary-2025-apr"}
]
}
user_results = client.search("Any dietary flags?", filters=user_scope)
print(user_results)
```
**3. Retrieve by agent scope**
```python
agent_scope = {
"AND": [
{"agent_id": "travel_planner"},
{"app_id": "concierge_portal"}
]
}
agent_results = client.search("Any dietary flags?", filters=agent_scope)
print(agent_results)
```
<Tip icon="compass">
Writes can include multiple identifiers, but searches resolve one entity space at a time. Query user scope *or* agent scope in a given call—combining both returns an empty list today.
</Tip>
<Tip icon="sparkles">
Want to experiment with AND/OR logic, nested operators, or wildcards? The <Link href="/platform/features/v2-memory-filters">Memory Filters v2 guide</Link> walks through every filter pattern with working examples.
</Tip>
**4. Audit everything for an app**
```python
app_scope = {
"AND": [
{"app_id": "concierge_portal"},
{"user_id": "*"},
{"agent_id": "*"}
]
}
page = client.get_all(filters=app_scope, page=1, page_size=20)
```
<Info>
Wildcards (`"*"`) include only non-null values. Use them when you want "any agent" or "any user" without limiting results to null-only records.
</Info>
**5. Clean up a session**
```python
client.delete_all(
user_id="customer_6412",
run_id="itinerary-2025-apr"
)
```
<Info icon="check">
A successful delete returns `{"message": "Memories deleted successfully!"}`. Run the previous `get_all` call again to confirm the session memories were removed.
</Info>
## Verify the feature is working
- Run `client.search` with your filters and confirm only expected memories appear. Mismatched identifiers usually mean a typo in your scoping.
- Check the Mem0 dashboard filter pills. User, agent, app, and run should all show populated values for your memory entry.
- Call `client.delete_all` with a unique `run_id` and confirm other sessions remain intact (the count in `get_all` should only drop for that run).
## Best practices
- Use consistent identifier formats (like `team-alpha` or `app-ios-retail`) so you can query or delete entire groups later
- When debugging, print your filters before each call to verify wildcards (`"*"`), lists, and run IDs are spelled correctly
- Combine entity filters with metadata filters (categories, created_at) for precise exports or audits
- Use `run_id` for temporary sessions like support tickets or experiments, then schedule cleanup jobs to delete them
For a complete walkthrough, see the Partition Memories by Entity cookbook.
{/* DEBUG: verify CTA targets */}
<CardGroup cols={2}>
<Card
title="Master Memory Filters"
description="Deep dive into JSON logic, operators, and wildcard behavior."
icon="sliders"
href="/platform/features/v2-memory-filters"
/>
<Card
title="Partition Memories in Practice"
description="Follow the essentials cookbook to implement scoped workflows."
icon="book-open"
href="/cookbooks/essentials/entity-partitioning-playbook"
/>
</CardGroup>