docs/platform/features/entity-scoped-memory.mdx
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>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.
| 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" |
client.add) accept any combination of these fields. Absent fields default to null.client.search, client.get_all, exports, deletes) accept the same identifiers inside the filters JSON object.{"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.| 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.
The example below adds memories with entity tags:
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"
)
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.
<Warning> Platform writes that include both `user_id` and `agent_id` (or other combinations) are persisted as separate records per entity so we can enforce privacy boundaries. Each record carries exactly one primary entity, which is why `{"AND": [{"user_id": ...}, {"agent_id": ...}]}` never returns results. Plan searches per entity scope or combine scopes with `OR`. </Warning>The HTTP equivalent uses POST /v1/memories/ with the same identifiers in the JSON body. See the Add Memories API reference for REST details.
1. Store scoped memories
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"}
)
2. Retrieve by user scope
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
agent_scope = {
"AND": [
{"agent_id": "travel_planner"},
{"app_id": "concierge_portal"}
]
}
agent_results = client.search("Any dietary flags?", filters=agent_scope)
print(agent_results)
4. Audit everything for an app
app_scope = {
"AND": [
{"app_id": "concierge_portal"}
],
"OR": [
{"user_id": "*"},
{"agent_id": "*"}
]
}
page = client.get_all(filters=app_scope, page=1, page_size=20)
5. Clean up a session
client.delete_all(
user_id="customer_6412",
run_id="itinerary-2025-apr"
)
client.search with your filters and confirm only expected memories appear. Mismatched identifiers usually mean a typo in your scoping.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).team-alpha or app-ios-retail) so you can query or delete entire groups later"*"), lists, and run IDs are spelled correctlyrun_id for temporary sessions like support tickets or experiments, then schedule cleanup jobs to delete themFor a complete walkthrough, see the Partition Memories by Entity cookbook.
<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>