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

# 长期记忆

> 通过基于中间件的长期记忆后端，让知识在多个会话间持久保留

## 概述

**长期记忆**让 agent 在多次会话之间保留并检索可持久化的信息，例如用户偏好、历史决策，以及需要在后续对话中反复使用的知识。

在 AgentScope 中，记忆提取和存储服务（如 mem0、ReMe）作为长期记忆后端，以[中间件](/versions/2.0.3/zh/building-blocks/middleware)的形式集成到 agent 中。每个记忆中间件是一个 `MiddlewareBase` 子类，可以按需挂接到 agent 生命周期的 hook 位置。例如：

* `on_reply` —— 在 reply 前检索记忆，在 reply 后把新的对话写回。
* `on_system_prompt` —— 向模型声明记忆工具。
* `list_tools` —— 提供供 agent 调用的 memory 相关工具，例如 `search_memory` / `add_memory`。

具体挂接哪些位置由各记忆后端自行决定。

这样无需改动 agent 与 model 代码：只要把记忆中间件传入 `Agent(middlewares=[...])` 即可启用长期记忆，并且能与任意其它中间件自由组合。

AgentScope 目前提供以下长期记忆后端，更多后端（如 ReMe）正在规划中：

| 后端                                     | 类                | 状态 |
| -------------------------------------- | ---------------- | -- |
| [mem0](https://github.com/mem0ai/mem0) | `Mem0Middleware` | 可用 |

## Mem0

`Mem0Middleware` 是由 [mem0](https://github.com/mem0ai/mem0) 驱动的、开箱即用的长期记忆后端，同时支持 `mem0.AsyncMemory`（开源版）与 `mem0.AsyncMemoryClient`（托管 Platform 版）。在使用 `mem0.AsyncMemory`（开源版）时，可以让 mem0 自身的记忆抽取与 embedding 都走你现有的 AgentScope 模型 —— 因此 mem0 无需单独的 provider key。

### 安装

`Mem0Middleware` 的依赖位于 AgentScope 的可选依赖中：

```bash theme={null}
pip install "agentscope[mem0]"
```

### 快速开始

最快捷的方式是直接传入你的 AgentScope chat 与 embedding 模型；中间件会在内部构建一个开源版 mem0 存储，并把记忆抽取与 embedding 都接到这两个模型上。

```python theme={null}
import asyncio

from agentscope.agent import Agent
from agentscope.middleware import Mem0Middleware
from agentscope.tool import Toolkit


async def main():
    mw = Mem0Middleware(
        user_id="alice",
        chat_model=my_chat_model,
        embedding_model=my_embedding_model,
        mode="both",
    )

    agent = Agent(
        name="assistant",
        system_prompt="You are a helpful assistant.",
        model=my_chat_model,
        toolkit=Toolkit(tools=await mw.list_tools()),
        middlewares=[mw],
    )

    # 本次会话写入的记忆，会在后续相同 ``user_id`` 的会话中重新出现。
    await agent(...)


asyncio.run(main())
```

<Note>
  `Mem0Middleware` 通过 `list_tools()` 提供 `search_memory` / `add_memory` 工具，而 agent **不会**自动调用它。要让这些工具对 agent 可用，需要你自己收集并传入 toolkit —— `Toolkit(tools=await mw.list_tools())`。在 `static_control` 模式下 `list_tools()` 返回空列表。
</Note>

### 控制模式

`mode` 参数决定 agent 与 mem0 的交互方式，默认为 `"both"`，与 AgentScope 1.x 的 `ReActAgent.long_term_memory_mode` 一致。

| 模式               | 行为                                                                                                     |
| ---------------- | ------------------------------------------------------------------------------------------------------ |
| `static_control` | 中间件在每次 reply 前检索 mem0，把检索到的记忆以 `AssistantMsg(name="memory")` 注入上下文，并在 reply 后把新的对话写回。agent 对 mem0 无感知。 |
| `agent_control`  | 中间件暴露 `search_memory` / `add_memory` 工具，并在 system prompt 中追加一段简短的使用提示。由 agent 自行决定何时读写记忆；没有自动检索或写回。    |
| `both`           | 两种模式同时生效 —— 既自动检索，又提供按需调用的工具。                                                                          |

### 构造方式

`Mem0Middleware` 支持三种接入 mem0 后端的方式：

<Tabs>
  <Tab title="AgentScope 模型">
    传入 AgentScope 模型，让中间件在内部构建开源版 `AsyncMemory`（mem0 默认的 Qdrant 存储）。embedding 模型的 `dimensions` 必须与向量存储匹配（默认 Qdrant 期望 `1536`）。

    ```python theme={null}
    Mem0Middleware(
        user_id="alice",
        chat_model=my_chat_model,
        embedding_model=my_embedding_model,
    )
    ```
  </Tab>

  <Tab title="模型 + 自定义 config">
    以你自己的 `mem0.configs.base.MemoryConfig` 为基础，自定义向量存储、history DB 或 reranker，同时仍让 LLM 与 embedder 走 AgentScope。只有 `.llm` / `.embedder` 槽位会被覆盖，其余字段全部保留。

    ```python theme={null}
    Mem0Middleware(
        user_id="alice",
        chat_model=my_chat_model,
        embedding_model=my_embedding_model,
        mem0_config=my_mem0_config,
    )
    ```
  </Tab>

  <Tab title="预构建 client">
    当你需要完全掌控时（例如使用托管 Platform，或在多个 agent 间共享同一存储），可传入预构建的 mem0 client。一旦提供 `client`，它具有绝对优先级，`chat_model` / `embedding_model` / `mem0_config` 都会被忽略。

    ```python theme={null}
    from mem0 import AsyncMemoryClient

    Mem0Middleware(
        user_id="alice",
        client=AsyncMemoryClient(api_key="m0-..."),
    )
    ```
  </Tab>
</Tabs>

<Warning>
  `Mem0Middleware` 要求使用**异步** mem0 client（`mem0.AsyncMemory` 或 `mem0.AsyncMemoryClient`）。同步的 `Memory` / `MemoryClient` 不受支持。
</Warning>

### 关键参数

| 参数                      | 类型                                              | 默认值      | 说明                                                                         |
| ----------------------- | ----------------------------------------------- | -------- | -------------------------------------------------------------------------- |
| `user_id`               | `str`                                           | *（必填）*   | 用户记忆的 mem0 命名空间。                                                           |
| `mode`                  | `"static_control" \| "agent_control" \| "both"` | `"both"` | agent 与 mem0 的交互方式（见上文）。                                                   |
| `agent_id`              | `str \| None`                                   | `None`   | 可选的更细粒度命名空间。                                                               |
| `top_k`                 | `int`                                           | `5`      | 每次 static-control 检索返回的最大记忆数；同时作为 `search_memory` 工具的默认值。                  |
| `threshold`             | `float \| None`                                 | `None`   | 最小相似度分数；`None` 表示交由 mem0 决定。                                               |
| `scope_search_by_agent` | `bool`                                          | `True`   | 为 `True` 时检索同时按 `user_id` 与 `agent_id` 过滤；为 `False` 时同一用户的记忆在多个 agent 间共享。 |
| `await_write`           | `bool`                                          | `True`   | 为 `True` 时回合结束后的写入会内联等待；为 `False` 时为异步触发（更快，但异常只在日志中体现）。                   |

### 供 agent 调用的工具

在 `agent_control` 与 `both` 模式下，中间件提供两个模型可按需调用的工具：

* **`search_memory(keywords, limit=5)`** —— 用一组简短、精准的关键词检索记忆。每个关键词作为独立查询发起，结果合并并去重。
* **`add_memory(thinking, content)`** —— 记录持久信息。只有 `content`（一组独立完整的句子）会被写入 mem0；`thinking` 留在对话记录中以便审计。

两个工具都会自动放行（auto-allow），并直接从中间件实例读取 `user_id` / `agent_id`，因此除了把它们加入 toolkit 之外无需额外接线。
