DeepAgents 记忆机制:让 AI Agent 拥有“跨对话“的记忆

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


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

1.1 记忆机制的整体架构

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

步骤 做什么 类比
1. 准备存储与文件 配置 Backend 和 Store,预置记忆文件 装修房子,准备好书架
2. 加载记忆 memory= 指定文件路径,内容进入系统提示词 入住时把书摆上书架
3. 更新记忆(可选) 通过提示词约定写入规则,Agent 调用 edit_file 更新 读完后往书架上添新书
python 复制代码
# 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 结束即消失 永久保留(除非手动删除)
实现机制 Checkpointer StoreBackend + CompositeBackend
典型用途 对话上下文、临时文件 用户偏好、项目知识、Agent 经验
类比 工作桌面 书房书架

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

3.1 Checkpointer:短期记忆的基础

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

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

来看实际代码演示:

python 复制代码
from langgraph.checkpoint.memory import InMemorySaver

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 中间件:

python 复制代码
from langchain.messages import RemoveMessage
from langgraph.graph.message import REMOVE_ALL_MESSAGES
from langchain.agents import AgentState
from langchain.agents.middleware import before_model
from langgraph.runtime import Runtime

@before_model
def trim_messages(state: AgentState, runtime: Runtime) -> dict | None:
    """只保留最近几条消息,防止上下文溢出。"""
    messages = state["messages"]
    if len(messages) <= 3:
        return None  # 不需要裁剪

    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,添加自定义字段:

python 复制代码
class CustomAgentState(AgentState):
    user_id: str          # 用户 ID
    preferences: dict     # 用户偏好

agent = create_agent(
    model=model,
    state_schema=CustomAgentState,
    checkpointer=checkpointer,
)

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

python 复制代码
@tool
def get_user_info(runtime: ToolRuntime) -> str:
    """查询当前用户信息。"""
    user_id = runtime.state["user_id"]  # 从 Agent State 中读取
    return f"用户ID: {user_id}"

@tool
def update_preferences(new_theme: str, runtime: ToolRuntime):
    """更新用户偏好设置。"""
    from langgraph.types import Command
    current_prefs = runtime.state.get("preferences", {})
    current_prefs["theme"] = new_theme
    return Command(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 的记忆。

python 复制代码
# Agent 级记忆:所有用户共享
namespace = ("my-coding-agent", "memories")

# 用户级记忆:按用户隔离
namespace = ("user-123", "memories")   # 用户 A
namespace = ("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 的核心能力。它的思想很简单:不同的文件路径,路由到不同的后端存储。

python 复制代码
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

backend = CompositeBackend(
    default=StateBackend(),  # 默认路由:临时文件
    routes={
        "/memories/": StoreBackend(
            namespace=lambda rt: (rt.context.user_id, "memories"),
        ),
        "/policies/": StoreBackend(
            namespace=lambda rt: (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 随时间积累知识,越来越'懂'这个领域

示例文件内容:

markdown 复制代码
## 从反馈中学到的经验
- 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
    → 跨多次对话逐渐构建项目知识库

示例文件内容:

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

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

怎么用:

  1. 用多个 memory 路径加载不同研究文件
  2. Agent 启动时加载所有文件,了解当前进度
  3. 每次对话更新对应的文件
python 复制代码
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)填充内容

如何实现:

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

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

python 复制代码
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("""## 合规政策
- 不得披露内部定价
- 金融建议必须附加免责声明
"""),
)

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

6.2 情景记忆(Episodic Memory)

用在什么场景:

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

和语义记忆的区别:

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

如何实现:

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

python 复制代码
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:
    """搜索过去的对话以获取相关上下文。"""
    user_id = current_user_id(runtime)
    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)

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

6.3 记忆的六个维度全景

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

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

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

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

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

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

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

json 复制代码
{
    "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------如何为敏感操作添加人工审批,构建安全的人机协作流程。

相关推荐
Helix2501 小时前
Python与其他编程语言优劣势对比:2026初学者选型指南
java·python·教程·编程语言·入门·初学者编程选型
龙腾AI白云1 小时前
数字孪生驱动大模型工业知识库:为具身机器人植入领域专业经验
数据库·人工智能·机器学习·知识图谱
Huangjin007_1 小时前
【Linux 系统篇(二十七)】文件(四):Ext 系列文件系统(上):从物理磁盘到逻辑抽象
linux·运维·服务器
大飞记Python1 小时前
MiMo-V2.6-Distill-Qwen-9B 本地部署实测:8GB内存可跑,但推理能力让人失望
人工智能·ai·ai编程
天天代码码天天1 小时前
开源 GPU OCR:不依赖 CUDA,C# 和 Web 都能用的 lw.PPOCR.Vulkan
人工智能
在所不辞兄2 小时前
分层PINN提升多物理场一致性
人工智能·神经网络·算法·机器学习·工程仿真
鬼手点金2 小时前
opencode-隐私优先配置
服务器·前端·javascript·bug·openclaw
夜之眷属2 小时前
记一次战斗服务器 CPU 打满 100% 且“无法恢复“的排查
java·linux·运维·服务器·后端·性能优化
林伽一2 小时前
从2048并发会话到501B开源模型,算力账本开始按“单位卡产出“计价|2026年10月07日
人工智能·安全·ai·开源