夜雨聆风学习资料网

ARTICLE · 992340

《AI Agent 核心技术解析》|CHAPTER 05 Memory

《AI Agent 核心技术解析》|CHAPTER 05 Memory
inShocking

INSHOCKING · ENGINEERING NOTE

quiet interface / sudden insight

IN / FEATURE SIGNAL

Agent Memory:从上下文管理到长期记忆运行时

《AI Agent 核心技术解析》 CHAPTER 05

AI AGENT · MEMORY · CONTEXT ENGINEERING · AGENT RUNTIME

inShocking

让 agent完成一次回答并不难,调LLM 返回一次 output 就好了。

但是让 Agent 在几天、几个月甚至跨多个任务后,仍然记得用户偏好、项目决定和过去的执行经验,问题就会变得复杂起来。

假设用户在一次会话里提出:

IN / SOURCE SIGNAL 

我们公司内部 Java 项目统一使用自研框架注解,不要使用 springboot 的。后续生成的代码都遵守这条约定。

只要这句话还在当前对话中,模型通常能够照做。换一个 session,或者旧消息因为上下文压缩被移走后,这条约定可能不再可见。将全部历史消息重新发送给模型可以暂时缓解问题,但随着会话增多,输入成本、噪声和隐私风险都会持续上升。

这类跨时间的信息管理由 Agent Memory 负责。它从用户对话交互中选择有长期价值的信息,将其保存、整理和索引,并在后续任务中按权限和相关性重新加载。

从运行时角度看,Memory 横跨当前上下文、会话状态、原始轨迹、长期知识和任务系统,并包含两条持续运行的数据链路:

IN / TEXT
写入链路:交互 → 抽取 → 校验 → 去重/更新 → 持久化 → 建索引加载链路:请求 → 查询理解 → 权限过滤 → 检索 → 重排 → 上下文注入

这两条链路决定了 Agent 会记住什么、会忘掉什么,以及某段旧信息能否影响今天的行动。

本文以通用记忆架构为主线。learn-claude-code 和 AgentScope Java 用于说明两种实现尺度:前者展示一个可逐行阅读的最小闭环,后者展示记忆进入长运行、多会话和分布式 Agent Runtime 后需要补齐的工程边界。

本文源码:

  • AgentScope Java:

    https://java.agentscope.io/v1/zh/docs/task/memory.html

  • learn-claude-code:
    https://learn.shareai.run/zh/s09/

IN / SIGNAL 01

1. Agent Memory 的历史定位

1.1 对话历史解决了最早的连续性问题

早期对话系统通常把历史消息拼接到下一次模型请求中。对大模型应用而言,这种做法直接、有效:

IN / TEXT
system prompt+ 第 1 轮 user / assistant+ 第 2 轮 user / assistant+ 当前 user message→ 下一次模型调用

只要历史没有超出上下文窗口,模型就能引用前文。这里的 history 更接近短期工作记录。它没有判断哪些信息值得长期保存,也没有解决跨 session 共享、事实更新和按需检索。

随着 Agent 开始调用工具,历史消息中又出现了 Tool Call、Tool Result、代码、日志和外部页面。上下文增长速度明显快于普通聊天。一条命令输出就可能占用数万 token,完整保留所有历史逐渐变得不可行。

1.2 RAG 扩展了模型可访问的外部知识

Retrieval-Augmented Generation 把文档放入外部知识库,根据当前问题检索相关片段,再把结果交给模型。它解决了模型参数之外的知识访问问题,也形成了成熟的切分、索引、召回与重排体系。

Memory 系统会复用这些检索技术,但两者关注的数据来源不同。RAG 的语料通常由组织或应用预先提供,例如产品文档、合同和代码库;Memory 则持续从 Agent 与用户、工具和环境的交互中产生。它还要处理用户作用域、session、时间变化、事实纠正、删除请求和写入权限。

1.3 长上下文扩大了容量,没有消除选择问题

模型上下文窗口不断扩大后,应用可以一次传入更多历史。容量提升很有价值,但大量低相关信息仍会占用注意力和输入成本。旧工具结果、重复对话和已失效事实混在一起时,模型还可能引用错误版本。

Anthropic 在 context engineering 的工程实践中,将上下文视为有限的注意力预算,并建议对长任务使用 compaction、结构化笔记和子 Agent 隔离。Effective context engineering for AI agents

因此,长上下文与外部记忆通常配合使用:context 保留当前任务最有用的信息,外部存储保留可按需取回的历史与知识。

1.4 Agent 研究把记忆扩展为主动管理机制

近几年的代表性工作分别推动了几个方向:

  • Generative Agents 保存完整经历,根据相关性、近因性和重要性取回记忆,并通过 reflection 形成更高层认识。Generative Agents
  • Reflexion 将任务反馈转化为语言反思,写入 episodic memory,用于下一次尝试。Reflexion
  • MemGPT 参考操作系统的分层内存,在有限上下文与外部存储之间搬运信息,形成 virtual context。MemGPT
  • CoALA 从认知架构角度统一描述工作记忆、长期记忆、内部动作和外部动作。CoALA

这些工作让 Memory 从被动保存聊天记录,逐步演进为 Agent 可以读写、整理和反思的运行时能力。

阶段
主要做法
解决的问题
仍然存在的限制
对话 history
拼接历史消息
当前会话连续性
容量、成本、跨会话
RAG
检索外部文档
参数外知识访问
交互记忆、时间与用户作用域
长上下文
一次输入更多历史
减少截断
注意力稀释、无关信息
Agent Memory
主动写入、整理、检索和遗忘
长期连续性与经验复用
一致性、安全、评测

IN / SIGNAL 02

2. 什么是 Agent Memory

可以把 Agent Memory 定义为:

IN / SOURCE SIGNAL 

Agent Runtime 对历史交互、环境观察、用户信息和执行经验进行选择性持久化、组织、检索与更新的能力。

这个定义包含几个限制。

这里的存储具有选择性。原始对话和工具轨迹可以完整归档,但长期记忆只保留后续任务仍可能使用的信息。

每条记忆还要落到明确的作用域。个人偏好通常属于 user,一次任务的进度属于 session 或 task,团队运行手册属于 project。作用域错误会导致数据串扰。

长期信息本身也会变化。偏好可能更新,项目事实可能失效,旧经验可能被新实践取代,因此存储层必须支持版本、有效时间、删除和重新整理。

外部网页、旧会话和子 Agent 产出的文本都可能进入记忆库,这些内容不会自动获得指令权限,也不能覆盖 system policy 或当前用户授权。

2.1 Memory 与相邻概念的边界

概念
保存内容
典型生命周期
默认进入模型上下文吗
Context
当前请求、近期消息、工具结果、召回资料
一次模型调用
Session State
消息、摘要、计划、权限、任务状态
一个 session
部分进入
Transcript
完整消息与工具轨迹
长期归档
否,按需检索
Long-term Memory
筛选后的偏好、事实、经验、规则
跨 session
选择性进入
RAG Knowledge
预先提供的外部知识
随知识库版本
选择性进入
Task State
状态、依赖、结果、完成条件
一个任务
按运行需要进入

Context 是模型此刻能看到的输入集合。Memory 是构造这份输入时可以使用的信息来源之一。

Session State 让同一个会话能够恢复。它除了对话,还可能包含 Plan Mode、todo、权限和工具状态;Long-term Memory 则负责跨会话的知识连续性。

Transcript 追求保真,Memory 追求复用价值。一次排障轨迹可以完整保存在 transcript 中,经过验证的根因和处理方法再晋升为长期记忆。至于 background job 的 RUNNINGCOMPLETED 和 FAILED,它们具有明确状态转换,应该进入任务仓库,而不是只写进自然语言摘要。

IN / SIGNAL 03

3. 为什么 Agent 需要记忆

3.1 跨会话连续性

个人助理需要记住用户的语言、格式和工作偏好;编码 Agent 需要记住仓库的构建命令、模块边界和验证方式;客服 Agent 需要知道用户之前的问题与处理结果。

这些信息如果每次都由用户重新提供,Agent 只能完成一次性问答,无法形成稳定的长期协作关系。

3.2 长任务的上下文管理

代码迁移、技术调研和生产排障可能跨越几十次模型调用。完整历史会持续膨胀,最终需要摘要、落盘或重新开一个 context window。

长任务需要两类持久信息:

  • 用于继续执行的状态,例如当前目标、已修改文件、剩余步骤和后台任务;
  • 用于未来复用的知识,例如仓库测试命令、失败原因和验证过的解决方案。

前者属于 session/task state,后者可以沉淀为长期记忆。

3.3 个性化

同一个问题对不同用户可能有不同答案。有人偏好简短结论,有人需要完整推导;有人使用 Java 17,有人受限于 Java 8;某个团队要求所有数据库变更经过人工确认。

个性化信息具有用户或组织作用域。记忆系统需要在检索前完成权限过滤,不能先跨租户搜索,再依赖模型自行忽略不该看到的内容。

3.4 经验复用

Agent 在工具环境中会产生大量执行轨迹。成功轨迹可以转化为案例,失败轨迹可以转化为反思,经过验证的反思还可以晋升为程序记忆或 Skill。

这类能力让 Agent 在不更新模型参数的情况下,利用过去的工作结果改进后续决策。

3.5 上下文成本

每次模型调用都重新发送全部记忆,会把长期存储成本转换为持续的 token 成本。更合理的方式是保留小型目录、profile 或摘要,根据当前请求逐步加载正文。

记忆系统追求的目标是用少量高相关内容支撑当前推理。

IN / SIGNAL 04

4. Agent Memory 的组成

一个完整实现通常包含五个运行组件和一套元数据。

IN / TEXT
                    ┌────────────────────┐Conversation ──────►│   Memory Writer    │Tool / Event        │ extract + validate │                    └─────────┬──────────┘                              ▼                    ┌────────────────────┐                    │    Memory Store    │                    │ facts / episodes  │                    └─────────┬──────────┘                              │                 ┌────────────┴────────────┐                 ▼                         ▼       ┌──────────────────┐      ┌──────────────────┐       │   Consolidator   │      │    Retriever     │       │ merge / version  │      │ search / rerank  │       └────────┬─────────┘      └────────┬─────────┘                │                         ▼                └──────────────► Context Injector                                           │                                           ▼                                         Model

4.1 Memory Writer

Writer 决定当前交互是否产生了值得保存的信息。它可能由用户显式触发,也可能在回合结束、任务完成或 compaction 前自动运行。

LLM 适合做语义抽取和初步分类,确定性程序负责 schema、权限、敏感字段、作用域和幂等校验。

4.2 Memory Store

Store 保存记忆记录和原始证据。后端可以是文件、关系数据库、KV、对象存储、向量库或知识图谱。复杂系统通常组合多个后端,不要求一个数据库承担所有职责。

4.3 Consolidator

Consolidator 处理重复、冲突、过期和容量限制。它把细粒度记录合并为稳定的长期视图,也负责保留版本和推进处理水位。

Consolidation 属于有损操作。生产实现需要快照、版本或可重放事件源,避免一次错误整理永久破坏记忆。

4.4 Retriever

Retriever 根据当前请求查找候选记忆。常见信号包括关键词、向量相似度、实体、时间范围、来源权威、任务状态和最近使用频率。

召回结果还需要去重与 rerank。低于阈值时返回空结果,是正常行为。

4.5 Context Injector

Injector 把最终选择的记忆放入模型上下文,并明确它们的来源、时间和优先级。它要控制 token 预算,避免记忆挤占当前请求、工具说明和必要的近期消息。

4.6 记忆元数据

一条生产级记忆通常需要以下字段:

IN / JSON
{  "id": "mem_01...",  "namespace": ["tenant", "user", "project"],  "kind": "semantic | episodic | procedural | prospective",  "content": "用户在 Java 项目中偏好构造器注入",  "source": {    "session_id": "s-123",    "message_ids": ["m-8", "m-9"],    "actor": "user"  },  "valid_time": {"from": "2026-08-30", "to": null},  "recorded_at": "2026-08-30T12:00:00Z",  "confidence": 0.95,  "authority": "user_explicit",  "status": "active",  "supersedes": null,  "tags": ["java", "style"],  "embedding_version": "v3"}

source 保留证据来源,namespace 决定可见范围,valid_time 表示事实在现实世界中的有效期,recorded_at 表示系统何时记录它。supersedes 用于表达新版本对旧版本的替代关系。

IN / SIGNAL 05

5. 一条记忆如何运行

下面用用户偏好为例,走完整个生命周期。

5.1 产生

用户在会话中说:

IN / TEXT
我们的 Java 项目统一使用构造器注入,后续生成的代码都遵守这条约定。

这句话首先进入 conversation。此时它只是当前上下文中的一条用户消息。

5.2 抽取

Writer 判断这是一条稳定、未来可复用的项目约定,生成候选记录:

IN / JSON
{  "kind": "semantic",  "scope": "persistent",  "content": "该 Java 项目统一使用构造器注入",  "authority": "user_explicit"}

同一个会话里如果还有一句这次不要新建文件,抽取器应将它标为 current task,而不是 persistent。

5.3 校验

确定性代码检查:

  • 当前调用是否有权写入该 namespace;
  • schema 是否完整;
  • 内容是否包含密钥或禁止保存的 PII;
  • scope 是否允许跨会话;
  • source message 是否真实存在;
  • 幂等键是否已经处理。

LLM 输出通过这些检查后,才能进入持久化阶段。

5.4 去重与冲突处理

系统查找同主题记录。如果旧记录已经表达相同事实,可以跳过或增加证据引用。如果旧记录写着该项目使用字段注入,则新旧内容发生冲突。

冲突处理不应简单地用最后写入覆盖一切。系统需要比较 authority、时间和作用域,并保留 supersedes 关系。

5.5 持久化与索引

通过校验的记录写入主存。随后更新全文、向量或图索引。主存写入和索引更新之间需要 outbox、重试或重建机制,防止主记录已经成功但检索索引仍然缺失。

5.6 整理

后台任务会把相近记录合并,清理重复描述,更新旧版本并控制长期视图大小。原始事件和历史版本继续用于审计与重建。

5.7 检索与注入

未来用户要求生成一个 Spring Service。Retriever 根据 Java、依赖注入和当前 project namespace 找到这条记忆,经权限过滤和重排后,把它作为项目背景注入 context。

模型最终看到的内容可以是:

IN / TEXT
<memory_context>Source: project/user memoryRecorded: 2026-08-30- 该 Java 项目统一使用构造器注入。</memory_context>

5.8 更新与遗忘

用户后来将约定改为框架生成类允许字段注入。系统新建记录并结束旧记录的有效期,同时保留历史。

用户要求删除记忆时,需要同时处理主存、索引、缓存和派生视图。Context eviction 只表示不再放进当前 prompt,不等于合规删除。

IN / SIGNAL 06

6. 如何对记忆分类

记忆可以从时间范围和内容用途两个维度分析。

6.1 按时间范围分类

层次
生命周期
典型内容
常见实现
工作记忆
一次模型调用
当前请求、近期观察、工具结果
context window
会话记忆
一个 session
消息、滚动摘要、计划、权限
StateStore、checkpoint
跨会话记忆
多个 session
偏好、稳定事实、可复用经验
文件、SQL、向量、图
团队记忆
多 Agent、多用户、多项目
规范、运行手册、验证过的经验
共享知识库、artifact
参数记忆
模型版本生命周期
模型内化的知识与行为
预训练、微调

MemGPT 的 virtual context 可以理解为在工作记忆与外部长期存储之间进行受控换入和换出。MemGPT

6.2 按内容用途分类

CoALA 与 LangGraph 的记忆文档使用了接近认知科学的分类。CoALA、LangGraph Memory Overview

类型
保存内容
Agent 示例
常见表示
Semantic 语义记忆
事实与概念
用户偏好、项目约束
profile、事实集合、知识图谱
Episodic 情景记忆
经历与行动轨迹
一次成功排障过程
事件、案例、session log
Procedural 程序记忆
做事规则
编码规范、部署步骤
prompt、Skill、policy、代码
Prospective 前瞻状态
未来要完成的事
deadline、回访、目标
task、goal、scheduler

语义记忆回答已知什么,情景记忆回答以前发生过什么,程序记忆回答应该怎样做。

一次成功轨迹不能直接晋升为程序记忆。它可能只是偶然成功。更稳妥的流程是:

IN / TEXT
episode  → reflection candidate  → test / evaluator / human review  → validated procedure  → Skill or policy

Reflexion 展示了如何用语言反思改进下一次尝试;工程系统还需要为反思增加验证和版本管理。Reflexion

前瞻信息有明确的触发时间和完成状态,更适合 task 或 scheduler。把周五复查迁移结果只存成一条自然语言事实,系统不会因此在周五自动执行。

IN / SIGNAL 07

7. Agent Memory 的分层存储设计

短期、中期和长期记忆在读取频率、数据形态和一致性要求上差异很大。生产系统通常把它们放入不同的数据平面。

7.1 短期记忆存什么

短期记忆是当前模型调用直接使用的工作集,通常包括:

  • 当前用户请求;
  • 最近若干轮消息;
  • 模型尚未消费的 Tool Result;
  • 当前目标和必要计划;
  • 本轮检索出的少量外部知识与长期记忆;
  • system policy 与可用工具说明。

它位于 context window 中,读取不需要额外 Tool Call。代价是每次推理都会重复发送,并受到模型上下文上限约束。

短期层追求高相关和立即可用。大型日志、完整 transcript、全部用户历史都不适合常驻。

7.2 中期记忆存什么

中期记忆覆盖一个 session 或长任务,负责中断恢复和跨多次模型调用的连续性。典型内容包括:

  • 完整或增量消息历史;
  • compaction summary;
  • 当前计划与 active goal;
  • todo 和任务依赖;
  • 权限规则与已激活工具;
  • 后台任务状态和最终结果;
  • checkpoint、interrupt 和恢复元数据;
  • 指向大型 Tool Result 与 artifact 的路径。

这类数据适合进入 StateStore、关系数据库、KV 或 append-only session log。

Session State 与自然语言长期记忆应保持分离。RUNNING 任务需要原子状态更新,权限规则需要确定性判断,不能依赖模型从 MEMORY.md 中自行推断。

7.3 长期记忆存什么

长期层保存跨 session 仍然有用的信息:

  • 用户明确表达的稳定偏好;
  • 项目架构、环境和业务约束;
  • 经过验证的执行经验;
  • 历史事件与重要决定;
  • 可复用的 procedure、example 和 Skill;
  • 记忆来源、有效时间、版本和删除状态。

长期层读取频率低于 context,生命周期更长。它需要支持搜索、更新、归档和用户删除。

7.4 原始轨迹放在哪里

原始 transcript 与长期记忆属于不同数据产品。Transcript 应尽量保留原始 user、assistant、Tool Call 和 Tool Result,用于:

  • 审计一次操作是怎样发生的;
  • 从摘要中找回被省略的细节;
  • 重新运行记忆抽取与索引构建;
  • 训练或评估 retrieval、reflection 和 Skill;
  • 调查记忆投毒与错误写入。

原始轨迹通常写入 JSONL、事件流或对象存储,不默认进入 prompt。

7.5 存储映射

数据层
典型内容
推荐存储
加载方式
主要要求
Context
当前请求、近期消息、检索结果
模型请求内存
每次调用直接输入
token 预算、顺序正确
Session State
摘要、计划、权限、任务
Redis、MySQL、JSON state
按 user/session 恢复
一致性、并发隔离
Transcript
原始消息和工具轨迹
JSONL、对象存储、日志系统
session search、审计
保真、保留策略
Curated Memory
偏好、事实、经验
Markdown、SQL、文档库
常驻摘要或按需读取
版本、来源、更新
Retrieval Index
text/vector/graph 索引
搜索引擎、向量库、图数据库
query、filter、rerank
新鲜度、可重建
Task Repository
task、result、checkpoint
SQL、KV、任务系统
Runtime 自动恢复
状态机、幂等

7.6 后端怎样选择

表示方式
优点
局限
适合场景
Markdown/JSON 文件
透明、可 diff、Agent 易读取
并发和规模有限
coding agent、个人助理
KV/SQL
结构明确、过滤和事务能力好
语义召回需额外索引
profile、状态、事实表
全文检索
精确词与可解释性好
同义表达召回较弱
代码、日志、实体名
向量库
模糊语义召回较强
时间、否定和版本关系较弱
大量非结构化经历
知识图谱
关系与多跳查询强
抽取和维护成本高
人物关系、项目依赖
混合存储
能综合多种信号
系统复杂度较高
生产级长期助手

向量库是 retrieval index 的一种实现。主记录仍然需要明确的 namespace、版本、来源和删除状态。

Mem0 在 LoCoMo 上比较了基础记忆和图记忆,并报告图结构对复杂关系有增益,相比全上下文方案还能减少延迟和 token 成本。这些结果来自作者实验,落地前需要使用业务数据复验。Mem0

A-MEM 借鉴 Zettelkasten,为新记忆生成上下文描述、关键词与标签,并与旧记录建立连接;新信息也可能触发历史记录更新。A-MEM

IN / SIGNAL 08

8. Agent Memory 的写入与加载机制

记忆系统的技术实现可以从一次 Runtime 调用展开。

IN / TEXT
Request arrives  → restore session state  → assemble base context  → retrieve relevant long-term memory  → model reasoning / tool loop  → persist session state and transcript  → extract memory candidates  → consolidate and maintain indexes

8.1 写入发生在什么时候

生产系统常见四个写入入口。

用户显式写入

用户明确说请记住时,可以在请求热路径调用 memory_save。系统应即时校验作用域和敏感信息,并返回保存结果。

这种写法新鲜度最高,也最容易让用户理解。但它会增加当前请求延迟。

回合结束抽取

Agent 返回最终答案后,从本轮 conversation 中抽取持久候选。抽取可以异步执行,避免阻塞主响应。

适合写入隐含偏好、稳定项目事实和本轮新获得的经验。系统需要避免重复抽取同一消息窗口。

Compaction 前 flush

Context compaction 会用摘要替换旧消息。摘要面向当前任务,不一定保留所有跨会话事实。因此在压缩前,可以先从即将被移出的前缀中 flush 长期记忆。

后台 consolidation

后台任务周期性合并新记录与长期视图,处理重复、冲突、过期和容量限制。它还可以归档旧 daily log、清理 session transcript,并重建索引。

LangGraph 将长期记忆写入分为 hot path 与 background 两类。二者在延迟、新鲜度和故障处理上各有取舍。LangGraph Memory Overview

8.2 写入流水线

IN / TEXT
Conversation / Event  → Candidate Extraction  → Scope Classification  → Schema & Security Validation  → Deduplication / Conflict Detection  → Versioning  → Durable Write  → Index Update
对话 / 活动 → 候选提取 → 范围分类 → 模式与安全验证 → 去重/冲突检测 → 版本控制 → 持久化写入 → 索引更新

Candidate Extraction 可以使用 LLM,从自然语言中提取自包含事实。输出只是一组候选。

Scope Classification 判断内容属于 current turn、session、user、project 还是 global。当前任务临时限制不进入跨会话记忆。

Schema & Security Validation 由程序完成,包括字段完整性、namespace 权限、PII 规则、来源存在性和内容长度。

Deduplication 可以使用精确键、文本归一化、embedding 和实体匹配。Conflict Detection 识别同一 subject 与 predicate 下相互矛盾的 value。

Versioning 为记录分配版本、valid time 和 supersedes 关系。

Durable Write 先写权威主存。Index Update 通过 outbox 或异步事件更新全文、向量和图索引。索引应可以从主存重建。

8.3 一个可落地的写入策略

下面的伪代码展示 LLM 与确定性规则的分工:

IN / PYTHON
def write_memories(messages, runtime_context):    candidates = extractor.extract(messages)    accepted = []    for candidate in candidates:        if candidate.scope not in {"user", "project", "global"}:            continue        if not schema_validator.valid(candidate):            continue        if not acl.can_write(runtime_context, candidate.namespace):            continue        if pii_policy.prohibited(candidate.content):            continue        existing = store.find_subject(candidate.namespace, candidate.subject)        decision = conflict_resolver.resolve(existing, candidate)        if decision.action == "skip":            continue        record = versioner.apply(candidate, decision)        store.put(record)        outbox.publish("memory.updated", record.id)        accepted.append(record)    return accepted

这段流程允许模型做语义判断,但不允许模型自行决定越权写入、删除或提高记忆 authority。

8.4 会话状态怎样加载

新请求到达后,Runtime 先根据 (userId, sessionId) 加载 Session State。典型顺序如下:

IN / TEXT
resolve user + tenant + session  → acquire per-session gate  → load AgentState / checkpoint  → restore messages + summary  → restore plan + task + permission state  → attach state to RuntimeContext

解析用户+租户+会话→ 获取会话级门控→ 加载 AgentState / 检查点→ 恢复消息 + 摘要→ 恢复计划 + 任务 + 权限状态→ 将状态附加到 RuntimeContext

同一个 session 的并发请求需要串行化或使用乐观锁,防止两个调用基于相同旧状态分别写回,造成消息和任务状态丢失。

原始 transcript 不默认整份加载。Runtime 可以根据 session ID 查询最近消息,或在模型主动调用 session_search 时读取相关片段。

8.5 长期记忆怎样加载

长期记忆的读取通常分成六步:

IN / TEXT
Current Request  → Query / Entity / Time Extraction  → Namespace & Permission Filter  → Keyword / Vector / Graph Retrieval  → Deduplication & Rerank  → Token-budget Packing  → Context Injection

当前请求→ 查询/实体/时间提取→ 命名空间与权限过滤器→ 关键词/向量/图谱检索→ 去重与重排序→ Token 预算打包→ 上下文注入

Query Extraction 从当前请求和最近几轮对话中提取查询词、实体与时间范围。类似那次故障是怎么解决的查询,需要同时识别故障实体和历史时间。

Namespace Filter 在检索前限制 tenant、user、project 和 agent 范围。这是数据访问边界。

Retrieval 可以并行执行关键词、BM25、向量和图查询。最近 session、活跃 task 和用户 profile 也可以作为独立召回源。

Rerank 综合多个信号:

IN / TEXT
rank_score =  α × semantic_relevance+ β × keyword_relevance+ γ × recency_decay+ δ × importance+ ε × source_authority+ ζ × task_state_match- η × contradiction_penalty- θ × staleness_penalty

Token-budget Packing 根据输入预算选择最终记录。它应优先保留当前请求、system policy、未消费 Tool Result,再为长期记忆分配剩余预算。

Context Injection 为每条记忆添加来源和时间,并声明这些内容是 reference data。当前用户请求与系统策略具有更高优先级。

8.6 常驻加载与按需加载

规模较小的 user profile 或 curated summary 可以常驻 system prompt,使常用偏好无需每轮调用检索工具。

详细事实、daily log 和 session transcript 更适合按需读取。常见方式包括:

  • Runtime 在模型调用前自动检索并注入;
  • 模型调用 memory_search 搜索候选;
  • 模型使用 memory_get 读取特定文件或行范围;
  • 模型使用 session_search 回查完整轨迹。

自动检索延迟更稳定,模型主动检索更灵活。复杂系统通常同时提供两种方式。

8.7 冲突记忆怎样进入上下文

系统发现同一用户的两条偏好互相冲突时,可以:

  • 根据 valid time 选择当前有效版本;
  • 根据 source authority 选择用户显式陈述;
  • 将冲突记录一起交给模型并标注不确定性;
  • 对高风险场景询问用户;
  • 低于可信阈值时不注入。

检索阶段需要支持 abstention。错误记忆常常比没有记忆更危险。

8.8 learn-claude-code:最小写入与加载闭环

s09_memory/code.py 使用 .memory/MEMORY.md 作为目录,每条记忆保存在独立 Markdown 文件中。类型包括 userfeedbackproject 和 reference

should_store_memory() 对候选执行持久性检查:

  • scope == persistent
  • 类型属于允许集合;
  • name、description 和 body 完整;
  • 不包含当前会话、当前任务、暂时等临时语义;
  • 与已有名称、描述或正文不重复。

对应源码为 s09_memory/code.py:108-139

加载采用目录选择与正文读取两步。select_relevant_memories() 读取最近 3 条用户消息,让轻量模型从目录中最多选择 5 条记录;调用失败时退化为关键词匹配。load_memories() 再读取正文,总召回量限制为 20,000 字符。对应源码为 s09_memory/code.py:253-329

当 Agent 停止工具调用后,extract_memories() 从最近消息抽取候选。记忆达到 10 条后,consolidate_memories() 合并重复和过期信息,最多保留 30 条。替换失败时,代码使用快照恢复旧文件。对应源码为 s09_memory/code.py:386-537, 720-747

这套实现没有分布式锁、版本、时间有效性和租户隔离,但完整展示了 select、load、extract、filter 和 consolidate。

8.9 AgentScope Java:生产 Runtime 中的记忆

AgentScope Java 2.0 将会话状态和工作区长期文件放在两个数据平面:

IN / TEXT
AgentStateStore└── (userId, sessionId)    ├── conversation context    ├── compaction summary    ├── permissions    ├── plan state    ├── todo/task context    └── tool contextWorkspace / distributed filesystem├── MEMORY.md                    # 整理后的长期记忆├── memory/YYYY-MM-DD.md         # 追加式每日账本├── agents/.../sessions/*.jsonl  # 原始会话轨迹├── agents/.../tasks/*.json      # 子任务状态/结果└── large_tool_results/...       # 被卸载的大输出

AgentState 按 (userId, sessionId) 加载和保存。相同会话的并发调用通过 per-session gate 串行,不同会话可以并行。完整生命周期见 docs/v2/en/docs/building-blocks/context.md:33-78, 150-165, 232-268

长期记忆采用两层结构。MemoryFlushManager 将新事实追加到 memory/YYYY-MM-DD.mdMemoryConsolidator 读取水位线之后发生变化的 daily files,与当前 MEMORY.md 合并、去重、更新和裁剪,成功后推进 watermark。

默认情况下,MemoryFlushMiddleware 会在每次 call() 结束后触发 flush,也可以配置为 NEVER 或按时间间隔 THROTTLED。Compaction 前和上下文溢出恢复时仍有各自的 flush 入口。Per-call flush 与 transcript offload 在响应流结束后异步运行,不阻塞主调用返回。

读取侧提供 memory_searchmemory_getmemory_save 和 session_search。当前 MemorySearchTool 实现的是大小写不敏感的关键词扫描,并未使用 embedding。

AgentScope core 中旧的 MemoryInMemoryMemory 和 LongTermMemory 在 2.0 已标记废弃。新代码的会话上下文位于 AgentState.getContext(),跨会话记忆由 Harness 工作区管线或应用层实现。版本边界见 Memory.java:22-37LongTermMemory.java:64-70 和 context.md:208-210

IN / SIGNAL 09

9. 工程实践中的边界与风险

9.1 Compaction 与长期记忆

Compaction 处理 context depth:旧对话前缀被摘要,最近尾部保持原文。Tool Result eviction 处理 context width:单条大结果写入文件,context 中只保留预览和路径。

learn-claude-code s08 把超过 30,000 字符的 Tool Result 写入 .task_outputs/tool-results/。已经被模型消费的旧结果可以缩成文件指针,模型尚未读取的新结果受到保护。相关源码为 s08_context_compact/code.py:288-379, 412-456

AgentScope 默认 eviction 阈值是 80,000 字符,保留首尾各约 2,000 字符,完整结果写入 large_tool_results/execute 没有排除在 eviction 外,因为 shell 输出可能很大。源码见 ToolResultEvictionConfig.java:20-74

Compaction summary 服务于当前任务,长期 memory 服务于跨会话复用。压缩前 flush 可以把即将离开 context 的长期事实先写入 memory。

9.2 工具调用边界不能被切断

Assistant Tool Call 与后续 Tool Result 通过 ID 配对。Compaction 如果从两者中间切开,模型 API 可能拒绝请求,模型也可能看到孤立结果。

安全切点需要识别连续 Tool Result,并向前找到发出对应 Tool Call 的 assistant message。AgentScope 的 ConversationCompactor.findSafeCutoffPoint() 采用了这类处理。

9.3 任务状态独立于自然语言记忆

Plan、todo、permission、active goal 和 background task 具有各自状态机。它们应独立持久化,并在 session 恢复时加载。

AgentScope 的 compaction 只修改 conversation list,不处理 Plan Mode、todo、权限和后台子任务。后台结果会在下一次 reasoning 前通过 system reminder 推回父 Agent,任务记录本身保存在独立 repository。

9.4 并发写入与整理

并发问题主要出现在三个位置:

  • 同一 session 的两个请求同时修改 AgentState;
  • 多个 Writer 重复处理相同消息窗口;
  • 多个 Consolidator 同时重写 curated memory。

常见控制方式包括 per-session gate、idempotency key、乐观版本、CAS、watermark、分布式锁和 append-only event log。

Consolidation 只有在新视图成功持久化后才能推进 watermark。失败时保留旧视图和待处理事件,下一次继续重试。

9.5 多 Agent 记忆作用域

范围
适合保存的内容
写入策略
Agent Private
局部尝试、专家工作记录
子 Agent 自主管理
Parent Session
当前计划、依赖、子任务结果
Runtime 管理
User
用户偏好、跨会话事实
用户或受控 Writer
Project / Team
架构决定、运行手册、验证经验
Curator 或审核晋升
Global
通用策略与公共 Skill
高门槛发布流程

子 Agent 通常拥有独立 context,只把结论、证据和 artifact 返回父 Agent。共享范围越大,错误记忆的影响面越大,写入门槛也应提高。

AgentScope 的 ISOLATED workspace 为子 Agent 提供独立空间;SHARED 模式直接使用父 workspace。persistSession(true) 才会根据 (parentSessionId, agentId, label) 复用子 Agent 历史。相关说明见 docs/v2/en/docs/harness/subagent.md:99-105, 192-205

团队级长期记忆可以采用晋升流程:

IN / TEXT
Subagent observation  → candidate artifact  → evidence verification  → parent / curator review  → project memory

9.6 Memory Poisoning

长期记忆会让一次恶意输入跨 session 存活。网页或工具结果中的注入指令可能诱导 Writer 保存伪造事实,未来又被 Retriever 召回。

2026 年的预印本研究了 sleeper memory poisoning 和来源洗白:外部内容经过总结、可信工具回显或伪造佐证后,可能获得更高的表面可信度。这些结论仍需持续复核,但攻击链可以直接用于系统测试。Hidden in Memory、Securing LLM-Agent Long-Term Memory Against Poisoning

基础防线包括:

  • 在写入时绑定不可丢失的来源;
  • 用户陈述、可信工具和网页内容使用不同 authority;
  • 召回文本明确标记为 reference data;
  • 记忆内容不能自动获得 Tool 权限;
  • 授权过滤采用 fail closed;
  • 高风险动作重新检查当前授权;
  • 记录 write、retrieve、inject 和 act 的完整链路。

9.7 隐私与删除

记忆系统保存的是长期用户数据,需要支持查询、导出、更正和删除。删除流程应覆盖:

IN / TEXT
authoritative store  → text index  → vector index  → graph edges  → cache  → derived profile / summary
→ 文本索引 → 向量索引 → 图 → 缓存 → 派生配置文件 / 摘要

备份和审计数据的处理取决于组织政策和法规要求。系统需要明确 retention、加密、访问日志和管理员权限。

9.8 如何评测

只评最终回答,无法判断错误发生在写入还是检索。评测可以分四层:

问题
指标示例
写入
该保存的是否写入,不该保存的是否挡住
precision、recall、PII leakage
整理
更新、冲突、过期是否正确
update accuracy、stale rate、consolidation loss
检索
相关记忆能否在预算内取回
Recall@k、MRR、nDCG、abstention F1
下游
记忆是否改善任务
answer accuracy、task success、latency、token cost

LoCoMo 的对话最长约 35 个 session,平均 300 turns,评测问答、事件总结和多模态长对话。LoCoMo

LongMemEval 包含 500 个问题,覆盖信息抽取、多 session 推理、时间推理、知识更新和 abstention。LongMemEval

业务评测还应加入事实纠正、删除请求、跨租户访问、工具轨迹、后台任务恢复和 memory poisoning。基线至少包括无记忆、全量历史、滚动摘要、关键词、向量与混合检索。

IN / SIGNAL 10

10. 总结

Agent Memory 是 Runtime 中的信息生命周期管理能力。它持续回答六个工程问题:

  1. 哪些信息值得保存;
  2. 信息属于 turn、session、user、project 还是 global;
  3. 何时同步写入,何时异步抽取或 consolidation;
  4. 当前请求应该加载哪些记录;
  5. 新旧事实冲突时如何更新、降权或失效;
  6. 哪个用户或 Agent 有权读取和修改。

短期记忆位于 context,负责当前推理。中期记忆位于 StateStore、checkpoint 和 session log,负责会话与任务恢复。长期记忆位于 curated store 与检索索引,负责跨 session 的事实、偏好和经验复用。

写入链路需要 LLM 与确定性程序配合:模型理解语义,程序控制 scope、schema、权限、PII、幂等与版本。加载链路先做 namespace 过滤,再执行多路召回、重排和 token packing,最终以带来源的参考数据进入 context。

learn-claude-code 展示了这套机制的最小闭环:文件存储、目录选择、持久性过滤、抽取和 consolidation。AgentScope Java 则补上了 AgentState、双层长期记忆、compaction、session transcript、并发隔离、分布式 watermark 和 Agent-controlled memory tools。

当 Agent 开始长期运行并参与真实业务后,Memory 的质量还取决于来源、时间、权限、状态恢复、冲突处理、删除能力和安全审计。它们共同决定一条旧信息能否被可靠地用于今天的行动。

IN / SIGNAL 11

参考资料

  1. MemGPT: Towards LLMs as Operating Systems
  2. Generative Agents: Interactive Simulacra of Human Behavior
  3. Reflexion: Language Agents with Verbal Reinforcement Learning
  4. Cognitive Architectures for Language Agents (CoALA)
  5. A Survey on the Memory Mechanism of Large Language Model based Agents
  6. Evaluating Very Long-Term Conversational Memory of LLM Agents (LoCoMo)
  7. LongMemEval: Benchmarking Chat Assistants on Long-Term Interactive Memory
  8. Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory
  9. A-MEM: Agentic Memory for LLM Agents
  10. LangGraph Memory Overview
  11. LangGraph Add Memory
  12. Anthropic: Effective context engineering for AI agents
  13. AgentScope Java GitHub
  14. AgentScope Java Workspace and Memory
  15. Hidden in Memory: Sleeper Memory Poisoning in LLM Agents
  16. Securing LLM-Agent Long-Term Memory Against Poisoning

inShocking

quiet interface / sudden insight

IN / END OF SIGNAL

相关学习资料

返回首页浏览学习资料