☰
DeepAgents 记忆机制:让 AI Agent 拥有“跨对话“的记忆
2026/10/8 7:24:31 网站建设 项目流程

作为一个 39 岁的技术人,我最近在啃 DeepAgents 框架的长期记忆章节时,发现了一个很有意思的设计——Agent 的记忆不是像人类大脑那样"自然存在"的,而是通过文件系统 + 存储后端 + 路由机制这套组合拳来实现的。上一章我们学完了 Skills(可复用的能力包),但 Skills 解决的是"Agent 会做什么",而本章的 Memory 解决的是"Agent 记得什么"。今天我们就来把这个机制扒开揉碎,讲得明明白白。


一、DeepAgents 中的记忆机制是怎么实现的?

1.1 记忆机制的整体架构

DeepAgents 将记忆作为一等公民——Agent 以文件形式读写记忆,你用 Backend 控制这些文件存储在哪里。整个流程可以概括为三步:

步骤做什么类比
1. 准备存储与文件配置 Backend 和 Store,预置记忆文件装修房子,准备好书架
2. 加载记忆memory=指定文件路径,内容进入系统提示词入住时把书摆上书架
3. 更新记忆(可选)通过提示词约定写入规则,Agent 调用edit_file更新读完后往书架上添新书
# memory= 是读取配置:指定哪些文件的内容会被注入系统提示词# skills= 是程序性记忆:先注入元数据,正文由 Agent 按需读取agent=create_deep_agent(model=model,memory=["/memories/preferences.md"],# 加载用户偏好skills=["/skills/"],# 加载技能包backend=...,# 控制文件存在哪里)

关键细节:在 DeepAgents 0.7.10 中,缺失的记忆文件会被跳过,不会自动创建,缺失文件的路径也不会作为已加载记忆注入提示词。所以要固定偏好的写入位置,需要同时约定写入路径——仅声明memory=不能保证 Agent 使用这个文件名。

1.2 memory= vs backend=:它们各自管什么?

这是很多初学者容易混淆的地方。我们用一张表说清楚:

参数职责类比如果不配置会怎样
memory=读配置:告诉框架"启动时把哪些文件的内容加载到系统提示词里"“请帮我把书架上那本《用户手册》拿给我看”Agent 启动时不加载任何已有记忆
backend=存储配置:告诉框架"文件实际存在哪里、怎么路由"“书架是实木的还是金属的、放在哪个房间”文件存在默认的 StateBackend(对话结束就没了)

它们的关系是这样的:

memory=["/memories/preferences.md"] ↓ 告诉框架要加载这个文件 ↓ 框架去 backend 中找这个路径 ↓ backend = CompositeBackend( routes={"/memories/": StoreBackend(...)} ↑ 告诉框架 /memories/ 开头的文件存在 StoreBackend 里 )

memory=负责**“加载什么”,backend=负责"存在哪、怎么找"**。两者配合,缺一不可。


二、Agent 的两种记忆:短期记忆和长期记忆的应用场景区别

人类有短期记忆和长期记忆——你记得今天的对话内容(短期),也记得你的名字和偏好(长期)。Agent 也一样,但需要不同的技术来实现。

2.1 短期记忆(Thread-scoped)

定义:同一个对话线程(thread)内持久化,对话结束后消失。

实现方式:默认的StateBackend将文件存在 LangGraph 的 Agent State 中,通过Checkpointer机制保证同一 thread 内多轮对话不丢失。

应用场景:

  • 当前任务的中间结果(比如草稿、临时笔记)
  • 对话上下文(“你刚才说了什么”)
  • 本次会话中产生的临时文件

类比:就像你的工作桌面——当前任务的资料都摊在上面,但下班清理后就干净了。换一个 thread_id,桌面就清空了。

2.2 长期记忆(Cross-thread)

定义:跨不同对话线程保留的信息,不随对话结束而消失。

实现方式:通过StoreBackend存储在持久化存储中(内存、PostgreSQL、LangSmith 平台等)。

应用场景:

  • 用户的偏好设置(“我喜欢简洁的代码风格”)
  • 项目的背景知识(“我们用 React + TypeScript”)
  • 累积的研究成果(多次对话中逐渐收集的资料)
  • Agent 从反馈中学到的改进指令

类比:就像你的书房书架——不管今天聊什么,书架上的书都在那里,明天来还在。

2.3 两者的对比

维度短期记忆长期记忆
作用域单个 thread(对话线程)跨所有 thread
底层存储Agent State(内存中的状态字典)Store(持久化存储)
生命周期thread 结束即消失永久保留(除非手动删除)
实现机制CheckpointerStoreBackend + CompositeBackend
典型用途对话上下文、临时文件用户偏好、项目知识、Agent 经验
类比工作桌面书房书架

三、DeepAgents 中短期记忆的实现机制和记忆管理策略

3.1 Checkpointer:短期记忆的基础

Checkpointer 是 LangGraph 的短期记忆机制。它的工作原理很简单:

  1. 每次 Agent 执行完一步,自动保存当前状态(消息历史、文件系统状态、任务清单等)
  2. 下次调用时,如果thread_id相同,自动恢复上次的状态
  3. 开发用MemorySaver(内存,重启丢失),生产用PostgresSaver(数据库,持久化)

来看实际代码演示:

fromlanggraph.checkpoint.memoryimportInMemorySaver checkpointer=InMemorySaver()agent=create_deep_agent(model=model,checkpointer=checkpointer,)# 同一个 thread_id 内,Agent 记得之前的对话config={"configurable":{"thread_id":"conversation-001"}}agent.invoke({"messages":[{"role":"user","content":"我叫张三"}]},config=config)agent.invoke({"messages":[{"role":"user","content":"我叫什么名字?"}]},config=config)# Agent 能回答"你叫张三"# 换一个 thread_id,Agent 不记得了config2={"configurable":{"thread_id":"conversation-002"}}agent.invoke({"messages":[{"role":"user","content":"我叫什么名字?"}]},config=config2)# Agent 不知道你是谁

实际运行效果:

Thread 1 ID: conversation-001 Thread 2 ID: conversation-002 → 两个 thread 之间状态完全隔离,互不干扰 Thread 1 保存了: 我叫张三 Thread 2 是空的: [] → 换 thread 后,Agent 不记得之前对话的内容

关键限制:Checkpointer 只在同一个thread_id内有效。不同的对话(不同thread_id)之间,状态完全隔离。

3.2 短期记忆的管理策略

随着对话越来越长,消息历史可能超出 LLM 的上下文窗口。LangChain 提供了三种应对策略:

策略做法适用场景
Trim(裁剪)只保留最近 N 条消息,丢弃更早的简单粗暴,适合不需要历史上下文的场景
Delete(删除)用RemoveMessage精确删除特定消息需要选择性清理(如删除敏感信息)
Summarize(总结)用 LLM 将旧消息压缩为摘要需要保留历史语义,是最推荐的方式

在 DeepAgents 中,Summarize 策略已经自动内置(SummarizationMiddleware)。create_deep_agent()在已知模型窗口大小时,默认到 85% 触发;缺少窗口信息时使用固定 token 阈值。

如果你需要自定义裁剪逻辑,可以用 LangChain 的@before_model中间件:

fromlangchain.messagesimportRemoveMessagefromlanggraph.graph.messageimportREMOVE_ALL_MESSAGESfromlangchain.agentsimportAgentStatefromlangchain.agents.middlewareimportbefore_modelfromlanggraph.runtimeimportRuntime@before_modeldeftrim_messages(state:AgentState,runtime:Runtime)->dict|None:"""只保留最近几条消息,防止上下文溢出。"""messages=state["messages"]iflen(messages)<=3:returnNone# 不需要裁剪first_msg=messages[0]# 保留第一条(通常是系统消息)recent=messages[-3:]# 保留最近 3 条return{"messages":[RemoveMessage(id=REMOVE_ALL_MESSAGES),first_msg,*recent,]}agent=create_deep_agent(model=model,middleware=[trim_messages],)

@before_model是 LangChain 的中间件装饰器——它在每次模型调用之前执行,可以修改传给模型的消息。对应地还有@after_model(模型调用之后执行)。

3.3 进阶:自定义 AgentState

LangChain 允许你扩展默认的AgentState,添加自定义字段:

classCustomAgentState(AgentState):user_id:str# 用户 IDpreferences:dict# 用户偏好agent=create_agent(model=model,state_schema=CustomAgentState,checkpointer=checkpointer,)

工具可以通过ToolRuntime读写这些自定义状态字段:

@tooldefget_user_info(runtime:ToolRuntime)->str:"""查询当前用户信息。"""user_id=runtime.state["user_id"]# 从 Agent State 中读取returnf"用户ID:{user_id}"@tooldefupdate_preferences(new_theme:str,runtime:ToolRuntime):"""更新用户偏好设置。"""fromlanggraph.typesimportCommand current_prefs=runtime.state.get("preferences",{})current_prefs["theme"]=new_themereturnCommand(update={"preferences":current_prefs})

关键点:runtime.state是读状态,Command(update={...})是写状态。这样工具不仅能返回结果给模型,还能直接修改 Agent 的短期记忆。


四、DeepAgents 中的长期记忆:路径路由与用户隔离

4.1 长期记忆都有哪些?

DeepAgents 的长期记忆通过Store存储,主要包括:

记忆类型存储内容作用域典型文件路径
Agent 级记忆Agent 从多次对话中积累的知识所有用户共享/memories/AGENTS.md
用户级记忆个人偏好、私有笔记单个用户/memories/preferences.md
组织级记忆合规策略、公司政策全组织共享/policies/compliance.md
项目记忆技术栈、架构文档项目组成员/memories/project/tech-stack.md
研究记忆研究笔记、参考资料研究者/memories/research/sources.md
情景记忆过去的完整对话记录单个用户通过 Checkpointer 搜索

4.2 如何分清不同用户的长期记忆?——namespace 机制

DeepAgents 通过namespace(命名空间)来隔离不同用户、不同 Agent 的记忆。

# Agent 级记忆:所有用户共享namespace=("my-coding-agent","memories")# 用户级记忆:按用户隔离namespace=("user-123","memories")# 用户 Anamespace=("user-456","memories")# 用户 B

实际运行效果:

Agent 级记忆(所有用户共享): Namespace: ('my-coding-agent', 'memories') 内容: ## Agent 知识库 - 本项目使用 React + TypeScript - 代码规范:ESLint + Prettier 用户 A 的私有记忆: Namespace: ('alice', 'memories') 内容: # Alice 的偏好 - 深色主题 - 中文注释 用户 B 的私有记忆: Namespace: ('bob', 'memories') 内容: # Bob 的偏好 - 浅色主题 - 英文注释 关键区别: Agent 级: namespace = (assistant_id, 'memories') → 所有用户读同一份 用户级: namespace = (user_id, 'memories') → 各用户隔离

4.3 什么是路径路由机制?

路径路由是CompositeBackend的核心能力。它的思想很简单:不同的文件路径,路由到不同的后端存储。

fromdeepagents.backendsimportCompositeBackend,StateBackend,StoreBackend backend=CompositeBackend(default=StateBackend(),# 默认路由:临时文件routes={"/memories/":StoreBackend(namespace=lambdart:(rt.context.user_id,"memories"),),"/policies/":StoreBackend(namespace=lambdart:(rt.context.org_id,),),},)

4.4 路径路由在长期记忆中起到什么作用?

路径路由解决了三个核心问题:

1. 透明的存储切换:Agent 操作文件的方式完全一样——都是调用write_file、read_file。区别只在于路径前缀:

write_file('/workspace/draft.txt', '草稿') → StateBackend (临时,对话后消失) write_file('/notes.txt', '笔记') → StateBackend (临时,对话后消失) write_file('/memories/preferences.md', '偏好') → StoreBackend (持久化) write_file('/policies/compliance.md', '合规') → StoreBackend (持久化)

2. 存储空间的隔离:/memories/和/policies/路由到不同的 namespace,互不干扰。

3. 路由前缀的自动剥离:

Agent 看到的虚拟路径: /memories/preferences.md 实际 Store 中的 key: /preferences.md(路由前缀 /memories/ 被自动剥离) 实际 Store 中的 namespace: (user_id, 'memories')

大坑提醒:如果 Store key 写成/memories/preferences.md(带路由前缀),CompositeBackend 在返回结果时还会补一次/memories/,最终暴露成错误的/memories/memories/preferences.md。Store key 不应该包含路由前缀!


五、四种实用场景

通俗讲解四种场景的使用方式

场景 1:用户偏好记忆(preferences.md)

一句话总结:让 Agent 记住"我喜欢什么"。

怎么用:

  1. 配置memory=["/memories/preferences.md"]
  2. 在 system_prompt 中约定:“当用户明确要求记住偏好时,用edit_file更新/memories/preferences.md”
  3. 用户说"记住我的偏好",Agent 就会调用edit_file写入

实际运行效果:

[场景 1] 用户偏好记忆 — preferences.md → 每次对话 Agent 都能记住并使用用户偏好
场景 2:自我改进的 Agent(AGENTS.md)

一句话总结:让 Agent 随着时间"越用越聪明"。

怎么用:

  1. 配置memory=["/memories/AGENTS.md"]
  2. 约定 Agent 从用户反馈中学习:“当用户指出错误时,记录到 AGENTS.md”
  3. 随着时间推移,AGENTS.md 积累越来越多经验

实际运行效果:

[场景 2] 自我改进的 Agent — AGENTS.md → Agent 随时间积累知识,越来越'懂'这个领域

示例文件内容:

## 从反馈中学到的经验 - 2026-01-15: 用户希望减少解释,直接给代码 - 2026-01-20: 用户希望错误信息附带修复建议
场景 3:知识库累积(project/*.md)

一句话总结:让 Agent 跨多次对话逐渐构建项目知识库。

怎么用:

  1. 按项目子目录组织文件:/memories/project/tech-stack.md
  2. 每次对话,Agent 读取已有内容,追加新信息
  3. 新对话启动时,Agent 加载完整的项目知识

实际运行效果:

[场景 3] 知识库累积 — project/tech-stack.md → 跨多次对话逐渐构建项目知识库

示例文件内容:

## 项目技术栈 - 前端: React 18 + TypeScript - 后端: FastAPI + Python 3.12 - 数据库: PostgreSQL 16 - 部署: Docker + K8s
场景 4:研究项目持续推进(research/*.md)

一句话总结:让大型研究任务可以"分多次对话"持续推进。

怎么用:

  1. 用多个memory 路径加载不同研究文件
  2. Agent 启动时加载所有文件,了解当前进度
  3. 每次对话更新对应的文件
agent=create_deep_agent(model=model,memory=["/memories/research/sources.md",# 参考资料"/memories/research/notes.md",# 研究笔记"/memories/research/report.md",# 研究报告],...)

实际运行效果:

[场景 4] 研究项目持续推进 — 多个 memory 文件 /research/sources.md ✓ /research/notes.md ✓ /research/report.md ✓ → Agent 启动时加载所有文件,每次对话更新进度

核心使用原则

原则说明
按主题拆分文件不要把所有记忆塞进一个大文件,拆分成preferences.md、tech-stack.md、sources.md等
memory= 加载,提示词约定写入memory=负责读取,system_prompt负责约定写入规则
持久化路径要有意义用/memories/project/tech-stack.md而不是/memories/file1.md

六、组织记忆和情景记忆:场景与实现

6.1 组织级记忆(Organization-level Memory)

用在什么场景:

  • 公司的合规政策(“不得披露内部定价”)
  • 全组织共享的知识库
  • 安全规则和行为准则

核心特点:

  • 跨所有用户和 Agent 共享
  • 通常设为只读(防止恶意用户注入攻击)
  • 由应用代码(而非 Agent)填充内容

如何实现:

agent=create_deep_agent(model=model,memory=["/memories/preferences.md",# 用户级(可读写)"/policies/compliance.md",# 组织级(只读)],backend=CompositeBackend(default=StateBackend(),routes={"/memories/":StoreBackend(namespace=lambdart:(rt.context.user_id,"memories"),# 用户级),"/policies/":StoreBackend(namespace=lambdart:(rt.context.org_id,),# 组织级),},),)

从应用代码中填充组织级记忆:

fromlanggraph_sdkimportget_clientfromdeepagents.backends.utilsimportcreate_file_data client=get_client(url="<DEPLOYMENT_URL>")awaitclient.store.put_item((org_id,),"/compliance.md",create_file_data("""## 合规政策 - 不得披露内部定价 - 金融建议必须附加免责声明 """),)

安全提醒:如果一个用户能写入另一个用户读取的记忆,恶意用户可以注入指令。共享策略应该用只读模式——通过应用代码填充,不让 Agent 写入。

6.2 情景记忆(Episodic Memory)

用在什么场景:

  • 回忆"上次是怎么解决这个问题的"
  • 搜索过去的完整对话记录
  • Agent 回溯上次调试过程,直接跳到可能的根因

和语义记忆的区别:

  • 语义记忆:记"是什么"(事实和偏好)→/memories/preferences.md
  • 情景记忆:记"发生了什么"(完整经历)→ 过去的对话历史

如何实现:

DeepAgents 的Checkpointer 天然支持情景记忆——每次对话都被完整持久化。要让过去的对话变得可搜索,可以包装一个搜索工具:

fromlanggraph_sdkimportget_clientfromlangchain.toolsimporttool,ToolRuntime client=get_client(url="<DEPLOYMENT_URL>")@toolasyncdefsearch_past_conversations(query:str,runtime:ToolRuntime)->str:"""搜索过去的对话以获取相关上下文。"""user_id=current_user_id(runtime)threads=awaitclient.threads.search(metadata={"user_id":user_id},limit=5,)results=[]forthreadinthreads:history=awaitclient.threads.get_history(thread_id=thread["thread_id"])results.append(history)returnstr(results)

这对执行复杂多步任务的 Agent 尤为有用——比如代码 Agent 可以回溯上次调试过程,直接跳到可能的根因。

6.3 记忆的六个维度全景

官方文档将记忆系统拆分为六个可独立配置的维度:

维度核心问题选项
持续时间保留多久?短期(单次对话)/ 长期(跨对话)
信息类型记什么?情景记忆 / 程序性记忆(Skills)/ 语义记忆(事实)
作用域谁能看?用户级 / Agent 级 / 组织级
更新策略何时写入?对话中(默认)/ 对话间(后台整合)
检索方式如何读取?启动加载(memory=)/ 按需读取(Skills)
权限控制Agent 能写吗?读写(默认)/ 只读(共享策略)

这六个维度互相独立,你可以自由组合。比如:

  • “用户偏好” = 长期 + 语义记忆 + 用户级 + 对话中写入 + 启动加载 + 读写
  • “合规政策” = 长期 + 语义记忆 + 组织级 + 应用代码写入 + 启动加载 + 只读

七、从开发到生产:Store 的升级路径

阶段Store 类型特点
开发阶段InMemoryStore零配置,快速迭代,重启丢失
生产阶段PostgresStore真正持久化,可伸缩,需要pip install langgraph-checkpoint-postgres
LangSmith 部署平台自动配置无需手动管理,平台自动提供持久化存储

记忆文件格式(deepagents >= 0.5 v2 格式)

{"content":"第一行\n第二行\n第三行","encoding":"utf-8","created_at":"2024-01-15T10:30:00Z","modified_at":"2024-01-15T11:45:00Z"}

不要手写底层 JSON!Agent 外部(后端服务、初始化脚本)预填记忆时应使用create_file_data辅助函数。


小结

本章我们深入剖析了 DeepAgents 的记忆系统:

  • 短期记忆靠 Checkpointer,管同一个 thread 内的状态持久化
  • 长期记忆靠 Store + CompositeBackend,跨 thread 保留信息
  • memory=是读配置,backend=是存储配置,两者配合才完整
  • 路径路由让 Agent 用统一方式操作文件,底层自动路由到正确的存储
  • namespace实现了用户级、Agent 级、组织级的隔离
  • 四种实用场景告诉你:通用记忆能力在实际中怎么用
  • 组织记忆用只读模式防注入,情景记忆用搜索工具回溯历史

记忆机制的本质就是:把"记忆"变成"文件",把"存储"变成"后端",把"隔离"变成"路由规则"。理解了这个底层逻辑,你就能灵活应对各种记忆需求。

下一章,我们将学习 Human-in-the-Loop——如何为敏感操作添加人工审批,构建安全的人机协作流程。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询