Memory 让你的 agent 可以跨 conversations 学习和改进。Deep Agents 通过 filesystem-backed memory 将 memory 作为 first-class capability:agent 以 files 的形式 read 和 write memory,你使用 backends 控制这些 files 存储在哪里。
本页介绍 long-term memory:跨 conversations 持久化的 memory。Short-term memory(单个 session 内的 conversation history 和 scratch files)请参阅 context engineering guide。Short-term memory 会作为 agent state 的一部分自动管理。Short-term memory is scoped to a single thread via checkpoints; long-term memory persists across threads via the store

How memory works

  1. 将 agent 指向 memory files。 创建 agent 时将 file paths 传给 memory=。你也可以通过 skills= 传入 skills,用于 procedural memory(告诉 agent 如何 执行 task 的 reusable instructions)。backend 控制 files 存储在哪里,以及谁可以访问。
  2. Agent 读取 memory。 Agent 可以在 startup 时将 memory files 加载到 system prompt 中,也可以在 conversation 期间按需读取它们。例如,skills 使用 on-demand loading:agent 在 startup 时只读取 skill descriptions,然后只在 skill 匹配 task 时读取 full skill file。这样在 capability 被需要前,context 会保持精简。
  3. Agent 更新 memory(可选)。 当 agent 学到新 information 时,它可以使用内置 edit_file tool 更新 memory files。Updates 可以在 conversation 期间发生(默认),也可以通过 background consolidation 在 conversations 之间后台发生。Changes 会被 persisted,并在下一次 conversation 中可用。并非所有 memory 都是 writable:developer-defined skillsorganization policies 通常是 read-only。详情请参阅 read-only vs writable memory
最常见的两种 patterns 是 agent-scoped memory(所有 users 共享)和 user-scoped memory(按 user 隔离)。

Scoped memory

Agent memory 可以 scoped,使同一组 memory files 对所有使用 agent 的人可访问,也可以让每个 user 拥有各自的 memory files。

Agent-scoped memory

为 agent 提供随时间演化的 persistent identity。Agent-scoped memory 在所有 users 之间共享,因此 agent 会通过每次 conversation 积累自己的 persona、knowledge 和 learned preferences。随着它与 users 交互,它会发展 expertise、refine approach,并记住哪些做法有效。如果它拥有 write access,也可以学习并更新 skills 关键是 backend namespace:将其设置为 (assistant_id,) 意味着该 agent 的每个 conversation 都会 read 和 write 同一个 memory file。
访问 rt.server_info 需要 deepagents>=0.5.0。在更旧版本中,请改为从 get_config()["metadata"]["assistant_id"] 读取 assistant ID。
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=["/memories/AGENTS.md"],
    skills=["/skills/"],
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(
                namespace=lambda rt: (
                    rt.server_info.assistant_id,
                ),
            ),
            "/skills/": StoreBackend(
                namespace=lambda rt: (
                    rt.server_info.assistant_id,
                ),
            ),
        },
    ),
)
用 initial memories 填充 store,然后跨两个 threads invoke agent,观察它如何记住并更新学到的内容。
from langchain_core.utils.uuid import uuid7

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from deepagents.backends.utils import create_file_data
from langgraph.store.memory import InMemoryStore

store = InMemoryStore()  # Use platform store when deploying to LangSmith

# Seed the memory file
store.put(
    ("my-agent",),
    "/memories/AGENTS.md",
    create_file_data("""## Response style
- Keep responses concise
- Use code examples where possible
"""),
)

# Seed a skill
store.put(
    ("my-agent",),
    "/skills/langgraph-docs/SKILL.md",
    create_file_data("""---
name: langgraph-docs
description: Fetch relevant LangGraph documentation to provide accurate guidance.
---

# langgraph-docs

Use the fetch_url tool to read https://docs.langchain.com/llms.txt, then fetch relevant pages.
"""),
)

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=["/memories/AGENTS.md"],
    skills=["/skills/"],
    backend=lambda rt: CompositeBackend(
        default=StateBackend(rt),
        routes={
            "/memories/": StoreBackend(
                rt, namespace=lambda rt: ("my-agent",)
            ),
            "/skills/": StoreBackend(
                rt, namespace=lambda rt: ("my-agent",)
            ),
        },
    ),
    store=store,
)

# Thread 1: the agent learns a new preference and saves it to memory
config1 = {"configurable": {"thread_id": str(uuid7())}}
agent.invoke(
    {"messages": [{"role": "user", "content": "I prefer detailed explanations. Remember that."}]},
    config=config1,
)

# Thread 2: the agent reads memory and applies the preference
config2 = {"configurable": {"thread_id": str(uuid7())}}
agent.invoke(
    {"messages": [{"role": "user", "content": "Explain how transformers work."}]},
    config=config2,
)

User-scoped memory

为每个 user 提供自己的 memory file。Agent 会按 user 记住 preferences、context 和 history,同时 core agent instructions 保持固定。如果 skills 存储在 user-scoped backend 中,users 也可以拥有 per-user skills Namespace 使用 (user_id,),因此每个 user 都获得 isolated copy 的 memory file。User A 的 preferences 永远不会泄漏到 User B 的 conversations。
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=["/memories/preferences.md"],
    skills=["/skills/"],
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
            "/skills/": StoreBackend(
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
        },
    ),
)
Seed per-user memories,并以两个不同 users 身份 invoke agent。每个 user 只会看到自己的 preferences。
from langchain_core.utils.uuid import uuid7

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from deepagents.backends.utils import create_file_data
from langgraph.store.memory import InMemoryStore


store = InMemoryStore()  # Use platform store when deploying to LangSmith

# Seed preferences for two users
store.put(
    ("user-alice",),
    "/memories/preferences.md",
    create_file_data("""## Preferences
- Likes concise bullet points
- Prefers Python examples
"""),
)
store.put(
    ("user-bob",),
    "/memories/preferences.md",
    create_file_data("""## Preferences
- Likes detailed explanations
- Prefers TypeScript examples
"""),
)

# Seed a skill for Alice
store.put(
    ("user-alice",),
    "/skills/langgraph-docs/SKILL.md",
    create_file_data("""---
name: langgraph-docs
description: Fetch relevant LangGraph documentation to provide accurate guidance.
---

# langgraph-docs

Use the fetch_url tool to read https://docs.langchain.com/llms.txt, then fetch relevant pages.
"""),
)

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=["/memories/preferences.md"],
    skills=["/skills/"],
    backend=lambda rt: CompositeBackend(
        default=StateBackend(rt),
        routes={
            "/memories/": StoreBackend(
                rt,
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
            "/skills/": StoreBackend(
                rt,
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
        },
    ),
    store=store,
)

# When deployed, each authenticated request resolves
# `rt.server_info.user.identity` to the calling user, so Alice and Bob
# automatically see only their own preferences.
agent.invoke(
    {"messages": [{"role": "user", "content": "How do I read a CSV file?"}]},
    config={"configurable": {"thread_id": str(uuid7())}},
)

Advanced usage

在 memory paths 和 scope 的 basic configuration options 之上,你还可以为 memory 配置更高级的 parameters:
DimensionQuestion it answersOptions
Duration它持续多久?Short-term(single conversation)或 long-term(across conversations)
Information type它是什么类型的信息?Episodic(past experiences)、procedural(instructions 和 skills)或 semantic(facts)
Scope谁可以 see 和 modify 它?Useragentorganization
Update strategyMemories 何时写入?Conversation 期间(默认)或 between conversations
RetrievalMemories 如何读取?加载到 prompt(默认)或 on demand(例如 skills
Agent permissionsAgent 是否可以 write memory?Read-write(默认)或 read-only(用于 shared policies)

Episodic memory

Episodic memory 存储 past experiences 的 records:发生了什么、顺序如何,以及结果是什么。不同于 semantic memory(存储在 AGENTS.md 等 files 中的 facts 和 preferences),episodic memory 会保留完整 conversational context,因此 agent 可以回忆问题是 如何 解决的,而不仅是从中学到了 什么 Deep Agents 已经使用 checkpointers,这是支持 episodic memory 的机制:每个 conversation 都会作为 checkpointed thread 持久化。 若要让 past conversations 可搜索,请将 thread search 包装成 tool。user_id 从 runtime context 拉取,而不是作为 parameter 传入:
from langgraph_sdk import get_client
from langchain.tools import tool, ToolRuntime

client = get_client(url="<DEPLOYMENT_URL>")


@tool
async def search_past_conversations(query: str, runtime: ToolRuntime) -> str:
    """Search past conversations for relevant context."""
    user_id = runtime.server_info.user.identity  
    threads = await client.threads.search(
        metadata={"user_id": user_id},
        limit=5,
    )
    results = []
    for thread in threads:
        history = await client.threads.get_history(thread_id=thread["thread_id"])
        results.append(history)
    return str(results)
你可以通过调整 metadata filter,按 user 或 organization scope thread search:
# Search conversations for a specific user
threads = await client.threads.search(
    metadata={"user_id": user_id},
    limit=5,
)

# Search conversations across an organization
threads = await client.threads.search(
    metadata={"org_id": org_id},
    limit=5,
)
这对执行 complex multi-step tasks 的 agents 很有用。例如,coding agent 可以回看 past debugging session,并直接跳到可能的 root cause。

Organization-level memory

Organization-level memory 与 user-scoped memory 遵循相同 pattern,但使用 organization-wide namespace,而不是 per-user namespace。将其用于应适用于 organization 内所有 users 和 agents 的 policies 或 knowledge。 Organization memory 通常是 read-only,以防通过 shared state 发生 prompt injection。详情请参阅 read-only vs writable memory
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=[
        "/memories/preferences.md",
        "/policies/compliance.md",
    ],
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
            "/policies/": StoreBackend(
                namespace=lambda rt: (rt.context.org_id,),
            ),
        },
    ),
)
从 application code 填充 organization memory:
from langgraph_sdk import get_client
from deepagents.backends.utils import create_file_data

client = get_client(url="<DEPLOYMENT_URL>")

await client.store.put_item(
    (org_id,),
    "/compliance.md",
    create_file_data("""## Compliance policies
- Never disclose internal pricing
- Always include disclaimers on financial advice
"""),
)
使用 permissions enforce org-level memory 为 read-only,或使用 policy hooks 实现 custom validation logic。

Background consolidation

默认情况下,agent 会在 conversation 期间写入 memories(hot path)。另一种方式是将 memories 作为 background task 在 between conversations 处理,有时称为 sleep time compute。一个单独的 deep agent 会 review recent conversations、extract key facts,并将其与 existing memories 合并。
ApproachProsCons
Hot path(conversation 期间)Memories 立即可用,对 user 透明增加 latency,agent 必须 multitask
Background(between conversations)无 user-facing latency,可以跨多个 conversations synthesizeMemories 要到下一次 conversation 才可用,需要 second agent
对于大多数 applications,hot path 已足够。当你需要减少 latency 或提升跨许多 conversations 的 memory quality 时,再添加 background consolidation。 推荐 pattern 是在 main agent 旁部署一个 consolidation agent,即一个读取 recent conversation history、extract key facts,并 merge 到 memory store 的 deep agent,然后按 cron schedule 触发它。请选择反映 users 实际交互频率的 cadence:日常稳定使用的 chat product 可以每几个小时 consolidate 一次,而每周只用几次的 tool 只需要 nightly 或 weekly 运行。比 users conversation 频率高很多的 consolidation 只会在 no-op runs 上消耗 tokens。

Consolidation agent

Consolidation agent 读取 recent conversation history,并将 key facts 合并进 memory store。在 langgraph.json 中将其与 main agent 一起注册:
consolidation_agent.py
from datetime import datetime, timedelta, timezone

from deepagents import create_deep_agent
from langchain.tools import tool, ToolRuntime
from langgraph_sdk import get_client

sdk_client = get_client(url="<DEPLOYMENT_URL>")


@tool
async def search_recent_conversations(query: str, runtime: ToolRuntime) -> str:
    """Search this user's conversations updated in the last 6 hours."""
    user_id = runtime.server_info.user.identity  

    since = datetime.now(timezone.utc) - timedelta(hours=6)
    threads = await sdk_client.threads.search(
        metadata={"user_id": user_id},
        updated_after=since.isoformat(),
        limit=20,
    )
    conversations = []
    for thread in threads:
        history = await sdk_client.threads.get_history(
            thread_id=thread["thread_id"]
        )
        conversations.append(history["values"]["messages"])
    return str(conversations)


agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    system_prompt="""Review recent conversations and update the user's memory file.
Merge new facts, remove outdated information, and keep it concise.""",
    tools=[search_recent_conversations],
)
langgraph.json
{
  "dependencies": ["."],
  "graphs": {
    "agent": "./agent.py:agent",
    "consolidation_agent": "./consolidation_agent.py:agent"
  },
  "env": ".env"
}

Cron

cron job 会按固定 schedule 运行 consolidation agent。Agent 会搜索 recent conversations,并将其 synthesize 到 memory 中。请将 schedule 与你的 usage patterns 匹配,让 consolidation 大致跟随真实 activity。 使用 cron job schedule consolidation agent:
from langgraph_sdk import get_client

client = get_client(url="<DEPLOYMENT_URL>")

cron_job = await client.crons.create(
    assistant_id="consolidation_agent",
    schedule="0 */6 * * *",
    input={"messages": [{"role": "user", "content": "Consolidate recent memories."}]},
)
所有 cron schedules 都按 UTC 解释。管理和删除 cron jobs 的 details 请参阅 cron jobs
Cron interval 必须匹配 consolidation agent 内的 lookback window。上方 example 每 6 小时运行一次(0 */6 * * *),agent 的 search_recent_conversations tool 会回看 timedelta(hours=6),请保持二者同步。如果 cron 运行频率高于 lookback,你会重复处理相同 conversations;如果运行频率低于 lookback,你会丢掉 window 外的 memories。
有关使用 background processes 部署 agents 的更多信息,请参阅 going to production

Read-only vs writable memory

默认情况下,agent 可以 read 和 write memory files。对于 organization policies 或 compliance rules 等 shared state,你可能希望将 memory 设为 read-only,让 agent 可以 reference 它,但不能 modify 它。这可以防止 shared memory 中的 prompt injection,并确保只有你的 application code 控制 file 内容。
PermissionUse caseHow it works
Read-write(默认)User preferences、agent self-improvement、learned skillsAgent 通过 edit_file tool 更新 files
Read-onlyOrganization policies、compliance rules、shared knowledge bases、developer-defined skills通过 application code 或 Store API 填充。使用 permissions deny writes to specific paths,或使用 policy hooks 实现 custom validation logic。
Security considerations: 如果一个 user 可以写入另一个 user 会读取的 memory,malicious user 可能会将 instructions 注入 shared state。为缓解这一点:
  • 默认使用 user scope (user_id),除非你有具体理由共享
  • 对 shared policies 使用 read-only memory(通过 application code 填充,而不是 agent)
  • 在 agent 写入 shared memory 前添加 human-in-the-loop validation。使用 interrupt 要求 human approval 后再写入 sensitive paths。
若要 enforce read-only memory,请使用 permissions declaratively deny writes to specific paths。对于 custom validation logic(rate limiting、audit logging、content inspection),请使用 backend policy hooks

Concurrent writes

多个 threads 可以并行写入 memory,但并发写入 同一个 file 可能导致 last-write-wins conflicts。对于 user-scoped memory,这通常很少见,因为 users 通常一次只有一个 active conversation。对于 agent-scoped 或 organization-scoped memory,请考虑使用 background consolidation serialize writes,或将 memory 组织为按 topic 分离的 files,以减少 contention。 实践中,如果 write 因 conflict 失败,LLM 通常足够智能,可以 retry 或 graceful recover,因此单个 lost write 通常不是灾难性问题。

Multiple agents in the same deployment

若要在 shared deployment 中为每个 agent 提供自己的 memory,请将 assistant_id 添加到 namespace:
StoreBackend(
    namespace=lambda rt: (
        rt.server_info.assistant_id,
        rt.server_info.user.identity,
    ),
)
如果你只需要 per-agent isolation,而不需要 per-user scoping,请只使用 assistant_id
使用 LangSmith tracing audit agent 写入 memory 的内容。每次 file write 都会在 trace 中显示为 tool call。