Custom Categories - Mem0
Custom Categories
Mem0 automatically tags every memory, but the default labels (travel, sports, music, etc.) may not match the names your app uses. Custom categories let you replace that list so the tags line up with your own wording.
Use custom categories when…
- You need Mem0 to tag memories with names your product team already uses.
- You want clean reports or automations that rely on those tags.
- You’re moving from the open-source version and want the same labels here.
You can set the list once for the whole project, or pass a different list on an individual add call.
Configure access
- Ensure
MEM0_API_KEYis set in your environment or pass it to the SDK constructor. - If you scope work to a specific organization/project, initialize the client with those identifiers.
How it works
- Default list: Each project starts with 15 broad categories like
travel,sports, andmusic. - Project override: When you call
project.update(custom_categories=[...]), that list replaces the defaults for future memories. - Per-call override: When you pass
custom_categories=[...]toclient.add(...), that list is used for the memories extracted from that call. - Automatic tags: As new memories come in, Mem0 picks the closest matches from the active list and saves them in the
categoriesfield.
Which list wins
Mem0 resolves the category catalog for each add call in this order, and stops at the first one it finds:
custom_categoriespassed on theaddcallcustom_categoriesset on the project- The built-in default catalog
A per-call list fully replaces the project list for that call. The two are not merged, so a memory added with a per-call list can only be tagged with categories from that list. Categories are applied at ingestion time. Changing the project list, or passing a new per-call list, does not re-tag memories that already exist.
Default catalog: personal_details, family, professional_details, sports, travel, food, music, health, technology, hobbies, fashion, entertainment, milestones, user_preferences, misc.
Configure it
1. Set custom categories at the project level
Code
import os
from mem0 import MemoryClient
os.environ["MEM0_API_KEY"] = "your-api-key"
client = MemoryClient()
# Update custom categories
new_categories = [
{"lifestyle_management_concerns": "Tracks daily routines, habits, hobbies and interests including cooking, time management and work-life balance"},
{"seeking_structure": "Documents goals around creating routines, schedules, and organized systems in various life areas"},
{"personal_information": "Basic information about the user including name, preferences, and personality traits"}
]
response = client.project.update(custom_categories=new_categories)
print(response)
{
"message": "Updated custom categories"
}
2. Confirm the active catalog
Code
# Get current custom categories
categories = client.project.get(fields=["custom_categories"])
print(categories)
{
"custom_categories": [
{"lifestyle_management_concerns": "Tracks daily routines, habits, hobbies and interests including cooking, time management and work-life balance"},
{"seeking_structure": "Documents goals around creating routines, schedules, and organized systems in various life areas"},
{"personal_information": "Basic information about the user including name, preferences, and personality traits"}
]
}
get echoes back the shape you set. update also accepts a plain list of names, such as [ "billing", "support" ], in which case get returns that same list of names. Descriptions are optional here, and the classifier uses them to disambiguate when it has them.
add is stricter than update. Every entry in a per-call custom_categories list must be an object mapping a name to a description. Passing bare names to add fails with 400 Expected a dictionary of items but got type "str".
3. Override categories on a single add call
Pass custom_categories directly to add when one call needs a different catalog than the project default. The memories created by that call are tagged from the list you pass, and the project list is left untouched.
Python
health_messages = [
{"role": "user", "content": "My doctor bumped my metformin to 1000mg and I see her again on the 14th."},
{"role": "assistant", "content": "Noted the new dosage and the follow-up appointment."},
]
health_categories = [
{"symptoms": "Reported physical or mental symptoms"},
{"medications": "Prescriptions, dosages, and adherence"},
{"appointments": "Scheduled visits and follow-ups"},
]
client.add(
health_messages,
user_id="alice",
custom_categories=health_categories,
)
const healthMessages = [
{ role: "user", content: "My doctor bumped my metformin to 1000mg and I see her again on the 14th." },
{ role: "assistant", content: "Noted the new dosage and the follow-up appointment." },
];
const healthCategories = [
{ symptoms: "Reported physical or mental symptoms" },
{ medications: "Prescriptions, dosages, and adherence" },
{ appointments: "Scheduled visits and follow-ups" },
];
await client.add(healthMessages, {
userId: "alice",
customCategories: healthCategories,
});
["medications", "appointments"]
The memory is tagged from health_categories alone. The project catalog is not consulted for this call, and it is not modified.
Per-user categories inside one project
The main reason to reach for a per-call list is to give different users, tenants, or entities their own vocabulary without splitting them across projects. Keep one project, and pass the list that fits the entity you are writing for.
Python
patient_categories = [
{"symptoms": "Reported physical or mental symptoms"},
{"medications": "Prescriptions, dosages, and adherence"},
]
clinician_categories = [
{"caseload": "Patients under this clinician's care"},
{"availability": "Shift patterns and on-call windows"},
]
client.add("My metformin is now 1000mg.", user_id="alice", custom_categories=patient_categories)
client.add("I'm on call Tuesdays and Thursdays.", user_id="dr-reyes", custom_categories=clinician_categories)
See it in action
Add a memory (uses the project catalog automatically)
Code
messages = [
{"role": "user", "content": "My name is Alice. I need help organizing my daily schedule better. I feel overwhelmed trying to balance work, exercise, and social life."},
{"role": "assistant", "content": "I understand how overwhelming that can feel. Let's break this down together. What specific areas of your schedule feel most challenging to manage?"},
{"role": "user", "content": "I want to be more productive at work, maintain a consistent workout routine, and still have energy for friends and hobbies."},
{"role": "assistant", "content": "Those are great goals for better time management. What's one small change you could make to start improving your daily routine?"},
]
# Add memories with project-level custom categories
client.add(messages, user_id="alice")
Retrieve memories and inspect categories
get_all returns a paginated object. The memories are under results, and each one carries its own categories list.
Code
response = client.get_all(filters={"user_id": "alice"})
for memory in response["results"]:
print(memory["memory"], memory["categories"])
User introduced herself as Alice and expressed a desire for help organizing her daily schedule. ['lifestyle_management_concerns', 'seeking_structure', 'personal_information']
User feels overwhelmed trying to balance work responsibilities, regular exercise, and a social life, indicating difficulty managing time across these areas. ['lifestyle_management_concerns']
User's goals include becoming more productive at work, maintaining a consistent workout routine, and preserving enough energy for friends and hobbies. ['lifestyle_management_concerns', 'seeking_structure']
Extraction is model driven, so the exact wording and the number of memories vary between runs. The categories are drawn from the active list.
Sample memory payload
{
"id": "638008c4-***",
"memory": "User is seeking to balance work responsibilities with regular workout sessions and requests a personalized schedule to manage both.",
"user_id": "alice",
"metadata": null,
"categories": ["lifestyle_management_concerns", "seeking_structure"],
"created_at": "2026-07-10T06:13:12-07:00",
"updated_at": "2026-07-10T06:13:20-07:00",
"expiration_date": null,
"structured_attributes": {
"year": 2026,
"month": 7,
"day": 10,
"hour": 13,
"minute": 13,
"day_of_week": "friday",
"week_of_year": 28,
"day_of_year": 191,
"quarter": 3,
"is_weekend": false
}
}
Categorization runs asynchronously, a moment after the memory itself is written. A memory fetched immediately after add may not show up in get_all yet, or can come back with categories: null and pick up its tags a moment later. Poll until categories is populated rather than reading once.
Default categories (fallback)
If you do nothing, memories are tagged with the built-in set below.
- personal_details
- family
- professional_details
- sports
- travel
- food
- music
- health
- technology
- hobbies
- fashion
- entertainment
- milestones
- user_preferences
- misc
Code
Memories with categories
import os
from mem0 import MemoryClient
os.environ["MEM0_API_KEY"] = "your-api-key"
client = MemoryClient()
messages = [
{"role": "user", "content": "Hi, my name is Alice."},
{"role": "assistant", "content": "Hi Alice, what sports do you like to play?"},
{"role": "user", "content": "I love playing badminton, football, and basketball. I'm quite athletic!"},
{"role": "assistant", "content": "That's great! Alice seems to enjoy both individual sports like badminton and team sports like football and basketball."},
{"role": "user", "content": "Sometimes, I also draw and sketch in my free time."},
{"role": "assistant", "content": "That's cool! I'm sure you're good at it."}
]
# Add memories with default categories
client.add(messages, user_id='alice')
# Following categories will be created for the memories added
Sometimes draws and sketches in free time (hobbies)
Is quite athletic (sports)
Loves playing badminton, football, and basketball (sports)
Name is Alice (personal_details)
You can verify the defaults are active by checking:
Code
Output
client.project.get(["custom_categories"])
{
"custom_categories": null
}
A project that has never set a list returns null. One you have reset with project.update(custom_categories=[]) returns []. Both mean the default catalog is active.
Verify the feature is working
client.project.get(["custom_categories"])returns the category list you set.client.get_all(filters={"user_id": ...})shows populatedcategorieslists on new memories.- The Mem0 dashboard (Project → Memories) displays the custom labels in the Category column.
Best practices
- Keep category descriptions concise but specific; the classifier uses them to disambiguate.
- Review memories with empty
categoriesto see where you might extend or rename your list. - Set the catalog your app uses most often at the project level, and reserve per-call lists for the calls that genuinely need a different vocabulary.
- If a per-call list should also keep the project categories, include them in the list you pass. Passing a list replaces, it does not extend.