跳到主要内容

文档索引

在以下地址获取完整的文档索引:https://docs.langchain.org.cn/llms.txt

在进一步探索之前,请使用此文件发现所有可用页面。

内存功能可以让你的代理在不同对话间学习并提升能力。Deep Agents 通过基于文件系统的内存将内存提升为一等公民:代理以文件形式读取和写入内存,你可以使用后端 (backends) 来控制这些文件的存储位置。
本页面介绍长期内存:即跨对话持久存在的内存。关于短期内存(单个会话内的对话历史和草稿文件),请参阅上下文工程指南。短期内存作为代理状态的一部分进行自动管理。短期内存通过检查点限定在单个线程中;长期内存通过存储在线程间持久存在

记忆如何工作

  1. 将代理指向内存文件。 创建代理时,通过 memory= 传入文件路径。你也可以通过 skills= 传入技能 (skills) 以实现程序化内存(告诉代理如何执行任务的可重用指令)。后端 (backend) 控制文件存储位置及访问权限。
  2. 代理读取内存。 代理可以在启动时将内存文件加载到系统提示词中,或者在对话过程中按需读取。例如,技能使用按需加载:代理仅在启动时读取技能描述,只有在与任务匹配时才读取完整的技能文件。这样可以在需要某种能力之前保持上下文精简。
  3. 代理更新内存(可选)。 当代理学到新信息时,可以使用其内置的 edit_file 工具来更新内存文件。更新可以在对话过程中(默认)发生,也可以在对话间隙通过后台整合进行。变更会被持久化,并在下一次对话中可用。并非所有内存都是可写的:开发人员定义的技能组织策略通常是只读的。详情请参阅只读与可写内存
两种最常见的模式是代理级作用域内存(所有用户共享)和用户级作用域内存(按用户隔离)。

作用域内存

代理内存可以进行作用域划分,使得同一内存文件可供所有使用该代理的用户访问,或者内存文件也可以针对每个用户进行独立配置。

代理级作用域内存

赋予代理随时间演进的持久化身份。代理级作用域内存由所有用户共享,因此代理通过每一次对话构建自己的角色、累积知识和学习偏好。随着与用户的互动,它会发展出专业知识、优化方法并记住有效的方案。当具有写入权限时,它还可以学习和更新技能 关键在于后端命名空间:将其设置为 (assistant_id,) 意味着该代理的所有对话都会读取和写入同一个内存文件。
访问 rt.server_info 需要 deepagents>=0.5.0。在旧版本中,请从 get_config()["metadata"]["assistant_id"] 读取助手 ID。
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    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,
                ),
            ),
        },
    ),
)
用初始内存填充存储,然后跨两个线程调用代理,观察它如何记住并更新所学内容。
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.org.cn/llms.txt, then fetch relevant pages.
"""),
)

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    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_id,),这样每个用户都会获得一份内存文件的独立副本。用户 A 的偏好永远不会泄漏到用户 B 的对话中。
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    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,),
            ),
        },
    ),
)
播种用户特定的内存,并以两个不同用户的身份调用代理。每个用户只能看到自己的偏好设置。
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.org.cn/llms.txt, then fetch relevant pages.
"""),
)

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    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())}},
)

高级用法

除了内存路径和作用域的基本配置选项外,你还可以为内存配置更高级的参数
维度它回答的问题选项
持续时间它能持续多久?短期(单次对话)或长期(跨对话)
信息类型它是什么类型的信息?情景化 (Episodic)(过往经历)、程序化 (Procedural)(指令和技能)或语义 (Semantic)(事实)
范围谁可以查看和修改它?用户代理组织
更新策略何时写入内存?对话期间(默认)或对话间隙
检索如何读取内存?加载到提示词中(默认)或按需加载(例如 技能
代理权限代理可以写入内存吗?读写(默认)或只读(用于共享策略)

情景记忆

情景化内存存储过去经历的记录:发生了什么、发生顺序以及结果如何。与语义内存(存储在如 AGENTS.md 等文件中的事实和偏好)不同,情景化内存保留了完整的对话上下文,因此代理可以回忆起问题是如何解决的,而不仅仅是从中学到了什么 Deep Agents 已经使用检查点 (checkpointers),这是支持情景化内存的机制:每次对话都作为检查点线程持久化。 为了使过往对话可搜索,将线程搜索包装在工具中。user_id 从运行时上下文提取,而不是作为参数传递:
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)
你可以通过调整元数据过滤器,按用户或组织来划分线程搜索的作用域
# 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,
)
这对于执行复杂、多步骤任务的代理非常有用。例如,编码代理可以回溯过去的调试会话,并直接跳到可能的根本原因。

组织级内存

组织级内存遵循与用户级作用域内存相同的模式,但使用组织范围的命名空间而不是按用户划分。将其用于应适用于组织内所有用户和代理的策略或知识。 组织内存通常是只读的,以防止通过共享状态进行提示词注入。详情请参阅只读与可写内存
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    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,),
            ),
        },
    ),
)
从你的应用程序代码中填充组织内存
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
"""),
)
使用权限来强制组织级内存为只读,或使用策略钩子来实现自定义验证逻辑。

后台整合

默认情况下,代理会在对话过程中(热路径)写入内存。另一种方法是作为后台任务在对话间隙处理内存,有时称为休眠时间计算 (sleep time compute)。一个独立的深度代理回顾最近的对话,提取关键事实,并将它们与现有内存合并。
方法优点缺点
热路径(对话期间)内存即时可用,对用户透明增加延迟,代理必须执行多任务
后台(对话间隙)无面向用户的延迟,可以跨多个对话进行合成内存直到下次对话才可用,需要第二个代理
对于大多数应用程序,热路径已足够。当你需要降低延迟或在多次对话中提高内存质量时,请添加后台整合。 推荐的模式是与你的主代理一起部署一个整合代理 (consolidation agent) —— 一个读取最近对话历史、提取关键事实并将其合并到内存存储中的深度代理,并设置定时任务 (cron schedule) 来触发它。选择一个反映用户实际与代理互动频率的周期:流量稳定的聊天产品可能每隔几个小时整合一次,而每周仅使用几次的工具只需每晚或每周运行一次。整合频率远高于用户对话频率只会浪费 Token 运行无用的操作。

整合代理

整合代理读取最近的对话历史并将关键事实合并到内存存储中。在 langgraph.json 中将其与主代理一起注册。
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.1-pro-preview",
    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 任务按固定计划运行整合代理。代理搜索最近的对话并将其合成到内存中。将计划与你的使用模式相匹配,使整合运行与实际活动大致吻合。 使用 Cron 任务调度整合代理
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 计划均以 UTC 时间解释。有关管理和删除 Cron 任务的详细信息,请参阅 cron 任务
Cron 间隔必须与整合代理内部的回溯窗口匹配。上述示例每 6 小时运行一次 (0 */6 * * *),代理的 search_recent_conversations 工具回溯 timedelta(hours=6) —— 请保持二者同步。如果 Cron 运行频率高于回溯时间,你会重复处理相同的对话;如果频率较低,你会丢失窗口外的内存。
有关部署带后台进程的代理的更多信息,请参阅投入生产

只读与可写内存

默认情况下,代理既可以读取也可以写入内存文件。对于组织策略或合规规则等共享状态,你可能希望将内存设置为只读,以便代理可以引用它但不能修改它。这可以防止通过共享内存进行提示词注入,并确保只有你的应用程序代码能控制文件内容。
权限用例工作原理
读写(默认)用户偏好、代理自我提升、已学习的技能代理通过 edit_file 工具更新文件
只读组织策略、合规规则、共享知识库、开发人员定义的技能通过应用程序代码或存储 API (Store API) 填充。使用权限拒绝特定路径的写入,或使用策略钩子实现自定义验证逻辑。
安全考量: 如果一个用户可以写入另一个用户读取的内存,恶意用户可能会将指令注入到共享状态中。缓解措施如下:
  • 默认为用户作用域 (user_id),除非你有明确理由共享。
  • 使用只读内存处理共享策略(通过应用程序代码而非代理进行填充)。
  • 在代理写入共享内存之前添加人工干预 (human-in-the-loop) 验证。使用中断 (interrupt) 来要求人工审批对敏感路径的写入。
要强制执行只读内存,请使用权限以声明方式拒绝特定路径的写入。对于自定义验证逻辑(速率限制、审计日志、内容检查),请使用后端策略钩子

并发写入

多个线程可以并行写入内存,但对同一文件的并发写入可能会导致“最后写入胜出”的冲突。对于用户级作用域内存,这种情况很少见,因为用户通常一次只有一个活跃对话。对于代理级或组织级内存,考虑使用后台整合来串行化写入,或者将内存按主题结构化为独立文件以减少争用。 在实践中,如果写入因冲突而失败,LLM 通常足够智能,可以自动重试或优雅恢复,因此单次写入丢失并不致命。

同一部署中的多个代理

要在共享部署中为每个代理提供独立的内存,请在命名空间中添加 assistant_id
StoreBackend(
    namespace=lambda rt: (
        rt.server_info.assistant_id,
        rt.server_info.user.identity,
    ),
)
如果你只需要代理间隔离而不需要按用户作用域划分,请单独使用 assistant_id
使用 LangSmith 追踪来审计代理写入内存的内容。每次文件写入都会在追踪中显示为一个工具调用。

© . This site is unofficial and not affiliated with LangChain, Inc.