Relevant source files
The following files were used as context for generating this wiki page:
- mem0/memory/main.py
- mem0-ts/src/oss/src/memory/index.ts
- mem0-ts/src/oss/src/prompts/index.ts
- integrations/opencode-plugin/opencode-mem0.ts
- integrations/claude-code-plugin/core/memory_core.py
- mem0/configs/prompts.py
- integrations/antigravity-plugin/core/memory_core.py
- integrations/hermes-plugin-mem0/init.py
- integrations/mem0-agent-plugin/core/memory_core.py
- integrations/codex-plugin/core/memory_core.py
- integrations/kimi-plugin/core/memory_core.py
- integrations/agent-plugin-core/python/memory_core.py
- integrations/cursor-plugin/core/memory_core.py
- server/main.py
- integrations/agent-plugin-core/typescript/src/lifecycle.ts
- integrations/hermes-plugin-mem0/_backend.py
- integrations/vercel-ai-sdk/src/mem0-utils.ts
- mem0/client/main.py
- mem0/configs/base.py
- mem0/memory/setup.py
- mem0/memory/notices.py
- server/server_state.py
Overview
The memory lifecycle manages the end-to-end journey of stored information, orchestrating how conversations are parsed into structured facts, linked across entities, updated in place, or systematically cleared. Operating across synchronous and asynchronous interfaces mem0/memory/main.py, the system standardizes public methods mem0/memory/main.py alongside language model fact extraction mem0-ts/src/oss/src/prompts/index.ts to transform raw interactions into queryable vectors. It governs metadata tracking, temporal expiration filters, and telemetry-driven operational notices mem0/memory/notices.py to maintain high retrieval precision and scale thresholds mem0-ts/src/oss/src/memory/index.ts.
Sources: mem0/memory/main.py:1960-2005, mem0-ts/src/oss/src/memory/index.ts:1-82, mem0-ts/src/oss/src/prompts/index.ts:1-43, mem0/memory/notices.py:99-163
Public Memory Engine Interface
Engine Method Signatures
The memory engine exposes core operations for both synchronous and asynchronous execution across management routines mem0/memory/main.py. The public interface handles initialization through MemoryConfig mem0/configs/base.py and coordinates internal lifecycle helpers like _create_memory, _update_memory, _delete_memory, and reset mem0/memory/main.py.
| Method | Parameters | Return Type | Purpose |
|---|---|---|---|
history | memory_id | list | Get the history of changes for a memory by ID mem0/memory/main.py |
_create_memory | data, existing_embeddings, metadata=None | str | Internal helper to embed, store, and record audit history for new text mem0/memory/main.py |
_create_procedural_memory | messages, metadata=None, prompt=None | dict | Generate procedural memory summaries using an LLM prompt workflow mem0/memory/main.py |
_update_memory | memory_id, data, existing_embeddings, metadata=None | str | Modify existing memory text and refresh entity-store links mem0/memory/main.py |
_delete_memory | memory_id, existing_memory=None | str | Remove vector entries, log deletion audit history, and clear entity relations mem0/memory/main.py |
reset | None | None | Reset history database, close connections, and reinitialize vector store collections mem0/memory/main.py |
Sources: mem0/memory/main.py:1960-2162
Configuration and Item Schemas
The engine initializes using MemoryConfig defaults and validates core payloads against MemoryItem mem0/configs/base.py. The configuration binds vector store settings, language models, embedding models, and audit database paths mem0/configs/base.py.
class MemoryItem(BaseModel):
id: str = Field(..., description="The unique identifier for the text data")
memory: str = Field(
..., description="The memory deduced from the text data"
) # TODO After prompt changes from platform, update this
hash: Optional[str] = Field(None, description="The hash of the memory")
# The metadata value can be anything and not just string. Fix it
metadata: Optional[Dict[str, Any]] = Field(None, description="Additional metadata for the text data")
score: Optional[float] = Field(None, description="The score associated with the text data")
created_at: Optional[str] = Field(None, description="The timestamp when the memory was created")
updated_at: Optional[str] = Field(None, description="The timestamp when the memory was updated")
class MemoryConfig(BaseModel):
vector_store: VectorStoreConfig = Field(
description="Configuration for the vector store",
default_factory=VectorStoreConfig,
)
llm: LlmConfig = Field(
description="Configuration for the language model",
default_factory=LlmConfig,
)
embedder: EmbedderConfig = Field(
description="Configuration for the embedding model",
default_factory=EmbedderConfig,
)
history_db_path: str = Field(
description="Path to the history database",
default=os.path.join(mem0_dir, "history.db"),
)
reranker: Optional[RerankerConfig] = Field(
description="Configuration for the reranker",
default=None,
)
version: str = Field(
description="The version of the API",
default="v1.1",
)
custom_instructions: Optional[str] = Field(
description="Custom instructions for fact extraction",
default=None,
)
Sources: mem0/configs/base.py:16-58
Note
During a database or vector store reset, reset() mem0/memory/main.py closes active SQLite connections, creates a fresh SQLiteManager instance at history_db_path mem0/configs/base.py, and attempts collection recreation via VectorStoreFactory.
Sources: mem0/memory/main.py:2144-2162, mem0/configs/base.py:42-45
LLM Fact Extraction Workflow
Fact Distillation Prompts and Schemas
The fact extraction workflow transforms raw conversational turns into discrete JSON objects containing structured fact lists mem0/configs/prompts.py. The engine uses targeted templates such as USER_MEMORY_EXTRACTION_PROMPT and AGENT_MEMORY_EXTRACTION_PROMPT to isolate user preferences, personal details, plans, and professional attributes mem0/configs/prompts.py.
Warning
Fact generation must isolate target participants strictly based on designated roles; USER_MEMORY_EXTRACTION_PROMPT explicitly penalizes the model if information from assistant or system messages is included mem0/configs/prompts.py.
Sources: mem0/configs/prompts.py:63-121
Procedural Memory Generation
Procedural memory creation aggregates entire conversation histories into a structured operational summary using _create_procedural_memory mem0/memory/main.py. The system wraps incoming messages with a system prompt and a terminal user turn, queries the language model, strips code block markdown, and stores the resulting summary with a procedural type tag mem0/memory/main.py.
def _create_procedural_memory(self, messages, metadata=None, prompt=None):
"""
Create a procedural memory
Args:
messages (list): List of messages to create a procedural memory from.
metadata (dict): Metadata to create a procedural memory from.
prompt (str, optional): Prompt to use for the procedural memory creation. Defaults to None.
"""
logger.info("Creating procedural memory")
parsed_messages = [
{"role": "system", "content": prompt or PROCEDURAL_MEMORY_SYSTEM_PROMPT},
*messages,
{
"role": "user",
"content": "Create procedural memory of the above conversation.",
},
]
try:
procedural_memory = self.llm.generate_response(messages=parsed_messages)
procedural_memory = remove_code_blocks(procedural_memory)
except Exception as e:
logger.error(f"Error generating procedural memory summary: {e}")
raise
if not procedural_memory:
raise ValueError(
"The LLM returned no content for the procedural memory summary. "
"The model may have declined the request or returned an empty response."
)
if metadata is None:
raise ValueError("Metadata cannot be done for procedural memory.")
metadata = {**metadata, "memory_type": MemoryType.PROCEDURAL.value}
embeddings = self.embedding_model.embed(procedural_memory, memory_action="add")
memory_id = self._create_memory(procedural_memory, {procedural_memory: embeddings}, metadata=metadata)
capture_event("mem0._create_procedural_memory", self, {"memory_id": memory_id, "sync_type": "sync"})
result = {"results": [{"id": memory_id, "memory": procedural_memory, "event": "ADD"}]}
return resultSources: mem0/memory/main.py:2007-2050
Caution
_create_procedural_memory raises a ValueError if the provided metadata dictionary is None or if the language model returns an empty string response mem0/memory/main.py.
Sources: mem0/memory/main.py:2034-2042
Vector Ingestion and Entity Linking
Metadata Preparation and Embedding Upsert
When new items are created via _create_memory, the engine checks whether precomputed embeddings exist in existing_embeddings mem0/memory/main.py. If missing, text strings are transformed into dense vector representations by invoking self.embedding_model.embed(data, memory_action="add") mem0/memory/main.py. A unique uuid.uuid4() identifier is assigned, and metadata dictionaries are cloned and populated with essential audit fields mem0/memory/main.py.
def _create_memory(self, data, existing_embeddings, metadata=None):
logger.debug(f"Creating memory with {data=}")
if data in existing_embeddings:
embeddings = existing_embeddings[data]
else:
embeddings = self.embedding_model.embed(data, memory_action="add")
memory_id = str(uuid.uuid4())
new_metadata = deepcopy(metadata) if metadata is not None else {}
new_metadata["data"] = data
new_metadata["hash"] = hashlib.md5(data.encode()).hexdigest()
if "created_at" not in new_metadata:
new_metadata["created_at"] = datetime.now(timezone.utc).isoformat()
new_metadata["updated_at"] = new_metadata["created_at"]
new_metadata["text_lemmatized"] = lemmatize_for_bm25(data)
self.vector_store.insert(
vectors=[embeddings],
ids=[memory_id],
payloads=[new_metadata],
)Sources: mem0/memory/main.py:1975-1994
Note
Metadata preparation automatically calculates an MD5 hash of the raw text and generates lemmatized tokens using lemmatize_for_bm25(data) to support keyword matching alongside dense vector search mem0/memory/main.py.
Sources: mem0/memory/main.py:1983-1988
Audit Recording and Entity Synchronization
Once the vector payload is inserted into the vector store, the transaction is recorded in the relational audit trail via self.db.add_history mem0/memory/main.py. During memory updates or deletions, _update_memory and _delete_memory invoke entity-store cleanup handlers (_remove_memory_from_entity_store and _link_entities_for_memory) to maintain cross-reference integrity across session filters (user_id, agent_id, run_id) mem0/memory/main.py.
self.db.add_history(
memory_id,
None,
data,
"ADD",
created_at=new_metadata.get("created_at"),
updated_at=new_metadata.get("updated_at"),
actor_id=new_metadata.get("actor_id"),
role=new_metadata.get("role"),
)
return memory_idSources: mem0/memory/main.py:1995-2005
Warning
Entity-store synchronization during memory modifications is text-content sensitive: _update_memory skips entity removal and relinking if the underlying text value has not changed (text_changed is false) mem0/memory/main.py.
Sources: mem0/memory/main.py:2107-2111
Memory Updates and Deletion Lifecycle
Memory Modification and Entity Resynchronization
The memory engine updates existing entries through _update_memory, which retrieves the target vector payload, validates its existence, and recomputes embeddings and hashes when text content changes mem0/memory/main.py. If the incoming data parameter is None, the engine retains the previous text value (prev_value) mem0/memory/main.py.
def _update_memory(self, memory_id, data, existing_embeddings, metadata=None):
logger.info(f"Updating memory with {data=}")
try:
existing_memory = self.vector_store.get(vector_id=memory_id)
except Exception:
# Backing-store failure, not a bad memory_id: re-raise the original so the REST layer maps it to 5xx, not 4xx.
logger.error(f"Error getting memory with ID {memory_id} during update.")
raise
if existing_memory is None:
raise ValueError(f"Memory with id {memory_id} not found. Please provide a valid 'memory_id'")
prev_value = existing_memory.payload.get("data")
if data is None:
data = prev_value
if not isinstance(data, str):
raise ValueError(f"Memory with id {memory_id} does not have text content to update")
text_changed = data != prev_value
new_metadata = deepcopy(existing_memory.payload)
if metadata is not None:
new_metadata.update(_strip_identity_keys(metadata, existing_memory.payload))
new_metadata["data"] = data
new_metadata["hash"] = hashlib.md5(data.encode()).hexdigest()
new_metadata["text_lemmatized"] = lemmatize_for_bm25(data)
new_metadata["created_at"] = existing_memory.payload.get("created_at")
new_metadata["updated_at"] = datetime.now(timezone.utc).isoformat()
if data in existing_embeddings:
embeddings = existing_embeddings[data]
else:
embeddings = self.embedding_model.embed(data, "update")
self.vector_store.update(
vector_id=memory_id,
vector=embeddings,
payload=new_metadata,
)
logger.info(f"Updating memory with ID {memory_id=} with {data=}")
self.db.add_history(
memory_id,
prev_value,
data,
"UPDATE",
created_at=new_metadata["created_at"],
updated_at=new_metadata["updated_at"],
actor_id=new_metadata.get("actor_id"),
role=new_metadata.get("role"),
)
# Entity-store cleanup: strip this memory's id from old-text entities,
# then re-extract entities from the new text and link them back.
session_filters = {k: new_metadata[k] for k in ("user_id", "agent_id", "run_id") if new_metadata.get(k)}
if text_changed:
self._remove_memory_from_entity_store(memory_id, session_filters)
self._link_entities_for_memory(memory_id, data, session_filters)
return memory_idSources: mem0/memory/main.py:2052-2112
Caution
If vector_store.get() fails due to a backing-store error rather than a missing identifier, the error is re-raised directly so that REST wrapper layers map it to a 5xx server response instead of a 4xx client error mem0/memory/main.py.
Sources: mem0/memory/main.py:2055-2060
Single Deletion and Scope Resets
Individual memory removal is executed via _delete_memory, which extracts existing payload metadata, normalizes creation timestamps to UTC, updates the vector store, records a DELETE event in history with is_deleted=1, and purges the memory identifier from the entity store mem0/memory/main.py. Bulk resets are handled by reset(), which re-initializes the SQLite history database and recreates or resets the vector collection mem0/memory/main.py.
def _delete_memory(self, memory_id, existing_memory=None):
logger.info(f"Deleting memory with {memory_id=}")
if existing_memory is None:
existing_memory = self.vector_store.get(vector_id=memory_id)
if existing_memory is None:
raise ValueError(f"Memory with id {memory_id} not found. Please provide a valid 'memory_id'")
prev_value = existing_memory.payload.get("data", "")
created_at = _normalize_iso_timestamp_to_utc(existing_memory.payload.get("created_at"))
updated_at = datetime.now(timezone.utc).isoformat()
payload = existing_memory.payload or {}
session_filters = {k: payload[k] for k in ("user_id", "agent_id", "run_id") if payload.get(k)}
self.vector_store.delete(vector_id=memory_id)
self.db.add_history(
memory_id,
prev_value,
None,
"DELETE",
created_at=created_at,
updated_at=updated_at,
actor_id=existing_memory.payload.get("actor_id"),
role=existing_memory.payload.get("role"),
is_deleted=1,
)
# Entity-store cleanup: strip this memory's id from any entity records
# that linked to it. Non-fatal — the helper swallows errors.
self._remove_memory_from_entity_store(memory_id, session_filters)
return memory_id
def reset(self):
"""
Reset the memory store by:
Deletes the vector store collection
Resets the database
Recreates the vector store with a new client
"""
logger.warning("Resetting all memories")
self.db.reset()
self.db.close()
self.db = SQLiteManager(self.config.history_db_path)
if hasattr(self.vector_store, "reset"):
self.vector_store = VectorStoreFactory.reset(self.vector_store)
else:
logger.warning("Vector store does not support reset. Skipping.")
self.vector_store.delete_col()
self.vector_store = VectorStoreFactory.create(Sources: mem0/memory/main.py:2114-2162
Warning
When executing reset(), if the vector store implementation lacks a native reset() method, the engine falls back to calling delete_col() followed by a factory recreation step mem0/memory/main.py.
Sources: mem0/memory/main.py:2157-2162
Temporal Filtering and Usage Notices
Telemetry Feature Flags and Usage Notice Constants
The open-source notices framework (mem0/memory/notices.py) manages telemetry-driven feature disclosures, temporal usage tracking, decay detection, and scale evaluation thresholds mem0/memory/notices.py. Notice evaluation uses remote configurations fetched from GitHub or bundled fallbacks governed by a time-to-live (_CONFIG_TTL_SECONDS) of 3600 seconds mem0/memory/notices.py.
| Notice ID / Constant | Value / Threshold | Meaning / Purpose |
|---|---|---|
NOTICE_ID | "first_run" | Identifier for first-run telemetry notices mem0/memory/notices.py |
TEMPORAL_USAGE_NOTICE_ID | "temporal_usage" | Notice identifier for temporal usage tracking mem0/memory/notices.py |
DECAY_USAGE_NOTICE_ID | "decay_usage" | Notice identifier for decay and deletion usage mem0/memory/notices.py |
SCALE_THRESHOLD_NOTICE_ID | "scale_threshold" | Notice identifier for vector scale evaluations mem0/memory/notices.py |
PERFORMANCE_SLOW_QUERY_NOTICE_ID | "performance_slow_query" | Notice identifier for slow query tracking mem0/memory/notices.py |
TEMPORAL_USAGE_CAP | 10 | Maximum temporal usage notices per window mem0/memory/notices.py |
DECAY_USAGE_CAP | 10 | Maximum decay usage notices per window mem0/memory/notices.py |
DECAY_USAGE_DELETE_THRESHOLD | 5 | Successful deletes required to trigger decay notice mem0/memory/notices.py |
SCALE_MEMORY_COUNT_THRESHOLD | 2000 | Vector count threshold triggering scale notices mem0/memory/notices.py |
SCALE_TOP_K_THRESHOLD | 50 | top_k query parameter threshold for scale notices mem0/memory/notices.py |
PERFORMANCE_SLOW_QUERY_THRESHOLD_SECONDS | 2.0 | Query execution time limit for slow query warnings mem0/memory/notices.py |
NOTICE_ID = "first_run"
TEMPORAL_FEATURE_NOTICE_ID = "temporal_stub"
TEMPORAL_USAGE_NOTICE_ID = "temporal_usage"
DECAY_FEATURE_NOTICE_ID = "decay_stub"
DECAY_USAGE_NOTICE_ID = "decay_usage"
SCALE_THRESHOLD_NOTICE_ID = "scale_threshold"
PERFORMANCE_SLOW_QUERY_NOTICE_ID = "performance_slow_query"
NOTICE_EVENT = "mem0.notice_displayed"
DISPLAYED_VARIANT = "displayed"
HOLDOUT_VARIANT = "holdout"
STATE_SECTION = "notice_state"
STATE_KEY = "first_run"
TEMPORAL_USAGE_STATE_KEY = "temporal_usage"
TEMPORAL_USAGE_CAP = 10
TEMPORAL_USAGE_WINDOW = timedelta(days=7)
DECAY_USAGE_STATE_KEY = "decay_usage"
DECAY_USAGE_CAP = 10
DECAY_USAGE_WINDOW = timedelta(days=7)
DECAY_USAGE_DELETE_THRESHOLD = 5
SCALE_THRESHOLD_STATE_KEY = "scale_threshold"
SCALE_THRESHOLD_CAP = 10
SCALE_THRESHOLD_WINDOW = timedelta(days=7)
SCALE_MEMORY_COUNT_THRESHOLD = 2000
SCALE_MEMORY_COUNT_CHECK_INTERVAL = 100
SCALE_TOP_K_THRESHOLD = 50
PERFORMANCE_SLOW_QUERY_STATE_KEY = "performance_slow_query"
PERFORMANCE_SLOW_QUERY_CAP = 10
PERFORMANCE_SLOW_QUERY_WINDOW = timedelta(days=7)
PERFORMANCE_SLOW_QUERY_THRESHOLD_SECONDS = 2.0Sources: mem0/memory/notices.py:99-127
Warning
The OSS Python Memory SDK explicitly does not support advanced query parameters such as timestamp, reference_date, or decay, raising structured error messages when callers attempt to invoke them mem0/memory/notices.py.
Sources: mem0/memory/notices.py:130-134
Temporal Extraction and Expiry Regex Patterns
Temporal filtering engines employ strict regular expression boundaries to detect ISO dates and relative conversational time anchors such as yesterday, last week, or specific date ranges mem0/memory/notices.py.
_ISO_DATE_RE = re.compile(
r"\b\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)?\b"
)
_RELATIVE_TIME_RE = re.compile(
r"\b("
r"today|yesterday|tomorrow|"
r"last\s+(?:night|week|month|year)|"
r"this\s+(?:week|month|year)|"
r"next\s+(?:week|month|year)|"
r"(?:past|last)\s+\d+\s+(?:day|days|week|weeks|month|months|year|years)|"
r"(?:since|before|after|until)\s+(?:today|yesterday|tomorrow|\d{4}-\d{2}-\d{2}|last\s+(?:week|month|year))"
r")\b",
re.IGNORECASE,
)
_RANGE_OPERATORS = {"gt", "gte", "lt", "lte"}Sources: mem0/memory/notices.py:136-150
Note
Usage notice tracking enforces concurrency protection via _state_lock and process-level flags to ensure telemetry events do not exceed capacity caps within their defined rolling time windows mem0/memory/notices.py.
Sources: mem0/memory/notices.py:152-163
Related
On This Page
OverviewPublic Memory Engine InterfaceEngine Method SignaturesConfiguration and Item SchemasLLM Fact Extraction WorkflowFact Distillation Prompts and SchemasProcedural Memory GenerationVector Ingestion and Entity LinkingMetadata Preparation and Embedding UpsertAudit Recording and Entity SynchronizationMemory Updates and Deletion LifecycleMemory Modification and Entity ResynchronizationSingle Deletion and Scope ResetsTemporal Filtering and Usage NoticesTelemetry Feature Flags and Usage Notice ConstantsTemporal Extraction and Expiry Regex PatternsRelated