# How Mem0 Handles Memory Updates: Explicit API and LLM-Driven Triggers Explained

> Discover how Mem0 handles memory updates using its explicit API and LLM-driven triggers. Learn about precise control and automatic refinements for your AI memory.

- Repository: [Mem0/mem0](https://github.com/mem0ai/mem0)
- Tags: deep-dive
- Published: 2026-03-07

---

**Mem0 processes memory modifications through two distinct pathways: direct programmatic updates via the `Memory.update()` API and automatic LLM-driven refinements triggered during the `Memory.add()` inference pipeline.**

Memory updates in Mem0 operate on vector-store records that track knowledge evolution through versioned history. According to the mem0ai/mem0 source code, every modification—whether initiated by a developer or deduced by an LLM—preserves session scoping identifiers and maintains a complete audit trail in SQLite. This dual-trigger architecture allows applications to both explicitly overwrite specific memories and automatically consolidate new facts with existing knowledge.

## Overview of Memory Update Triggers

Mem0 distinguishes between **explicit** and **implicit** modification triggers. Understanding these pathways is essential for implementing deterministic versus AI-governed memory management.

- **Explicit updates** occur when a caller invokes `Memory.update()` with a specific `memory_id` and replacement text.
- **Implicit updates** happen automatically inside `Memory.add()` when the LLM determines that new conversational facts refine existing memories rather than create new ones.

Both pathways eventually converge on the internal `_update_memory()` method in [`mem0/memory/main.py`](https://github.com/mem0ai/mem0/blob/main/mem0/memory/main.py), ensuring consistent vector-store mutations and history logging regardless of the trigger source.

## Explicit Memory Updates via the Public API

Developers trigger direct modifications using the public `update()` method when they know the exact memory identifier and replacement content.

### How the `update()` Method Works

In [`mem0/memory/main.py`](https://github.com/mem0ai/mem0/blob/main/mem0/memory/main.py), the `update()` method accepts a `memory_id` and `data` payload, then delegates to `_update_memory()`. The workflow follows these steps:

1. Retrieves the existing vector and metadata from the vector store.
2. Generates a new MD5 hash of the updated text and timestamps the change.
3. Preserves immutable session identifiers (`user_id`, `agent_id`, `run_id`, `actor_id`, `role`) unless explicitly overridden.
4. Writes the modified payload via `self.vector_store.update()`.
5. Records the operation in the SQLite history table via `self.db.add_history()`.
6. Emits a telemetry event via `capture_event("mem0.update", …)` in [`mem0/utils/telemetry.py`](https://github.com/mem0ai/mem0/blob/main/mem0/utils/telemetry.py).

```python
from mem0 import Memory, MemoryConfig

mem = Memory(MemoryConfig())
mem_id = "c7f2a1d4-9b3e-4a5f-8c1e-d123456789ab"

# Explicitly replace memory content

result = mem.update(
    memory_id=mem_id,
    data="User prefers dark mode on the dashboard."
)
print(result)  # {'message': 'Memory updated successfully!'}

```

## Implicit LLM-Driven Memory Updates

The more complex trigger occurs automatically when `Memory.add()` processes new messages with inference enabled (`infer=True`). This pathway allows Mem0 to autonomously consolidate knowledge without manual intervention.

### The Memory Addition Pipeline

When `mem.add(messages, user_id="...")` executes, Mem0 initiates a multi-stage pipeline in `_add_to_vector_store()`:

1. **Fact extraction** – Converts incoming messages into structured facts using retrieval prompts.
2. **Similarity search** – Embeds each fact and queries the vector store for semantically similar existing memories scoped to the provided `user_id`, `agent_id`, or `run_id`.
3. **LLM arbitration** – Constructs a decision prompt via `get_update_memory_messages()` in [`mem0/configs/prompts.py`](https://github.com/mem0ai/mem0/blob/main/mem0/configs/prompts.py).

### LLM Decision Making and JSON Actions

The LLM receives the current memory snapshot alongside new facts and returns a strictly formatted JSON list specifying actions. Each entry contains an `event` field with values `ADD`, `UPDATE`, `DELETE`, or `NONE`.

For entries marked `"event":"UPDATE"`, the JSON includes:
- `id`: The existing memory identifier
- `text`: The refined content
- `old_memory`: The previous text for audit purposes

```json
{
  "memory": [
    {
      "id": "existing-id-123",
      "text": "User plays squash on weekends",
      "event": "UPDATE",
      "old_memory": "User plays tennis on weekends"
    }
  ]
}

```

### The `_update_memory()` Implementation

After parsing the LLM response, Mem0 invokes `_update_memory(memory_id, data, existing_embeddings, metadata)` for each UPDATE action. This method handles optional re-embedding: if the text changes significantly, the system can generate new vectors through the `existing_embeddings` map parameter before calling `self.vector_store.update(vector_id=memory_id, vector=None, payload=updated_metadata)`.

The vector parameter remains `None` when only metadata changes, preserving computational resources while updating the payload.

```python

# Implicit update triggered during conversation processing

messages = [
    {"role": "user", "content": "I just started playing squash on weekends."}
]

add_result = mem.add(
    messages,
    user_id="user_42",
    agent_id="agent_7",
    infer=True  # Enables LLM-driven consolidation

)

# Output may include UPDATE events if similar sports preferences exist

print(add_result)

```

## Session Scoping Updates (NONE Events)

When the LLM returns `"event":"NONE"`, Mem0 performs a specialized metadata-only update. This occurs when the factual content requires no modification, but session identifiers—such as a new `run_id` or `agent_id`—must be associated with the existing memory.

In this scenario, [`mem0/memory/main.py`](https://github.com/mem0ai/mem0/blob/main/mem0/memory/main.py) still calls `self.vector_store.update()`, passing the existing vector and a payload that only amends the session scoping fields. This ensures that future retrieval queries correctly filter by the new identifiers without altering the stored knowledge text or its embedding.

```python

# Session scoping update example

mem.add(
    messages,
    user_id="user_42",
    agent_id="agent_7",
    run_id="run_2026_03"  # New run context

)

# If LLM returns NONE, Mem0 updates run_id in the vector store payload

# while preserving the original memory text and vector

```

## Summary

- **Explicit triggers** use `Memory.update()` in [`mem0/memory/main.py`](https://github.com/mem0ai/mem0/blob/main/mem0/memory/main.py) for direct, identifier-based modifications.
- **Implicit triggers** leverage the LLM during `Memory.add()` to automatically consolidate facts, guided by `get_update_memory_messages()` in [`mem0/configs/prompts.py`](https://github.com/mem0ai/mem0/blob/main/mem0/configs/prompts.py).
- **Update mechanics** in `_update_memory()` preserve session identifiers, generate new MD5 hashes, and write to SQLite history via [`mem0/memory/storage.py`](https://github.com/mem0ai/mem0/blob/main/mem0/memory/storage.py).
- **NONE events** handle session scoping without content changes, updating only metadata in the vector store payload.
- **Telemetry and versioning** ensure every modification is observable and auditable through `capture_event()` and the history table.

## Frequently Asked Questions

### What is the difference between explicit and implicit memory updates in Mem0?

Explicit updates require the developer to call `Memory.update()` with a specific `memory_id` and replacement text, providing deterministic control over exact records. Implicit updates occur automatically during `Memory.add()` when the LLM compares new facts against existing vectors and decides that an UPDATE action better serves knowledge consolidation than creating redundant entries.

### How does Mem0 decide when to update versus add a new memory?

The decision logic resides in `get_update_memory_messages()` within [`mem0/configs/prompts.py`](https://github.com/mem0ai/mem0/blob/main/mem0/configs/prompts.py). The system embeds incoming facts, searches for similar memories using session identifiers (`user_id`, `agent_id`, `run_id`), and prompts the LLM to evaluate semantic overlap. The LLM returns JSON specifying whether to ADD, UPDATE, DELETE, or preserve (NONE) each fact based on whether it represents new information, a refinement, a removal, or an exact duplicate.

### What happens to the vector embedding when a memory is updated?

During `_update_memory()`, the vector embedding remains unchanged unless the text modification necessitates re-embedding. The method accepts an optional `existing_embeddings` map; if provided with a new vector for the updated text, it updates the vector store entry. If no new embedding is supplied (metadata-only changes or session scoping), the call to `self.vector_store.update()` passes `vector=None`, preserving the original embedding while updating the payload metadata.

### How does Mem0 maintain version history for memory updates?

Every update operation writes to an SQLite history table managed by `SQLiteManager` in [`mem0/memory/storage.py`](https://github.com/mem0ai/mem0/blob/main/mem0/memory/storage.py). The `db.add_history()` call records the previous state, new content, timestamp, and action type. Additionally, `capture_event()` in [`mem0/utils/telemetry.py`](https://github.com/mem0ai/mem0/blob/main/mem0/utils/telemetry.py) emits observability data for each modification, creating a complete audit trail of how knowledge evolved over time.