> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mem0.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Categories

> Replace default memory tags with custom category labels that match your product terminology, set once per project or per individual add call.

# 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.

<Info>
  **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.
</Info>

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_KEY` is 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`, and `music`.
* **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=[...]` to `client.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 `categories` field.

### Which list wins

Mem0 resolves the category catalog for each `add` call in this order, and stops at the first one it finds:

1. `custom_categories` passed on the `add` call
2. `custom_categories` set on the project
3. 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.

<Note>
  Default catalog: `personal_details`, `family`, `professional_details`, `sports`, `travel`, `food`, `music`, `health`, `technology`, `hobbies`, `fashion`, `entertainment`, `milestones`, `user_preferences`, `misc`.
</Note>

## Configure it

### 1. Set custom categories at the project level

<CodeGroup>
  ```python Code theme={null}
  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)
  ```

  ```json Output theme={null}
  {
      "message": "Updated custom categories"
  }
  ```
</CodeGroup>

### 2. Confirm the active catalog

<CodeGroup>
  ```python Code theme={null}
  # Get current custom categories
  categories = client.project.get(fields=["custom_categories"])
  print(categories)
  ```

  ```json Output theme={null}
  {
    "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"}
    ]
  }
  ```
</CodeGroup>

`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.

<Warning>
  `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"`.
</Warning>

### 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.

<CodeGroup>
  ```python Python theme={null}
  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,
  )
  ```

  ```javascript JavaScript theme={null}
  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,
  });
  ```

  ```text Resulting categories theme={null}
  ["medications", "appointments"]
  ```
</CodeGroup>

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.

<CodeGroup>
  ```python Python theme={null}
  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)
  ```
</CodeGroup>

## See it in action

### Add a memory (uses the project catalog automatically)

<CodeGroup>
  ```python Code theme={null}
  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")
  ```
</CodeGroup>

### Retrieve memories and inspect categories

`get_all` returns a paginated object. The memories are under `results`, and each one carries its own `categories` list.

<CodeGroup>
  ```python Code theme={null}
  response = client.get_all(filters={"user_id": "alice"})

  for memory in response["results"]:
      print(memory["memory"], memory["categories"])
  ```

  ```text Output theme={null}
  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']
  ```
</CodeGroup>

Extraction is model driven, so the exact wording and the number of memories vary between runs. The categories are drawn from the active list.

<Info>
  **Sample memory payload**

  ```json theme={null}
  {
    "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
    }
  }
  ```
</Info>

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.

<Note>
  Need ad-hoc labels for a single call? Pass `custom_categories` on that `add` call. Use `metadata` instead when the label is a fixed value you already know, rather than something the classifier should infer.
</Note>

## 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
```

<CodeGroup>
  ```python Code theme={null}
  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')
  ```

  ```text Memories with categories theme={null}
  # 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)
  ```
</CodeGroup>

You can verify the defaults are active by checking:

<CodeGroup>
  ```python Code theme={null}
  client.project.get(["custom_categories"])
  ```

  ```json Output theme={null}
  {
      "custom_categories": null
  }
  ```
</CodeGroup>

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 populated `categories` lists 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 `categories` to 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.

<CardGroup cols={2}>
  <Card title="Advanced Memory Operations" icon="wand-magic-sparkles" href="/platform/advanced-memory-operations">
    Explore other ingestion tunables like custom prompts and selective writes.
  </Card>

  <Card title="Travel Assistant Cookbook" icon="plane-up" href="/cookbooks/companions/travel-assistant">
    See custom tagging drive personalization in a full agent workflow.
  </Card>
</CardGroup>
