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

# Long-Term Memory

> Persist knowledge across sessions with middleware-based long-term memory backends

## Overview

**Long-term memory** lets an agent store and retrieve durable information across sessions — user preferences, past decisions, and knowledge that should persist beyond a single conversation.

In AgentScope, memory extraction and storage services (such as mem0 and ReMe) serve as long-term memory backends, integrated into agents as [middleware](/versions/2.0.3/en/building-blocks/middleware). Each memory middleware is a `MiddlewareBase` subclass that can hook into any position of the agent lifecycle as needed. For example:

* `on_reply` — search the store before a reply and write the new exchange back afterward.
* `on_system_prompt` — advertise memory tools to the model.
* `list_tools` — contribute agent-callable memory tools, such as `search_memory` / `add_memory`.

Which positions a backend hooks is up to that backend.

This keeps the agent and model code untouched: you opt into long-term memory simply by passing a memory middleware into `Agent(middlewares=[...])`, and you can compose it with any other middleware.

AgentScope currently ships the following long-term memory backend, with more (e.g. ReMe) planned:

| Backend                                | Class            | Status    |
| -------------------------------------- | ---------------- | --------- |
| [mem0](https://github.com/mem0ai/mem0) | `Mem0Middleware` | Available |

## Mem0

`Mem0Middleware` is a drop-in long-term memory backend powered by [mem0](https://github.com/mem0ai/mem0). It works with both `mem0.AsyncMemory` (open-source) and `mem0.AsyncMemoryClient` (hosted Platform). With `mem0.AsyncMemory` (open-source), it can route mem0's own memory extraction and embedding through your existing AgentScope models — so mem0 needs no separate provider key.

### Installation

`Mem0Middleware`'s dependencies are available as an optional extra in AgentScope:

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

### Quick start

The fastest path is to pass your AgentScope chat and embedding models; the middleware builds an open-source mem0 store internally and wires both extraction and embedding through them.

```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],
    )

    # Memories written in this session resurface in later sessions
    # for the same ``user_id``.
    await agent(...)


asyncio.run(main())
```

<Note>
  `Mem0Middleware` contributes its `search_memory` / `add_memory` tools through `list_tools()`, which the agent does **not** call automatically. To make the tools available to the agent, collect them yourself and pass them into the toolkit — `Toolkit(tools=await mw.list_tools())`. In `static_control` mode `list_tools()` returns an empty list.
</Note>

### Control modes

The `mode` parameter decides how the agent interacts with mem0. It defaults to `"both"`, matching AgentScope 1.x's `ReActAgent.long_term_memory_mode`.

| Mode             | Behavior                                                                                                                                                                                                                 |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `static_control` | The middleware searches mem0 before each reply, injects the retrieved memories into the context as an `AssistantMsg(name="memory")`, and writes the new exchange back after the reply. The agent is unaware of mem0.     |
| `agent_control`  | The middleware exposes `search_memory` / `add_memory` tools and appends a short usage nudge to the system prompt. The agent decides when to read from or write to memory; there is no automatic retrieval or write-back. |
| `both`           | Both patterns are active at once — automatic retrieval **and** on-demand tools.                                                                                                                                          |

### Construction paths

`Mem0Middleware` supports three ways to wire up the mem0 backend:

<Tabs>
  <Tab title="AgentScope models">
    Pass AgentScope models and let the middleware build an open-source `AsyncMemory` internally (mem0's default Qdrant store). The embedding model's `dimensions` must match the vector store (the default Qdrant expects `1536`).

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

  <Tab title="Models + custom config">
    Start from your own `mem0.configs.base.MemoryConfig` to customize the vector store, history DB, or reranker, while still routing the LLM and embedder through AgentScope. Only the `.llm` / `.embedder` slots are overridden; every other field is preserved.

    ```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="Pre-built client">
    Pass a pre-built mem0 client when you want full control (e.g. the hosted Platform, or sharing one store across agents). When `client` is given it takes absolute precedence, and `chat_model` / `embedding_model` / `mem0_config` are ignored.

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

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

<Warning>
  `Mem0Middleware` requires an **async** mem0 client (`mem0.AsyncMemory` or `mem0.AsyncMemoryClient`). The synchronous `Memory` / `MemoryClient` are not supported.
</Warning>

### Key parameters

| Parameter               | Type                                            | Default      | Description                                                                                                                           |
| ----------------------- | ----------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `user_id`               | `str`                                           | *(required)* | mem0 namespace for the user's memories.                                                                                               |
| `mode`                  | `"static_control" \| "agent_control" \| "both"` | `"both"`     | How the agent interacts with mem0 (see above).                                                                                        |
| `agent_id`              | `str \| None`                                   | `None`       | Optional finer-grained namespace.                                                                                                     |
| `top_k`                 | `int`                                           | `5`          | Max memories retrieved per static-control search; also the default for the `search_memory` tool.                                      |
| `threshold`             | `float \| None`                                 | `None`       | Minimum similarity score; `None` lets mem0 decide.                                                                                    |
| `scope_search_by_agent` | `bool`                                          | `True`       | When `True`, searches filter by both `user_id` and `agent_id`; when `False`, a user's memories are shared across agents.              |
| `await_write`           | `bool`                                          | `True`       | When `True`, the post-turn write is awaited inline; when `False`, it's fire-and-forget (faster, but exceptions only surface in logs). |

### Agent-callable tools

In `agent_control` and `both` modes, the middleware contributes two tools the model can invoke on demand:

* **`search_memory(keywords, limit=5)`** — retrieves memories using a list of short, targeted keywords. Each keyword is issued as an independent query; results are merged and deduplicated.
* **`add_memory(thinking, content)`** — records durable facts. Only `content` (a list of standalone sentences) is persisted to mem0; `thinking` stays in the transcript for auditability.

Both tools auto-allow themselves and read `user_id` / `agent_id` directly from the middleware instance, so they require no extra wiring beyond adding them to the toolkit.
