文档索引 在以下地址获取完整的文档索引:https://docs.langchain.org.cn/llms.txt
在进一步探索之前,请使用此文件发现所有可用页面。
内存功能可以让你的代理在不同对话间学习并提升能力。Deep Agents 通过基于文件系统的内存将内存提升为一等公民:代理以文件形式读取和写入内存,你可以使用后端 (backends) 来控制这些文件的存储位置。
本页面介绍长期内存 :即跨对话持久存在的内存。关于短期内存(单个会话内的对话历史和草稿文件),请参阅上下文工程 指南。短期内存作为代理状态 的一部分进行自动管理。
记忆如何工作
将代理指向内存文件。 创建代理时,通过 memory= 传入文件路径。你也可以通过 skills= 传入技能 (skills) 以实现程序化内存(告诉代理如何 执行任务的可重用指令)。后端 (backend) 控制文件存储位置及访问权限。
代理读取内存。 代理可以在启动时将内存文件加载到系统提示词中,或者在对话过程中按需读取。例如,技能 使用按需加载:代理仅在启动时读取技能描述,只有在与任务匹配时才读取完整的技能文件。这样可以在需要某种能力之前保持上下文精简。
代理更新内存(可选)。 当代理学到新信息时,可以使用其内置的 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 中将其与主代理一起注册。
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 ],
)
{
" 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。
将这些文档 连接到 Claude、VSCode 等,以获得实时答案。