How to Filter Memories by user_id, agent_id, or run_id in Mem0
To filter memories in Mem0, pass a dictionary containing user_id, agent_id, and/or run_id to the filters parameter of the search() or list() methods, which the underlying vector store converts to native query syntax.
Mem0 (from the mem0ai/mem0 repository) stores every memory vector alongside a payload containing arbitrary metadata. The framework provides a unified filtering interface that works across Qdrant, Valkey, Pinecone, and other vector stores, allowing you to scope queries to specific users, agents, or execution runs.
How Filtering Works at the Vector Store Layer
Mem0 implements filtering at two architectural layers. The vector store layer translates Python dictionaries into database-specific query languages, while the SDK layer exposes a consistent API regardless of your backend.
In mem0/vector_stores/base.py, the abstract list(self, filters=None, limit=None) method defines the contract that every storage backend must implement. Concrete implementations in qdrant.py and valkey.py handle the translation:
- Qdrant (
mem0/vector_stores/qdrant.py, lines 41-61): Converts thefiltersdict into a QdrantFilterobject composed ofFieldConditioninstances. - Valkey (
mem0/vector_stores/valkey.py, lines 558-567): Constructs a RediSearch query string using the syntax@user_id:{alice} @agent_id:{agent1} @run_id:{run1}.
Filtering Memories with the Python SDK
The high-level Mem0 client exposes search() for similarity-based retrieval and list() for direct metadata queries. Both methods accept a filters dictionary supporting any combination of the three identifier keys.
Search with Similarity and Filters
Use search() when you need semantic similarity combined with metadata constraints. The method embeds your query, retrieves nearest neighbors, and applies the payload filters before returning results.
from mem0 import Mem0
mem = Mem0(
embedding_model="all-MiniLM-L6-v2",
vector_store="qdrant",
collection_name="my_memories",
)
results = mem.search(
query="What did I ask about the budget?",
limit=5,
filters={
"user_id": "alice",
"agent_id": "agent1",
"run_id": "run1",
},
)
for r in results:
print(r.payload)
Omitted keys in the filters dict are ignored, allowing flexible query scoping.
List Memories by Metadata Only
Use list() when you need to retrieve all memories matching specific metadata without vector similarity search. This executes a pure metadata filter against the vector store.
matches = mem.list(
filters={
"user_id": "alice",
"agent_id": "agent1",
"run_id": "run1",
},
limit=100,
)
for m in matches:
print(m.id, m.payload)
Implementation Details by Vector Store
Different storage backends translate the filters dictionary into their native query languages.
Qdrant Implementation
In mem0/vector_stores/qdrant.py, the _create_filter method constructs a Qdrant Filter object. Each key-value pair in your filters dict becomes a FieldCondition that Qdrant applies during the vector search.
# Conceptual implementation from qdrant.py
from qdrant_client.models import Filter, FieldCondition, MatchValue
def _create_filter(self, filters):
conditions = [
FieldCondition(key=k, match=MatchValue(value=v))
for k, v in filters.items()
]
return Filter(must=conditions)
Valkey Implementation
In mem0/vector_stores/valkey.py, the implementation builds a RediSearch query string. The filters dict is converted to the RediSearch tag syntax:
# From valkey.py lines 558-567
query_parts = [f"@{k}:{{{v}}}" for k, v in filters.items()]
rediserch_query = " ".join(query_parts)
# Result: @user_id:{alice} @agent_id:{agent1} @run_id:{run1}
Using the REST API
The OpenMemory HTTP API exposes a /api/v1/memories/filter endpoint defined in openmemory/api/app/routers/memories.py (lines 45-66). Currently, this endpoint filters by user, application, category, and date ranges, but does not expose the generic filters dictionary for agent_id or run_id.
To enable full filtering via HTTP, extend the request model to accept a filters field and forward it to the SDK:
from typing import Dict, Optional
from pydantic import BaseModel
class FilterMemoriesRequest(BaseModel):
user_id: str
page: int = 1
size: int = 10
filters: Optional[Dict[str, str]] = None # Add this field
# In the endpoint handler:
results = mem_client.list(
filters=request.filters,
limit=request.size,
)
Summary
- Mem0 stores user_id, agent_id, and run_id in each memory's payload metadata.
- Pass a
filtersdictionary tomem.search()ormem.list()to scope results by these fields. - Qdrant converts filters to
Filterobjects withFieldConditioninstances. - Valkey converts filters to RediSearch query strings using tag syntax (
@field:{value}). - The REST API can be extended to support these filters by adding a
filtersfield to the request model inmemories.py.
Frequently Asked Questions
Can I filter by only one of the IDs, or do I need all three?
You can filter by any combination. The filters dictionary accepts any subset of user_id, agent_id, and run_id. Omitting a key means that dimension is not constrained in the query, allowing you to filter by just user_id, by user_id and agent_id together, or any other combination.
Does filtering work with all vector store backends?
Yes. The base class in mem0/vector_stores/base.py mandates that all implementations support the filters parameter in their list() method. Whether using Qdrant, Valkey (Redis), Pinecone, or another supported store, the SDK translates the Python dictionary into the native query syntax automatically.
How do I filter memories for a specific user across all agents?
Pass only the user_id key in your filters dictionary:
results = mem.list(filters={"user_id": "alice"}, limit=50)
This returns all memories where the payload contains "user_id": "alice" regardless of which agent_id or run_id created them.
Is there a performance difference between search() and list() when filtering?
Yes. search() performs a vector similarity search first, then applies filters, which is computationally heavier. list() applies metadata filters directly against the vector store indexes without computing vector distances, making it faster for pure metadata retrieval. Use list() when you only need to filter by IDs and do not require semantic similarity matching.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →