Skip to main content

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. 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:
BackendClassStatus
mem0Mem0MiddlewareAvailable

Mem0

Mem0Middleware is a drop-in long-term memory backend powered by 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:
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.
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())
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.

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.
ModeBehavior
static_controlThe 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_controlThe 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.
bothBoth patterns are active at once — automatic retrieval and on-demand tools.

Construction paths

Mem0Middleware supports three ways to wire up the mem0 backend:
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).
Mem0Middleware(
    user_id="alice",
    chat_model=my_chat_model,
    embedding_model=my_embedding_model,
)
Mem0Middleware requires an async mem0 client (mem0.AsyncMemory or mem0.AsyncMemoryClient). The synchronous Memory / MemoryClient are not supported.

Key parameters

ParameterTypeDefaultDescription
user_idstr(required)mem0 namespace for the user’s memories.
mode"static_control" | "agent_control" | "both""both"How the agent interacts with mem0 (see above).
agent_idstr | NoneNoneOptional finer-grained namespace.
top_kint5Max memories retrieved per static-control search; also the default for the search_memory tool.
thresholdfloat | NoneNoneMinimum similarity score; None lets mem0 decide.
scope_search_by_agentboolTrueWhen True, searches filter by both user_id and agent_id; when False, a user’s memories are shared across agents.
await_writeboolTrueWhen 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.