Skip to content

Commit f62de70

Browse files
authored
Merge pull request #598 from kartik-mem0/feat/mem0-memory-store
feat: add Mem0 memory integration with config, implementation, docs, tests, and dependency
2 parents 117e4d8 + 2d9e889 commit f62de70

File tree

9 files changed

+837
-0
lines changed

9 files changed

+837
-0
lines changed

docs/user_guide/en/modules/memory.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,23 @@ memory:
3232
model: text-embedding-3-small
3333
```
3434
35+
### Mem0 Memory Config
36+
```yaml
37+
memory:
38+
- name: agent_memory
39+
type: mem0
40+
config:
41+
api_key: ${MEM0_API_KEY}
42+
agent_id: my-agent
43+
```
44+
3545
## 3. Built-in Store Comparison
3646
| Type | Path | Highlights | Best for |
3747
| --- | --- | --- | --- |
3848
| `simple` | `node/agent/memory/simple_memory.py` | Optional disk persistence (JSON) after runs; FAISS + semantic rerank; read/write capable. | Small conversation history, prototypes. |
3949
| `file` | `node/agent/memory/file_memory.py` | Chunks files/dirs into a vector index, read-only, auto rebuilds when files change. | Knowledge bases, doc QA. |
4050
| `blackboard` | `node/agent/memory/blackboard_memory.py` | Lightweight append-only log trimmed by time/count; no vector search. | Broadcast boards, pipeline debugging. |
51+
| `mem0` | `node/agent/memory/mem0_memory.py` | Cloud-managed by Mem0; semantic search + graph relationships; no local embeddings or persistence needed. Requires `mem0ai` package. | Production memory, cross-session persistence, multi-agent memory sharing. |
4152

4253
All stores register through `register_memory_store()` so summaries show up in UI via `MemoryStoreConfig.field_specs()`.
4354

@@ -98,6 +109,14 @@ This schema lets multimodal outputs flow into Memory/Thinking modules without ex
98109
- **Retrieval** – Returns the latest `top_k` entries ordered by time.
99110
- **Write** – `update()` appends the latest snapshot (input/output blocks, attachments, previews). No embeddings are generated, so retrieval is purely recency-based.
100111

112+
### 5.4 Mem0Memory
113+
- **Config** – Requires `api_key` (from [app.mem0.ai](https://app.mem0.ai)). Optional `user_id`, `agent_id`, `org_id`, `project_id` for scoping.
114+
- **Entity scoping**: `user_id` and `agent_id` are independent dimensions — both can be included simultaneously in `add()` and `search()` calls. When both are configured, retrieval uses an OR filter (`{"OR": [{"user_id": ...}, {"agent_id": ...}]}`) to search across both scopes. Writes include both IDs when available.
115+
- **Retrieval** – Uses Mem0's server-side semantic search. Supports `top_k` and `similarity_threshold` via `MemoryAttachmentConfig`.
116+
- **Write** – `update()` sends only user input to Mem0 via the SDK (as `role: "user"` messages). Assistant output is excluded to prevent noise memories from the LLM's responses being extracted as facts.
117+
- **Persistence** – Fully cloud-managed. `load()` and `save()` are no-ops. Memories persist across runs and sessions automatically.
118+
- **Dependencies** – Requires `mem0ai` package (`pip install mem0ai`).
119+
101120
## 6. EmbeddingConfig Notes
102121
- Fields: `provider`, `model`, `api_key`, `base_url`, `params`.
103122
- `provider=openai` uses the official client; override `base_url` for compatibility layers.

docs/user_guide/zh/modules/memory.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,23 @@ memory:
3232
model: text-embedding-3-small
3333
```
3434
35+
### Mem0 Memory 配置
36+
```yaml
37+
memory:
38+
- name: agent_memory
39+
type: mem0
40+
config:
41+
api_key: ${MEM0_API_KEY}
42+
agent_id: my-agent
43+
```
44+
3545
## 3. 内置 Memory Store 对比
3646
| 类型 | 路径 | 特点 | 适用场景 |
3747
| --- | --- | --- | --- |
3848
| `simple` | `node/agent/memory/simple_memory.py` | 运行结束后可选择落盘(JSON);使用向量搜索(FAISS)+语义重打分;支持读写 | 小规模对话记忆、快速原型 |
3949
| `file` | `node/agent/memory/file_memory.py` | 将指定文件/目录切片为向量索引,只读;自动检测文件变更并更新索引 | 知识库、文档问答 |
4050
| `blackboard` | `node/agent/memory/blackboard_memory.py` | 轻量附加日志,按时间/条数裁剪;不依赖向量检索 | 简易广播板、流水线调试 |
51+
| `mem0` | `node/agent/memory/mem0_memory.py` | 由 Mem0 云端托管;支持语义搜索 + 图关系;无需本地 embedding 或持久化。需安装 `mem0ai` 包。 | 生产级记忆、跨会话持久化、多 Agent 记忆共享 |
4152

4253
> 所有内置 store 都会在 `register_memory_store()` 中注册,摘要可通过 `MemoryStoreConfig.field_specs()` 在 UI 中展示。
4354

@@ -100,6 +111,14 @@ nodes:
100111
- **检索**:直接返回最近 `top_k` 条,按时间排序。
101112
- **写入**:`update()` 以 append 方式存储最新的输入/输出 snapshot(文本 + 块 + 附件信息),不生成向量,适合事件流或人工批注。
102113

114+
### 5.4 Mem0Memory
115+
- **配置**:必须提供 `api_key`(从 [app.mem0.ai](https://app.mem0.ai) 获取)。可选参数 `user_id`、`agent_id`、`org_id`、`project_id` 用于记忆范围控制。
116+
- **实体范围**:`user_id` 和 `agent_id` 是独立的维度,可在 `add()` 和 `search()` 调用中同时使用。若同时配置,检索时使用 OR 过滤器(`{"OR": [{"user_id": ...}, {"agent_id": ...}]}`)在一次 API 调用中搜索两个范围。写入时两个 ID 同时包含。
117+
- **检索**:使用 Mem0 服务端语义搜索。通过 `MemoryAttachmentConfig` 中的 `top_k` 和 `similarity_threshold` 控制。
118+
- **写入**:`update()` 仅将用户输入(`role: "user"` 消息)发送至 Mem0。不包含 Agent 输出,以避免 LLM 响应中的内容被提取为噪声记忆。
119+
- **持久化**:完全由云端托管。`load()` 和 `save()` 为空操作(no-op)。记忆在不同运行和会话间自动持久化。
120+
- **依赖**:需安装 `mem0ai` 包(`pip install mem0ai`)。
121+
103122
## 6. EmbeddingConfig 提示
104123
- 字段:`provider`, `model`, `api_key`, `base_url`, `params`。
105124
- `provider=openai` 时使用 `openai.OpenAI` 客户端,可配置 `base_url` 以兼容兼容层。

entity/configs/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
EmbeddingConfig,
1111
FileMemoryConfig,
1212
FileSourceConfig,
13+
Mem0MemoryConfig,
1314
MemoryAttachmentConfig,
1415
MemoryStoreConfig,
1516
SimpleMemoryConfig,
@@ -43,6 +44,7 @@
4344
"FunctionToolConfig",
4445
"GraphDefinition",
4546
"HumanConfig",
47+
"Mem0MemoryConfig",
4648
"MemoryAttachmentConfig",
4749
"MemoryStoreConfig",
4850
"McpLocalConfig",

entity/configs/node/memory.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,75 @@ def from_dict(cls, data: Mapping[str, Any], *, path: str) -> "BlackboardMemoryCo
279279
}
280280

281281

282+
@dataclass
283+
class Mem0MemoryConfig(BaseConfig):
284+
"""Configuration for Mem0 managed memory service."""
285+
286+
api_key: str = ""
287+
org_id: str | None = None
288+
project_id: str | None = None
289+
user_id: str | None = None
290+
agent_id: str | None = None
291+
292+
@classmethod
293+
def from_dict(cls, data: Mapping[str, Any], *, path: str) -> "Mem0MemoryConfig":
294+
mapping = require_mapping(data, path)
295+
api_key = require_str(mapping, "api_key", path)
296+
org_id = optional_str(mapping, "org_id", path)
297+
project_id = optional_str(mapping, "project_id", path)
298+
user_id = optional_str(mapping, "user_id", path)
299+
agent_id = optional_str(mapping, "agent_id", path)
300+
return cls(
301+
api_key=api_key,
302+
org_id=org_id,
303+
project_id=project_id,
304+
user_id=user_id,
305+
agent_id=agent_id,
306+
path=path,
307+
)
308+
309+
FIELD_SPECS = {
310+
"api_key": ConfigFieldSpec(
311+
name="api_key",
312+
display_name="Mem0 API Key",
313+
type_hint="str",
314+
required=True,
315+
description="Mem0 API key (get one from app.mem0.ai)",
316+
default="${MEM0_API_KEY}",
317+
),
318+
"org_id": ConfigFieldSpec(
319+
name="org_id",
320+
display_name="Organization ID",
321+
type_hint="str",
322+
required=False,
323+
description="Mem0 organization ID for scoping",
324+
advance=True,
325+
),
326+
"project_id": ConfigFieldSpec(
327+
name="project_id",
328+
display_name="Project ID",
329+
type_hint="str",
330+
required=False,
331+
description="Mem0 project ID for scoping",
332+
advance=True,
333+
),
334+
"user_id": ConfigFieldSpec(
335+
name="user_id",
336+
display_name="User ID",
337+
type_hint="str",
338+
required=False,
339+
description="User ID for user-scoped memories. Mutually exclusive with agent_id in API calls.",
340+
),
341+
"agent_id": ConfigFieldSpec(
342+
name="agent_id",
343+
display_name="Agent ID",
344+
type_hint="str",
345+
required=False,
346+
description="Agent ID for agent-scoped memories. Mutually exclusive with user_id in API calls.",
347+
),
348+
}
349+
350+
282351
@dataclass
283352
class MemoryStoreConfig(BaseConfig):
284353
name: str

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ dependencies = [
3939
"filelock>=3.20.1",
4040
"markdown>=3.10",
4141
"xhtml2pdf>=0.2.17",
42+
"mem0ai>=1.0.9",
4243
]
4344

4445
[build-system]

runtime/node/agent/memory/builtin_stores.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from entity.configs.node.memory import (
44
BlackboardMemoryConfig,
55
FileMemoryConfig,
6+
Mem0MemoryConfig,
67
SimpleMemoryConfig,
78
MemoryStoreConfig,
89
)
@@ -34,6 +35,19 @@
3435
)
3536

3637

38+
def _create_mem0_memory(store):
39+
from runtime.node.agent.memory.mem0_memory import Mem0Memory
40+
return Mem0Memory(store)
41+
42+
43+
register_memory_store(
44+
"mem0",
45+
config_cls=Mem0MemoryConfig,
46+
factory=_create_mem0_memory,
47+
summary="Mem0 managed memory with semantic search and graph relationships",
48+
)
49+
50+
3751
class MemoryFactory:
3852
@staticmethod
3953
def create_memory(store: MemoryStoreConfig) -> MemoryBase:

0 commit comments

Comments
 (0)