Entity-Scoped Memory - Mem0

Documentation Index

Fetch the complete documentation index at: /llms.txt

Use this file to discover all available pages before exploring further.

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.

Entity IDs vs. graph entities. This page covers the user_id / agent_id / app_id / run_id identifiers used to scope memories. These are different from the graph entities (the people, places, and concepts surfaced in Graph Memory).

Want the long-form tutorial? The Partition Memories by Entity cookbook walks through multi-agent storage, debugging, and cleanup step by step.

You’ll use this when…

Configure access

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"

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.

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:

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.

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.

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

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)

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.

Want to experiment with AND/OR logic, nested operators, or wildcards? The Memory Filters v2 guide walks through every filter pattern with working examples.

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)

Wildcards (\"*\") include only non-null values. Use them when you want “any agent” or “any user” without limiting results to null-only records.

5. Clean up a session

client.delete_all(
    user_id=\"customer_6412\",
    run_id=\"itinerary-2025-apr\"
)

A successful delete returns {\"message\": \"Memories deleted successfully!\"}. Run the previous get_all call again to confirm the session memories were removed.

Verify the feature is working

Best practices

For a complete walkthrough, see the Partition Memories by Entity cookbook.