这里是附件内容的逐字识别与中文翻译。
#
致谢简介上下文工程会话框架和模型之间的差异多 Agent 系统的会话跨多个 Agent 框架的互操作性会话的生产环境考量管理长上下文对话:权衡与优化记忆记忆的类型信息的类型组织模式存储架构创建机制记忆范围多模态记忆记忆生成:提取与整合深入探讨:记忆提取深入探讨:记忆整合记忆溯源在记忆管理期间考量记忆谱系在推理期间考量记忆谱系触发记忆生成记忆作为工具后台操作与阻塞操作记忆检索检索时机基于记忆的推理系统指令中的记忆对话历史中的记忆程序性记忆测试与评估记忆的生产环境考量隐私与安全风险结论
作者: Kimberly Milam 和 Antonio Gulli
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月
2
致谢
内容贡献者
Kaitlin Ardiff
Shangjie Chen
Yanfei Chen
Derek Egan
Hangfei Lin
Ivan Nardini
Anant Nawalgaria
Kanchana Patlolla
Huang Xia
Jun Yan
Bo Yang
Michael Zimmermann
Shangjie Chen
Yanfei Chen
Derek Egan
Hangfei Lin
Ivan Nardini
Anant Nawalgaria
Kanchana Patlolla
Huang Xia
Jun Yan
Bo Yang
Michael Zimmermann
策划与编辑
Anant Nawalgaria
Kanchana Patlolla
Kanchana Patlolla
设计师
Michael Lanning
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 6
简介
本白皮书探讨了会话(Sessions)和记忆(Memory)在构建有状态、智能 LLM Agent 中的关键作用,旨在赋能开发者创造更强大、更个性化且持久的 AI 体验。为了使大型语言模型(LLMs)能够记忆、学习并个性化交互,开发者必须在其上下文窗口内动态地组装和管理信息——这一过程被称为上下文工程(Context Engineering)。
本白皮书总结了以下核心概念:
- 上下文工程: 在 LLM 的上下文窗口内动态组装和管理信息的过程,以实现有状态的智能 Agent。
- 会话: 与 Agent 进行完整对话的容器,保存着对话的时间顺序历史和 Agent 的工作记忆。
有状态和个性化的 AI 始于上下文工程。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 7
- 记忆: 实现长期持久性的机制,跨多个会话捕获并整合关键信息,从而为 LLM Agent 提供连续且个性化的体验。
上下文工程
LLM 本质上是无状态的。除了训练数据之外,它们的推理和感知仅限于单个 API 调用中“上下文窗口”所提供的信息。这带来了一个根本性的问题,因为 AI Agent 必须配备操作指令以识别可采取的行动、用于推理的证据和事实数据,以及定义当前任务的即时对话信息。为了构建能够记忆、学习和个性化交互的有状态智能 Agent,开发者必须为对话的每一轮构建这种上下文。这种为 LLM 动态组装和管理信息的过程被称为上下文工程。
上下文工程代表了传统提示工程(Prompt Engineering)的演变。提示工程侧重于精心制作最佳的、通常是静态的系统指令。相反,上下文工程处理整个负载(payload),根据用户、对话历史和外部数据动态构建具有状态感知的提示。它涉及策略性地选择、总结和注入不同类型的信息,以在最大化相关性的同时最小化噪音。外部系统——如 RAG 数据库、会话存储和记忆管理器——管理着这其中的大部分上下文。Agent 框架必须编排这些系统,以检索并将上下文组装成最终的提示。
可以将上下文工程视为 Agent 的 mise en place(一切就绪)——这是厨师在烹饪前收集并准备所有食材的关键步骤。如果你只给厨师食谱(即提示),他们可能会利用手头任意的食材做出一顿还可以的饭菜。然而,如果你首先确保他们拥有所有正确、高质量的食材、专用工具,并清楚了解呈现风格,他们就能可靠地制作出卓越的定制化成果。上下文工程的目标是确保模型拥有完成任务所需的最相关信息,既不多也不少。
上下文工程管理着包含多种组件的复杂负载的组装:
- 指导推理的上下文定义了 Agent 的基本推理模式和可用动作,支配着其行为:
- 系统指令: 定义 Agent 人设、能力和约束的高级指令。
- 工具定义: Agent 可用于与外部世界交互的 API 或函数的架构。
- 少样本示例: 通过上下文学习指导模型推理过程的精选示例。
- 证据与事实数据是 Agent 进行推理的实质性数据,包括预先存在的知识和为特定任务动态检索的信息;它是 Agent 回复的“证据”:
- 长期记忆: 跨多个会话收集的关于用户或主题的持久化知识。
- 外部知识: 从数据库或文档中检索的信息,通常使用检索增强生成 (RAG)¹。
- 工具输出: 工具返回的数据或结果。
- 子 Agent 输出: 被委派特定子任务的专用 Agent 返回的结论或结果。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 9
- 工件: 与用户或会话相关的非文本数据(例如文件、图像)。
- 即时对话信息将 Agent 建立在当前的交互中,定义即时任务:
- 对话历史: 当前交互的逐轮记录。
- 状态 / 草稿本: Agent 用于其即时推理过程的临时、进行中的信息或计算。
- 用户的提示: 需要解决的即时查询。
上下文的动态构建至关重要。例如,记忆不是静态的;必须随着用户与 Agent 的交互或新数据的摄入,有选择地检索和更新它们。此外,有效的推理通常依赖于上下文学习²(LLM 从提示中的演示中学习如何执行任务的过程)。当 Agent 使用与当前任务相关的少样本示例,而不是依赖硬编码的示例时,上下文学习会更有效。同样,外部知识是由 RAG 工具根据用户的即时查询检索的。
构建上下文感知 Agent 最关键的挑战之一是管理不断增长的对话历史。理论上,具有大上下文窗口的模型可以处理大量的记录;实际上,随着上下文的增加,成本和延迟也会增加。此外,模型可能会遭遇“上下文腐烂(context rot)”,即随着上下文的增加,它们关注关键信息的能力会减弱。上下文工程通过采用动态改变历史的策略——例如摘要、选择性修剪或其他压缩技术——来直接解决这个问题,以在管理总 Token 数量的同时保留重要信息,最终带来更健壮和个性化的 AI 体验。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 10
这种实践体现为 Agent 在对话每一轮的操作循环中的一个连续周期:
图 1. Agent 的上下文管理流程
(图表描述:用户查询 -> 获取上下文 -> 准备上下文 -> Agent -> 调用 LLM + 工具 -> 上传上下文(事件)-> 上下文存储。响应 -> 用户。注:特定箭头表示流程和异步操作。)
- 获取上下文: Agent 首先检索上下文——例如用户记忆、RAG 文档和最近的对话事件。对于动态上下文检索,Agent 将使用用户查询和其他元数据来识别要检索的信息。
- 准备上下文: Agent 框架动态构建用于 LLM 调用的完整提示。虽然单个 API 调用可能是异步的,但准备上下文是一个阻塞的、“热路径(hot-path)”过程。在上下文准备好之前,Agent 无法继续。
- 调用 LLM 和工具: Agent 迭代调用 LLM 和任何必要的工具,直到生成给用户的最终响应。工具和模型输出被追加到上下文中。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 11
- 上传上下文: 在该轮次中收集的新信息被上传到持久存储。这通常是一个“后台”过程,允许 Agent 完成执行,而记忆整合或其他后处理异步发生。
这个生命周期的核心是两个基本组件:会话和记忆。会话管理单个对话的逐轮状态。相比之下,记忆提供了长期持久性的机制,跨多个会话捕获并整合关键信息。
你可以把会话想象成你为特定项目使用的工作台或桌子。当你工作时,上面摆满了所有必要的工具、笔记和参考资料。所有东西都触手可及,但也是临时的,并且特定于手头的任务。一旦项目完成,你不会把整个杂乱的桌子塞进仓库。相反,你开始创建记忆的过程,这就像一个有组织的档案柜。你审查桌上的材料,丢弃草稿和多余的笔记,只将最关键、最终定稿的文件归档到贴有标签的文件夹中。这确保了档案柜对于所有未来的项目来说是一个整洁、可靠且高效的真实信息来源,而不会被工作台上短暂的混乱所填满。这个类比直接反映了一个高效 Agent 的运作方式:会话充当单个对话的临时工作台,而 Agent 的记忆则是精心组织的档案柜,使其能够在未来的交互中回忆起关键信息。
基于这个上下文工程的高级概览,我们现在可以探索两个核心组件:会话和记忆,首先从会话开始。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 12
会话
上下文工程的一个基础元素是会话,它封装了单个连续对话的即时对话历史和工作记忆。每个会话都是一个独立的记录,绑定到特定用户。会话允许 Agent 在单个对话的范围内保持上下文并提供连贯的回复。一个用户可以有多个会话,但每个会话都作为一个特定交互的独特、不相连的日志运行。每个会话包含两个关键组件:按时间顺序的历史(事件)和 Agent 的工作记忆(状态)。
事件是对话的构建块。常见的事件类型包括:用户输入(来自用户的消息(文本、音频、图像等))、Agent 响应(Agent 对用户的回复)、工具调用(Agent 使用外部工具或 API 的决定)或工具输出(从工具调用返回的数据,Agent 使用它来继续其推理)。
除了聊天历史之外,会话通常还包含一个状态——一种结构化的“工作记忆”或草稿本。这保存了与当前对话相关的临时、结构化数据,例如购物车里有哪些物品。
随着对话的进行,Agent 将向会话追加额外的事件。此外,它可能会根据 Agent 中的逻辑改变状态。
事件的结构类似于传递给 Gemini API 的
Content 对象列表,其中每个具有 role 和 parts 的项目代表对话中的一轮——或一个事件。Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 13
# Python contents = [ { "role": "user", "parts": [ {"text": "What is the capital of France?"} ] }, { "role": "model", "parts": [ {"text": "The capital of France is Paris."} ] } ] response = client.models.generate_content( model="gemini-2.5-flash", contents=contents )
生产环境 Agent 的执行环境通常是无状态的,这意味着它在请求完成后不保留任何信息。因此,必须将其对话历史保存到持久存储中,以维持连续的用户体验。虽然内存存储适用于开发,但生产应用程序应利用健壮的数据库来可靠地存储和管理会话。例如,您可以将对话历史存储在像 Agent Engine Sessions³ 这样的托管解决方案中。
框架和模型之间的差异
虽然核心理念相似,但不同的 Agent 框架以不同的方式实现会话、事件和状态。Agent 框架负责维护 LLM 的对话历史和状态,使用该上下文构建 LLM 请求,并解析和存储 LLM 的响应。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 14
Agent 框架充当代码和 LLM 之间的通用翻译器。当你(开发者)使用框架一致的内部数据结构处理每个对话轮次时,框架负责将这些结构转换为 LLM 所需的精确格式这一关键任务。这种抽象非常强大,因为它将你的 Agent 逻辑与你使用的特定 LLM 解耦,从而防止供应商锁定。
图 2:Agent 的上下文管理流程
(图表描述:用户查询 <-> Agent 框架 <-> 模型。Agent 框架还连接到会话存储、记忆管理器和其他数据源。箭头表示翻译层。)
最终,目标是生成一个 LLM 能够理解的“请求”。对于 Google 的 Gemini 模型,这是一个
List[Content]。每个 Content 对象是一个简单的类似字典的结构,包含两个键:role 定义谁在说话(“user” 或 “model”),parts 定义消息的实际内容(文本、图像、工具调用等)。框架在进行 API 调用之前,会自动处理从其内部对象(例如 ADK
Event)到 Content 对象中相应 role 和 parts 的数据映射。本质上,框架为开发者提供了一个稳定的内部 API,同时在幕后管理不同 LLM 复杂多变的外部 API。Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 15
ADK 使用一个显式的
Session 对象,其中包含 Event 对象列表和一个单独的状态对象。Session 就像一个档案柜,一个文件夹用于对话历史(事件),另一个用于工作记忆(状态)。LangGraph 没有正式的“会话”对象。相反,状态就是会话。这个包罗万象的状态对象保存对话历史(作为
Message 对象列表)和所有其他工作数据。与传统会话的仅追加日志不同,LangGraph 的状态是可变的。它可以被转换,并且像历史压缩这样的策略可以更改记录。这对于管理长对话和 Token 限制非常有用。多 Agent 系统的会话
在多 Agent 系统中,多个 Agent 协同工作。每个 Agent 专注于一个较小的、专门的任务。为了使这些 Agent 有效协作,它们必须共享信息。如下图所示,系统的架构定义了它们用于共享信息的通信模式。该架构的一个核心组件是系统如何处理会话历史——即所有交互的持久日志。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 16
图 3:不同的多 Agent 架构模式³⁰
(图表描述:展示单 Agent、网络、主管模式的矩阵。还有主管(作为工具)、分层、自定义模式。)
在探索管理此历史记录的架构模式之前,将其与发送给 LLM 的上下文区分开来至关重要。将会话历史视为整个对话的永久、未删节的文字记录。另一方面,上下文是为单个轮次发送给 LLM 的精心制作的信息负载。Agent 可能会通过仅选择历史记录中的相关摘录,或添加特殊格式(如引导性前言)来构建此上下文,以引导模型的响应。本节重点介绍在 Agent 之间传递的信息,而不一定是发送给 LLM 的上下文。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 17
Agent 框架使用两种主要方法之一来处理多 Agent 系统的会话历史:共享、统一的历史,即所有 Agent 向单个日志做出贡献;或者分离、独立的历史,即每个 Agent 维护自己的视角⁴。这两种模式之间的选择取决于任务的性质和 Agent 之间期望的协作方式。
对于共享、统一的历史模型,系统中的所有 Agent 都读取并写入所有事件到同一个、单一的对话历史中。每个 Agent 的消息、工具调用和观察结果都按时间顺序追加到一个中央日志中。这种方法最适合需要单一真实来源的紧密耦合、协作任务,例如多步骤问题解决过程,其中一个 Agent 的输出直接是下一个 Agent 的输入。即使有共享历史,子 Agent 也可能在将日志传递给 LLM 之前对其进行处理。例如,它可以过滤相关的事件子集,或添加标签以标识哪个 Agent 生成了每个事件。
如果你使用 ADK 的 LLM 驱动委托来移交给子 Agent,子 Agent 的所有中间事件都将写入与根 Agent 相同的会话⁵:
# Python from google.adk.agents import LlmAgent # 子 Agent 可以访问 Session 并向其写入事件。 sub_agent_1 = LlmAgent(...) # 可选地,子 Agent 可以将最终响应文本(或结构化输出)保存到指定的状态键。 sub_agent_2 = LlmAgent( ..., output_key="...")
(下页继续…)
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 18
# 父 Agent。 root_agent = LlmAgent( ..., sub_agents=[sub_agent_1, sub_agent_2] )
片段 2:跨多个 Agent 框架的 A2A 通信
在分离、独立的历史模型中,每个 Agent 维护自己私有的对话历史,并对其他 Agent 充当黑盒。所有内部过程——如中间想法、工具使用和推理步骤——都保存在 Agent 的私有日志中,对其他 Agent 不可见。通信仅通过显式消息发生,Agent 分享其最终输出,而不是过程。
这种交互通常通过实现 Agent-as-a-Tool(将 Agent 作为工具)或使用 Agent-to-Agent (A2A) 协议来实现。使用 Agent-as-a-Tool,一个 Agent 像调用标准工具一样调用另一个 Agent,传递输入并接收最终的、自包含的输出⁶。使用 Agent-to-Agent (A2A) 协议,Agent 使用结构化协议进行直接消息传递⁷。
我们将在下一节更详细地探讨 A2A 协议。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 19
跨多个 Agent 框架的互操作性
图 4:使用不同框架的多个 Agent 之间的 A2A 通信
(图表描述:两个 Agent(基于 ADK 和基于 LangGraph)通过 A2A 协议进行通信。它们拥有独立的会话存储,但通过 MCP 连接。)
框架对内部数据表示的使用为多 Agent 系统引入了一个关键的架构权衡:将 Agent 与 LLM 解耦的抽象,同时也将其与使用其他 Agent 框架的 Agent 隔离开来。这种隔离在持久层被固化。
Session 的存储模型通常将数据库模式直接耦合到框架的内部对象,从而创建了一个僵化的、相对不可移植的对话记录。因此,用 LangGraph 构建的 Agent 无法原生解释由基于 ADK 的 Agent 持久化的独特的 Session 和 Event 对象,从而使无缝的任务移交变得不可能。Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 20
一种协调这些隔离 Agent 之间协作的新兴架构模式是 Agent-to-Agent (A2A) 通信⁸。虽然这种模式使 Agent 能够交换消息,但它未能解决共享丰富上下文状态的核心问题。每个 Agent 的对话历史都编码在其框架的内部模式中。因此,任何包含会话事件的 A2A 消息都需要一个翻译层才有用。
一种更健壮的互操作性架构模式涉及将共享知识抽象为与框架无关的数据层,例如记忆(Memory)。与保存原始的、特定于框架的对象(如
Events 和 Messsages)的 Session 存储不同,记忆层旨在保存处理过的、规范的信息。关键信息——如摘要、提取的实体和事实——是从对话中提取出来的,通常存储为字符串或字典。记忆层的数据结构不与任何单一框架的内部数据表示耦合,这使其能够充当通用的公共数据层。这种模式允许异构 Agent 通过共享公共认知资源来实现真正的协作智能,而无需自定义翻译器。会话的生产环境考量
当将 Agent 迁移到生产环境时,其会话管理系统必须从简单的日志演变为健壮的企业级服务。关键考量分为三个关键领域:安全与隐私、数据完整性和性能。像 Agent Engine Sessions 这样的托管会话存储是专门为满足这些生产要求而设计的。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 21
安全与隐私
保护会话中包含的敏感信息是一项不可协商的要求。严格隔离是最关键的安全原则。会话归单个用户所有,系统必须实施严格隔离,以确保一个用户永远无法访问另一个用户的会话数据(即通过 ACL)。对会话存储的每个请求都必须经过针对会话所有者的身份验证和授权。
处理个人身份信息 (PII) 的最佳实践是在会话数据写入存储之前对其进行编辑(redact)。这是一项基本的安全措施,可大幅降低潜在数据泄露的风险和“爆炸半径”。通过使用像 Model Armor⁹ 这样的工具确保敏感数据永不持久化,您可以简化对 GDPR 和 CCPA 等隐私法规的遵守,并建立用户信任。
数据完整性和生命周期管理
生产系统需要明确的规则来规定会话数据如何存储和随时间维护。会话不应永远存在。您可以实施生存时间 (TTL) 策略来自动删除不活跃的会话,以管理存储成本并减少数据管理开销。这需要明确的数据保留策略,定义会话在归档或永久删除之前应保留多长时间。
此外,系统必须保证操作按确定性顺序追加到会话历史中。保持事件的正确时间顺序对于对话日志的完整性至关重要。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 22
性能和可扩展性
会话数据位于每个用户交互的“热路径”上,使其性能成为首要关注点。读取和写入会话历史必须非常快,以确保响应迅速的用户体验。Agent 运行时通常是无状态的,因此在每一轮开始时都会从中央数据库检索整个会话历史,从而产生网络传输延迟。
为了减轻延迟,减少传输的数据量至关重要。一个关键的优化是在将数据发送给 Agent 之前过滤或压缩会话历史。例如,您可以删除当前对话状态不再需要的旧的、不相关的函数调用输出。下一节详细介绍了多种压缩历史记录的策略,以有效地管理长上下文对话。
管理长上下文对话:权衡与优化
在简单的架构中,会话是用户和 Agent 之间对话的不可变日志。然而,随着对话规模的扩大,对话的 Token 使用量也会增加。现代 LLM 可以处理长上下文,但也存在局限性,特别是对于延迟敏感型应用程序¹⁰:
- 上下文窗口限制: 每个 LLM 都有一次可以处理的最大文本量(上下文窗口)。如果对话历史超过此限制,API 调用将失败。
- API 成本: 大多数 LLM 提供商根据您发送和接收的 Token 数量收费。较短的历史记录意味着每轮更少的 Token 和更低的成本。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 23
- 延迟(速度): 向模型发送更多文本需要更长的时间来处理,导致用户的响应时间变慢。压缩使 Agent 感觉快速且响应灵敏。
- 质量: 随着 Token 数量的增加,由于上下文中的额外噪音和自回归错误,性能可能会变差。
管理与 Agent 的长对话可以比作一个精明的旅行者为长途旅行打包行李箱。行李箱代表 Agent 有限的上下文窗口,而衣服和物品是来自对话的信息片段。如果你只是试图把所有东西塞进去,行李箱会变得太重且杂乱无章,难以快速找到你需要的东西——就像过载的上下文窗口会增加处理成本并降低响应时间一样。另一方面,如果你装得太少,你可能会冒着遗漏护照或保暖外套等必需品的风险,从而危及整个旅程——就像 Agent 可能会丢失关键上下文,导致不相关或不正确的答案。旅行者和 Agent 都在类似的约束下运作:成功不取决于你能带多少,而取决于只带你需要的东西。
压缩策略缩小了长对话历史,将对话浓缩以适应模型的上下文窗口,从而降低 API 成本和延迟。随着对话变长,每一轮发送给模型的历史可能会变得太大。压缩策略通过智能地修剪历史记录,同时尝试保留最重要的上下文来解决这个问题。
那么,你怎么知道从会话中丢弃什么内容而不丢失有价值的信息呢?策略范围从简单的截断到复杂的压缩:
- 保留最近 N 轮: 这是最简单的策略。Agent 只保留对话的最近 N 轮(“滑动窗口”)并丢弃所有更旧的内容。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 24
- 基于 Token 的截断: 在将历史记录发送给模型之前,Agent 计算消息中的 Token,从最近的开始向后推算。它在不超过预定义 Token 限制(例如 4000 个 Token)的情况下包含尽可能多的消息。所有更旧的内容都被直接切断。
- 递归摘要: 对话的较旧部分被 AI 生成的摘要替换。随着对话的增长,Agent 定期使用另一个 LLM 调用来总结最旧的消息。此摘要随后被用作历史的浓缩形式,通常作为前缀添加到较新的逐字消息之前。
例如,您可以使用 ADK 保留最近 N 轮,方法是为您的 ADK 应用程序使用内置插件来限制发送给模型的上下文。这不会修改存储在会话存储中的历史事件:
片段 3:使用 ADK 进行会话截断,仅使用最近 N 轮
# Python from google.adk.apps import App from google.adk.plugins.context_filter_plugin import ContextFilterPlugin app = App( name='hello_world_app', root_agent=agent, plugins=[ # 保留最近 10 轮和最新的用户查询。 ContextFilterPlugin(num_invocations_to_keep=10), ], )
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 25
鉴于复杂的压缩策略旨在降低成本和延迟,在后台异步执行昂贵的操作(如递归摘要)并持久化结果至关重要。“在后台”确保客户端不需要等待,而“持久化”确保昂贵的计算不会被过度重复。通常,Agent 的记忆管理器负责生成和持久化这些递归摘要。Agent 还必须记录哪些事件包含在压缩摘要中;这可以防止原始的、更冗长的事件被不必要地发送给 LLM。
此外,Agent 必须决定何时需要压缩。触发机制通常分为几个不同的类别:
- 基于计数的触发器(即 Token 大小或轮次计数阈值):一旦对话超过某个预定义的阈值,就会压缩对话。这种方法对于管理上下文长度通常是“足够好”的。
- 基于时间的触发器: 压缩不是由对话的大小触发,而是由缺乏活动触发。如果用户停止交互一段时间(例如 15 或 30 分钟),系统可以在后台运行压缩作业。
- 基于事件的触发器(即语义/任务完成):当 Agent 检测到特定任务、子目标或对话主题已结束时,决定触发压缩。
例如,您可以使用 ADK 的
EventsCompactionConfig 在配置的轮次数量后触发基于 LLM 的摘要:Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 26
片段 4:使用 ADK 进行摘要式会话压缩
记忆生成是从冗长且嘈杂的数据源中提取持久知识的广泛能力。在本节中,我们涵盖了从对话历史中提取信息的一个主要示例:会话压缩。压缩提炼了整个对话的逐字记录,提取关键事实和摘要,同时丢弃对话填充物。
基于压缩,下一节将更广泛地探索记忆生成和管理。我们将讨论创建、存储和检索记忆的各种方式,以构建 Agent 的长期知识。
# Python from google.adk.apps import App from google.adk.apps.app import EventsCompactionConfig app = App( name='hello_world_app', root_agent=agent, events_compaction_config=EventsCompactionConfig( compaction_interval=5, overlap_size=1, ), )
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 27
记忆
记忆和会话有着深刻的共生关系:会话是生成记忆的主要数据源,而记忆是管理会话大小的关键策略。记忆是从对话或数据源中提取的、有意义信息的快照。它是一种浓缩的表示,保留了重要的上下文,使其对未来的交互有用。通常,记忆跨会话持久保存,以提供连续和个性化的体验。
作为一个专门的、解耦的服务,“记忆管理器”为多 Agent 互操作性提供了基础。记忆管理器经常使用与框架无关的数据结构,如简单的字符串和字典。这允许基于不同框架构建的 Agent 连接到单个记忆存储,从而能够创建任何连接的 Agent 都可以利用的共享知识库。
注意:某些框架也可能将会话或逐字对话称为“短期记忆”。在本白皮书中,记忆被定义为提取的信息,而不是逐轮对话的原始对话。
存储和检索记忆对于构建复杂和智能的 Agent 至关重要。一个健壮的记忆系统通过解锁几个关键能力,将基本的聊天机器人转变为真正的智能 Agent:
- 个性化: 最常见的用例是记住用户偏好、事实和过去的交互,以定制未来的回复。例如,记住用户最喜欢的运动队或他们在飞机上的首选座位,可以创造更有帮助和个性化的体验。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 28
- 上下文窗口管理: 随着对话变长,完整的历史记录可能会超过 LLM 的上下文窗口。记忆系统可以通过创建摘要或提取关键事实来压缩此历史记录,在保留上下文的同时,无需在每一轮中发送数千个 Token。这降低了成本和延迟。
- 数据挖掘和洞察: 通过分析许多用户的存储记忆(以聚合的、保护隐私的方式),您可以从噪音中提取洞察。例如,一个零售聊天机器人可能会发现许多用户都在询问特定产品的退货政策,从而标记潜在问题。
- Agent 自我改进和适应: Agent 通过创建关于自身表现的程序性记忆从以前的运行中学习——记录哪些策略、工具或推理路径导致了成功的结果。这使得 Agent 能够建立有效解决方案的剧本,使其能够随着时间的推移适应并改进其解决问题的能力。
在 AI 系统中创建、存储和利用记忆是一个协作过程。栈中的每个组件——从最终用户到开发者的代码——都有独特的作用。
- 用户: 为记忆提供原始源数据。在某些系统中,用户可能直接提供记忆(即通过表单)。
- Agent(开发者逻辑): 配置如何决定记住什么和何时记住,编排对记忆管理器的调用。在简单的架构中,开发者可以实现这样的逻辑:记忆总是被检索,并且总是被触发生成。在更高级的架构中,开发者可以实现记忆作为工具(memory-as-a-tool),其中 Agent(通过 LLM)决定何时应该检索或生成记忆。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 29
- Agent 框架(例如 ADK, LangGraph): 提供用于记忆交互的结构和工具。框架充当管道。它定义了开发者的逻辑如何访问对话历史并与记忆管理器交互,但它本身并不管理长期存储。它还定义了如何将检索到的记忆填充到上下文窗口中。
- 会话存储(即 Agent Engine Sessions, Spanner, Redis): 存储会话的逐轮对话。原始对话将被摄入到记忆管理器中以生成记忆。
- 记忆管理器(例如 Agent Engine Memory Bank, Mem0, Zep): 处理记忆的存储、检索和压缩。存储和检索记忆的机制取决于使用的提供商。这是专门的服务或组件,它获取由 Agent 识别的潜在记忆并处理其整个生命周期。
- 提取从源数据中提炼关键信息。
- 整合策划记忆以合并重复的实体。
- 存储将记忆持久化到持久数据库。
- 检索获取相关记忆以为新的交互提供上下文。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 30
图 5:会话、记忆和外部知识之间的信息流
(图表描述:外部知识库(RAG)-> 读取。工具响应 -> Agent。LLM -> 工具。LLM 响应 -> 用户。记忆管理器 -> 读取记忆。会话存储 -> 写入事件。记忆生成的源数据 -> 记忆管理器。创建记忆 -> 记忆管理器。)
责任的分工确保了开发者可以专注于 Agent 的独特逻辑,而无需为记忆持久化和管理构建复杂的底层基础设施。重要的是要认识到,记忆管理器是一个主动系统,而不仅仅是一个被动的向量数据库。虽然它使用相似性搜索进行检索,但其核心价值在于其随着时间的推移智能提取、整合和策划记忆的能力。托管记忆服务,如 Agent Engine Memory Bank,处理记忆生成和存储的整个生命周期,让您腾出精力专注于 Agent 的核心逻辑。
这种检索能力也是记忆经常被拿来与另一个关键架构模式进行比较的原因:检索增强生成 (RAG)。然而,它们建立在不同的架构原则之上,因为 RAG 处理静态的、外部数据,而记忆策划动态的、特定于用户的上下文。它们履行两个独特且互补的角色:RAG 使 Agent 成为事实专家,而记忆使其成为用户专家。下面的图表分解了它们的高级差异:
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 32
表 1:RAG 引擎和记忆管理器的比较
RAG 引擎 | 记忆管理器 | |
主要目标 | 将外部、事实知识注入到上下文中 | 创建个性化和有状态的体验。Agent 记住事实,随时间适应用户,并维护长期运行的上下文。 |
数据源 | 静态、预索引的外部知识库(例如 PDF、维基、文档、API)。 | 用户与 Agent 之间的对话。 |
隔离级别 | 通常共享。 知识库通常是所有用户可访问的全局、只读资源,以确保一致、事实性的答案。 | 高度隔离: 记忆几乎总是按用户划分范围,以防止数据泄露。 |
信息类型 | 静态、事实性和权威性。通常包含特定领域的数据、产品详情或技术文档。 | 动态且(通常)特定于用户。记忆源于对话,因此存在固有的不确定性水平。 |
写入模式 | 批处理,通过离线、管理操作触发。 | 基于事件的处理,按某种节奏触发(即每轮或会话结束时)或记忆作为工具(Agent 决定生成记忆)。 |
读取模式 | RAG 数据几乎总是“作为工具”检索。当 Agent 决定用户的查询需要外部信息时进行检索。 | 有两种常见的读取模式:• 记忆作为工具: 当用户的查询需要关于用户(或其他身份)的额外信息时检索。• 静态检索: 记忆总是在每轮开始时被检索。 |
数据格式 | 自然语言“块”。 | 自然语言片段或结构化档案。 |
数据准备 | 分块和索引: 源文档被分解为较小的块,然后转换为嵌入并存储以供快速查找。 | 提取和整合: 从对话中提取关键细节,确保存储内容不重复或矛盾。 |
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 33
理解这种差异的一个有用方法是将 RAG 视为 Agent 的研究图书管理员,将会话管理器视为其个人助理。
研究图书管理员(RAG)在一个充满百科全书、教科书和官方文件的巨大公共图书馆工作。当 Agent 需要一个既定事实——如产品的技术规格或历史日期——它会咨询图书管理员。图书管理员从这个静态、共享且权威的知识库中检索信息,以提供一致、事实性的答案。图书管理员是世界事实的专家,但他们不知道关于提问用户的任何个人信息。
相比之下,个人助理(记忆)跟随 Agent 并携带一本私人笔记本,记录与特定用户每次交互的细节。这个笔记本是动态且高度隔离的,包含个人偏好、过去的对话和不断演变的目标。当 Agent 需要回忆用户最喜欢的运动队或上周项目讨论的背景时,它会求助于助理。助理的专长不在于全球事实,而在于用户本身。
最终,一个真正智能的 Agent 两者都需要。RAG 为其提供对世界的专业知识,而记忆为其提供对其所服务的用户的专业理解。
下一节通过检查其核心组件来解构记忆的概念:它存储的信息类型、其组织模式、其存储和创建机制、其范围的策略定义,以及它对多模态与文本数据的处理。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 34
记忆的类型
Agent 的记忆可以根据信息的存储方式和捕获方式进行分类。这些不同类型的记忆协同工作,以创建对用户及其需求的丰富、上下文理解。在所有类型的记忆中,规则都是记忆是描述性的,而不是预测性的。
“记忆”是记忆管理器返回的、被 Agent 用作上下文的原子信息片段。虽然确切的模式可能有所不同,但单个记忆通常由两个主要组件组成:内容和元数据。
内容是从源数据(即会话的原始对话)中提取的记忆实质。至关重要的是,内容被设计为与框架无关,使用任何 Agent 都可以轻松摄取的简单数据结构。内容可以是结构化或非结构化数据。结构化记忆包含通常以字典或 JSON 等通用格式存储的信息。其模式通常由开发者定义,而不是特定的框架。例如,
{"seat_preference": "Window"}。非结构化记忆是自然语言描述,捕捉了较长交互、事件或主题的本质。例如,“用户喜欢靠窗的座位。”元数据提供关于记忆的上下文,通常存储为简单的字符串。这可以包括记忆的唯一标识符、记忆“所有者”的标识符,以及描述记忆内容或数据源的标签。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 35
信息的类型
除了基本结构之外,记忆还可以根据它们代表的基础知识类型进行分类。这种区别对于理解 Agent 如何使用记忆至关重要,它将记忆分为源自认知科学的两个主要功能类别¹¹:陈述性记忆(“知道是什么”)和程序性记忆(“知道怎么做”)。
陈述性记忆是 Agent 对事实、数据和事件的知识。它是 Agent 可以明确陈述或“宣告”的所有信息。如果记忆是对“什么”问题的回答,那它就是陈述性的。此类别包括通用世界知识(语义)和特定用户事实(实体/情景)。
程序性记忆是 Agent 对技能和工作流程的知识。它通过隐式演示如何正确执行任务来指导 Agent 的动作。如果记忆有助于回答“如何”问题——例如预订旅行的正确工具调用顺序——那它就是程序性的。
组织模式
一旦创建了记忆,下一个问题是如何组织它。记忆管理器通常采用以下一种或多种模式来组织记忆:集合¹²、结构化用户档案或“滚动摘要”。这些模式定义了单个记忆如何相互关联以及如何与用户关联。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 36
集合¹³模式将内容组织为单个用户的多个自包含、自然语言记忆。每个记忆都是一个独特的事件、摘要或观察,尽管集合中可能有多个记忆针对同一个高级主题。集合允许存储和搜索与特定目标或主题相关的更大、结构化程度较低的信息池。
结构化用户档案模式将记忆组织为关于用户的一组核心事实,就像一张不断用新的、稳定信息更新的联系人卡片。它专为快速查找基本、事实性信息(如姓名、偏好和帐户详细信息)而设计。
与结构化用户档案不同,“滚动”摘要模式将所有信息整合到一个单一的、不断演变的记忆中,该记忆代表整个用户-Agent 关系的自然语言摘要。管理器不断更新这个主文档,而不是创建新的、单独的记忆。此模式经常用于压缩长会话,在保留重要信息的同时管理总 Token 数量。
存储架构
此外,存储架构是一个关键决策,决定了 Agent 检索记忆的速度和智能程度。架构的选择定义了 Agent 是否擅长寻找概念上相似的想法、理解结构化关系,或两者兼而有之。
记忆通常存储在向量数据库和/或知识图谱中。向量数据库有助于找到与查询在概念上相似的记忆。知识图谱将记忆存储为实体及其关系的网路。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 37
向量数据库是最常见的方法,支持基于语义相似性而不是精确关键字的检索。记忆被转换为嵌入向量,数据库找到与用户查询最接近的概念匹配。这在检索上下文和意义是关键的非结构化、自然语言记忆方面表现出色(即“原子事实”¹⁴)。
知识图谱用于将记忆存储为实体(节点)及其关系(边)的网络。检索涉及遍历此图以查找直接和间接连接,从而允许 Agent 推理不同事实是如何链接的。它非常适合结构化、关系查询和理解数据中的复杂连接(即“知识三元组”¹⁵)。
您还可以通过用向量嵌入丰富知识图谱的结构化实体,将这两种方法结合为混合方法。这使得系统能够同时执行关系搜索和语义搜索。这提供了图谱的结构化推理和向量数据库的细致、概念化搜索,融合了两者的优点。
创建机制
我们还可以根据记忆的创建方式(包括信息的衍生方式)对记忆进行分类。当用户直接命令 Agent 记住某事时,就会创建显式记忆(例如,“记住我的周年纪念日是10月26日”)。另一方面,当 Agent 在没有直接命令的情况下从对话中推断和提取信息时,就会创建隐式记忆(例如,“我的周年纪念日是下周。你能帮我给我的伴侣找个礼物吗?”)。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 38
记忆还可以根据记忆提取逻辑是位于 Agent 框架内部还是外部来区分。内部记忆是指直接内置于 Agent 框架中的记忆管理。它便于入门,但通常缺乏高级功能。内部记忆可以使用外部存储,但生成记忆的机制在 Agent 内部。
外部记忆涉及使用专门用于记忆管理的独立专业服务(例如 Agent Engine Memory Bank, Mem0, Zep)。Agent 框架向此外部服务进行 API 调用以存储、检索和处理记忆。这种方法提供了更复杂的功能,如语义搜索、实体提取和自动摘要,将记忆管理的复杂任务卸载给专用工具。
记忆范围
您还需要考虑记忆描述的是谁或什么。这对您使用什么实体(即用户、会话或应用程序)来聚合和检索记忆有影响。
用户级范围是最常见的实现,旨在为每个人创造连续、个性化的体验;例如,“用户喜欢中间座位。”记忆绑定到特定用户 ID 并在其所有会话中持久存在,允许 Agent 建立对其偏好和历史的长期理解。
会话级范围专为长对话的压缩而设计;例如,“用户正在购买2025年11月7日至2025年11月14日之间纽约和巴黎之间的机票。他们喜欢直飞航班和中间座位”。它创建了从单个会话中提取的见解的持久记录,允许 Agent 替换冗长的、Token 密集的记录,代之以一组简洁的关键事实。至关重要的是,这种记忆与原始会话日志不同;它仅包含从对话中处理过的见解,而不是对话本身,并且其上下文隔离在特定的会话中。
应用程序级范围(或全局上下文)是指应用程序的所有用户都可以访问的记忆;例如,“代号 XYZ 指的是项目……”此范围用于提供共享上下文、广播系统范围的信息或建立常识基线。应用程序级记忆的一个常见用例是程序性记忆,它为 Agent 提供“操作指南”说明;这些记忆通常旨在帮助所有用户的 Agent 推理。至关重要的是,这些记忆必须清除所有敏感内容,以防止用户之间的数据泄露。
多模态记忆
“多模态记忆”是一个关键概念,描述了 Agent 如何处理非文本信息,如图像、视频和音频。关键是要区分记忆衍生自的数据(其源)和记忆存储为的数据(其内容)。
来自多模态源的记忆是最常见的实现。Agent 可以处理各种数据类型——文本、图像、音频——但它创建的记忆是源自该源的文本见解。例如,Agent 可以处理用户的语音备忘录以创建记忆。它不存储音频文件本身;相反,它转录音频并创建文本记忆,如“用户对最近的运输延误表示沮丧”。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 40
具有多模态内容的记忆是一种更高级的方法,其中记忆本身包含非文本媒体。Agent 不仅描述内容;它直接存储内容。例如,用户可以上传一张图像并说“记住这个作为我们的标志设计。”Agent 创建一个直接包含图像文件的记忆,链接到用户的请求。
大多数当代的记忆管理器专注于处理多模态源,同时生成文本内容。这是因为为特定记忆生成和检索非结构化二进制数据(如图像或音频)需要专门的模型、算法和基础设施。将所有输入转换为通用的、可搜索的格式:文本,要简单得多。
例如,您可以使用 Agent Engine Memory Bank 从多模态输入生成记忆¹⁶。输出记忆将是从内容中提取的文本见解:
# Python from google.genai import types client = vertexai.Client(project=..., location=...) response = client.agent_engines.memories.generate( name=agent_engine_name, direct_contents_source={ "events": [ { "content": types.Content( role="user", parts=[ types.Part.from_text( "This is context about the multimodal input." ), types.Part.from_bytes( data=CONTENT_AS_BYTES, mime_type=MIME_TYPE ), types.Part.from_uri( file_uri="file/path/to/content", mime_type=MIME_TYPE ) ] ) } ] }, scope={"user_id": user_id} )
片段 5:Agent Engine Memory Bank 的记忆生成 API 调用示例
下一节将考察记忆生成的机制,详细介绍两个核心阶段:从源数据中提取新信息,以及随后将该信息与现有记忆语料库进行整合。
记忆生成:提取与整合
记忆生成自主地将原始对话数据转换为结构化的、有意义的见解。可以将其视为旨在提取和浓缩记忆的 LLM 驱动的 ETL(提取、转换、加载)管道。记忆生成的 ETL 管道将记忆管理器与 RAG 引擎和传统数据库区分开来。
记忆管理器不需要开发者手动指定数据库操作,而是使用 LLM 来智能地决定何时添加、更新或合并记忆。这种自动化是记忆管理器的核心优势;它抽象了管理数据库内容、链接 LLM 调用以及部署后台服务进行数据处理的复杂性。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 42
图 6:记忆生成的高级算法,从新数据源提取记忆并将其与现有记忆整合
(图表描述:数据源(会话事件)-> 记忆提取(LLM)-> 原始记忆。原始记忆 -> 检索相似的现有记忆 -> 相似记忆。相似记忆 + 原始记忆 -> 记忆整合(LLM)-> 带有操作(添加/更新)的整合记忆。记忆存储 <-> 检索/存储。)
虽然具体算法因平台而异(例如 Agent Engine Memory Bank, Mem0, Zep),但记忆生成的高级过程通常遵循以下四个阶段:
- 摄入: 该过程始于客户端向记忆管理器提供原始数据源(通常是对话历史)。
- 提取与过滤: 记忆管理器使用 LLM 从源数据中提取有意义的内容。关键在于此 LLM 不会提取所有内容;它只捕获符合预定义主题定义的信息。如果摄入的数据不包含与这些主题匹配的信息,则不会创建记忆。
- 整合: 这是最复杂的阶段,记忆管理器在此处理冲突解决和去重。它执行“自我编辑”过程,使用 LLM 将新提取的信息与现有记忆进行比较。为了确保用户的知识库保持连贯、准确,并根据新信息随时间演变,管理器可以决定:
- 合并新见解到现有记忆中。
- 删除现有的记忆,如果它现在已失效。
- 创建全新的记忆,如果主题是新颖的。
- 存储: 最后,新的或更新的记忆被持久化到持久存储层(如向量数据库或知识图谱),以便可以在未来的交互中检索。
托管记忆管理器,如 Agent Engine Memory Bank,完全自动化此管道。它们提供单一、连贯的系统,将对话噪音转化为结构化知识,允许开发者专注于 Agent 逻辑,而不是自己构建和维护底层数据基础设施。例如,使用 Memory Bank 触发记忆生成只需要一个简单的 API 调用¹⁷:
# Python from google.cloud import vertexai client = vertexai.Client(project=..., location=...) client.agent_engines.memories.generate( name="projects/.../locations/...reasoningEngines/...", scope={"user_id": "123"}, direct_contents_source={ "events": [...] }, config={ # 在后台运行记忆生成。 "wait_for_completion": False } )
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 44
记忆生成的过程可以比作勤奋的园丁照料花园的工作。提取就像接收新的种子和树苗(来自对话的新信息)。园丁不会只是随意地把它们扔到地里。相反,他们通过拔除杂草(删除多余或冲突的数据),修剪过度生长的枝条以改善现有植物的健康状况(提炼和总结现有记忆),然后小心地将新树苗种植在最佳位置来执行整合。这种持续、深思熟虑的策划确保了花园保持健康、有条理,并随着时间的推移继续繁荣,而不是变成杂草丛生、无法使用的烂摊子。这个异步过程在后台发生,确保花园随时为下次访问做好准备。
现在,让我们深入探讨记忆生成的两个关键步骤:提取和整合。
深入探讨:记忆提取
记忆提取的目标是回答一个基本问题:“这次对话中哪些信息足够有意义,可以成为记忆?”这不是简单的摘要;这是一个有针对性的、智能的过滤过程,旨在将信号(重要事实、偏好、目标)与噪音(寒暄、填充文本)分离。
“有意义”不是一个普遍的概念;它完全由 Agent 的目的和用例定义。客户支持 Agent 需要记住的内容(例如订单号、技术问题)与个人健康教练需要记住的内容(例如长期目标、情绪状态)有着根本的不同。因此,自定义保留哪些信息是创建真正有效 Agent 的关键。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 45
记忆管理器的 LLM 通过遵循一组精心构建的程序化护栏和指令来决定提取什么,这些指令通常嵌入在复杂的系统提示中。此提示通过向 LLM 提供一组主题定义来定义“有意义”的含义。通过基于模式和模板的提取,LLM 会获得预定义的 JSON 模式或使用 LLM 功能(如结构化输出¹⁸)的模板;LLM 被指示使用对话中的相应信息构建 JSON。或者,通过自然语言主题定义,LLM 由简单的主题自然语言描述来指导。
通过少样本提示,LLM 被“展示”使用示例提取什么信息。提示包含几个输入文本示例和应提取的理想、高保真记忆。LLM 从示例中学习所需的提取模式,使其对于难以用模式或简单定义描述的自定义或细微主题非常有效。
大多数记忆管理器开箱即用,通过寻找常见主题,如用户偏好、关键事实或目标。许多平台还允许开发者定义自己的自定义主题,将提取过程定制到其特定领域。例如,您可以通过提供自己的主题定义和少样本示例,自定义 Agent Engine Memory Bank 认为有意义并持久化的信息¹⁹:
# Python from google.genai.types import Content, Part # 详见 https://cloud.google.com/agent-builder/agent-engine/memory-bank/set-up memory_bank_config = { "customization_configs": [{ "memory_topics": [ { "managed_memory_topic": {"managed_topic_enum": "USER_PERSONAL_INFO" }}, { "custom_memory_topic": { "label": "business_feedback", "description": """Specific user feedback about their experience at the coffeeshop. This includes opinions on drinks, food, pastries, ambiance, staff friendliness,service speed, cleanliness, and any suggestions for improvement.""" } } ], "generate_memories_examples": { "conversationSource": { "events": [ { "content": Content( role="model", parts=[Part(text="Welcome back to The Daily Grind! We'd love to hearyour feedback on your visit.")]) },{ "content": Content( role="user", parts=[Part(text= "Hey. The drip coffee was a bit lukewarm today, whichwas a bummer. Also, the music was way too loud, I could barely hear my friend.")]) }] }, "generatedMemories": [ {"fact": "The user reported that the drip coffee was lukewarm."}, {"fact": "The user felt the music in the shop was too loud."} ] } }] } agent_engine = client.agent_engines.create( config={ "context_spec": {"memory_bank_config": memory_bank_config } } )
片段 7:自定义 Agent Engine Memory Bank 认为有意义并持久化的信息
虽然记忆提取本身不是“摘要”,但算法可能会结合摘要来提炼信息。为了提高效率,许多记忆管理器将对话的滚动摘要直接合并到记忆提取提示²⁰中。这种浓缩的历史提供了必要的上下文来从最近的交互中提取关键信息。它消除了在每一轮中重复处理完整、冗长对话以保持上下文的需要。
一旦从数据源中提取了信息,现有记忆语料库必须通过整合进行更新,以反映新信息。
深入探讨:记忆整合
从冗长的对话中提取记忆后,整合应将新信息集成到一个连贯、准确且不断演变的知识库中。这无疑是记忆生命周期中最复杂的阶段,将简单的已收集事实转化为对用户的精心理解。没有整合,Agent 的记忆很快就会变成一个嘈杂、矛盾且不可靠的记录,包含曾经捕获的每一条信息。这种“自我策划”通常由 LLM 管理,正是这一点将记忆管理器提升到了简单数据库之上。
整合过程是一个 LLM 驱动的工作流,它将新提取的见解与用户的现有记忆进行比较。首先,该工作流尝试检索与新提取记忆相似的现有记忆。这些现有记忆是整合的候选者。如果现有记忆与新信息相矛盾,它可能会被删除。如果它被增强,它可能会被更新。
其次,向 LLM 展示现有记忆和新信息。其核心任务是将它们放在一起分析,并确定应执行哪些操作。主要操作包括:
- 更新: 用新的或修正的信息修改现有记忆。
- 创建: 如果新见解是全新的且与现有记忆无关,则创建一个新记忆。
- 删除 / 失效: 如果新信息使旧记忆完全不相关或不正确,则删除或使其失效。
最后,记忆管理器将 LLM 的决定转化为更新记忆存储的事务。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 49
记忆溯源
经典机器学习公理“垃圾进,垃圾出”对 LLM 来说更为关键,因为结果往往是“垃圾进,自信的垃圾出”。为了让 Agent 做出可靠的决策,并让记忆管理器有效地整合记忆,它们必须能够批判性地评估自身记忆的质量。这种可信度直接源于记忆的溯源(Provenance)——对其起源和历史的详细记录。
图 7:数据源与记忆之间的信息流。单个记忆可以源自多个数据源,单个数据源也可能促成多个记忆。
(图表描述:请求 1-4 具有不同的数据源(A、B、C、D),分别输入到记忆 1 的记忆修订版 1-3 和记忆 2 的记忆修订版 1-2。箭头显示谱系。)
记忆整合的过程——将来自多个来源的信息合并为单个、不断演变的记忆——产生了跟踪其谱系的需求。如上图所示,单个记忆可能是多个数据源的混合,而单个来源也可能被分割成多个记忆。
为了评估可信度,Agent 必须跟踪每个来源的关键细节,例如其起源(来源类型)和年龄(“新鲜度”)。这些细节至关重要,原因有二:它们决定了每个来源在记忆整合过程中的权重,并且它们告知 Agent 在推理过程中应在多大程度上依赖该记忆。
来源类型是决定信任度的最重要因素之一。数据源分为三个主要类别:
- 引导数据: 从内部系统(如 CRM)预加载的信息。这种高信任度数据可用于初始化用户记忆以解决冷启动问题,即向 Agent 从未交互过的用户提供个性化体验的挑战。
- 用户输入: 这包括显式提供的数据(例如通过表单,这是高信任度的)或从对话中隐式提取的信息(通常可信度较低)。
- 工具输出: 从外部工具调用返回的数据。通常不建议从工具输出生成记忆,因为这些记忆往往脆弱且陈旧,使这种来源类型更适合短期缓存。
在记忆管理期间考量记忆谱系
这种动态、多来源的记忆方法在管理记忆时带来了两个主要的操作挑战:冲突解决和删除衍生数据。
记忆整合不可避免地导致冲突,即一个数据源与另一个数据源冲突。记忆的溯源允许记忆管理器为其信息源建立信任层级。当来自不同来源的记忆相互矛盾时,Agent 必须在冲突解决策略中使用此层级。常见的策略包括优先考虑最受信任的来源、倾向于最新的信息,或在多个数据点之间寻找佐证。
管理多个记忆的另一个挑战发生在删除记忆时。一个记忆可以源自多个数据源。当用户撤销对一个数据源的访问权限时,源自该来源的数据也应被移除。删除该来源“接触”过的每一个记忆可能过于激进。一种更精确但计算成本更高的方法是仅使用剩余的、有效的来源从头重新生成受影响的记忆。
除了静态的溯源细节外,对记忆的信心也必须演变。信心通过佐证增加,例如当多个受信任的来源提供一致的信息时。然而,一个高效的记忆系统还必须通过记忆修剪来主动策划其现有知识——这是一个识别并“遗忘”不再有用的记忆的过程。这种修剪可以由几个因素触发:
- 基于时间的衰减: 记忆的重要性会随着时间的推移而降低。关于两年前会议的记忆可能不如上周的记忆相关。
- 低置信度: 从弱推断创建且从未被其他来源佐证的记忆可能会被修剪。
- 不相关性: 随着 Agent 对用户获得更复杂的理解,它可能会确定某些旧的、琐碎的记忆不再与用户的当前目标相关。
通过结合反应性整合管道和主动修剪,记忆管理器确保 Agent 的知识库不仅仅是一个不断增长的记录所有说过的话的日志。相反,它是对用户经过策划、准确且相关的理解。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 52
在推理期间考量记忆谱系
除了在策划语料库内容时考量记忆的谱系外,在推理时也应考虑记忆的可信度。Agent 对记忆的信心不应是静态的;它必须根据新信息和时间的流逝而演变。信心通过佐证增加,例如当多个受信任的来源提供一致的信息时。相反,随着旧记忆变得陈旧,信心会随时间减少(或衰减),并且当引入矛盾信息时也会下降。最终,系统可以通过归档或删除低置信度记忆来“遗忘”。这种动态置信度分数在推理时至关重要。记忆及其置信度分数(如果有)不是显示给用户,而是被注入到提示中,使 LLM 能够评估信息可靠性并做出更细致的决策。
整个信任框架服务于 Agent 的内部推理过程。记忆及其置信度分数通常不直接显示给用户。相反,它们被注入到系统提示中,允许 LLM 权衡证据,考虑其信息的可靠性,并最终做出更细致和可信的决策。
触发记忆生成
虽然一旦触发生成,记忆管理器就会自动进行记忆提取和整合,但 Agent 仍必须决定何时尝试记忆生成。这是一个关键的架构选择,要在数据新鲜度与计算成本和延迟之间取得平衡。此决定通常由 Agent 的逻辑管理,它可以采用多种触发策略。记忆生成可以基于各种事件启动:
- 会话完成: 在多轮会话结束时触发生成。
- 轮次节奏: 在特定数量的轮次后运行该过程(例如,每 5 轮)。
- 实时: 在每一轮之后生成记忆。
- 显式命令: 根据直接的用户命令激活该过程(例如,“记住这个”)。
触发器的选择涉及成本和保真度之间的直接权衡。频繁生成(例如实时)确保记忆高度详细且新鲜,捕捉对话的每一个细微差别。然而,这会产生最高的 LLM 和数据库成本,如果不当处理可能会引入延迟。不频繁生成(例如在会话完成时)更具成本效益,但存在创建低保真记忆的风险,因为 LLM 必须一次性总结更大的对话块。您还需要注意记忆管理器不要多次处理相同的事件,因为这会引入不必要的成本。
记忆作为工具
一种更复杂的方法是允许 Agent 自己决定何时创建记忆。在这种模式中,记忆生成被暴露为一个工具(即
create_memory);工具定义应定义哪些类型的信息应被认为是有意义的。然后,Agent 可以分析对话,并在识别出有意义持久化的信息时自主决定调用此工具。这将识别“有意义信息”的责任从外部记忆管理器转移到了 Agent(即您作为开发者)本身。例如,您可以使用 ADK 做到这一点,方法是将您的记忆生成代码打包到一个 Tool²¹ 中,当 Agent 认为对话有意义持久化时决定调用该工具。您可以将会话发送到 Memory Bank,Memory Bank 将从对话历史中提取并整合记忆:
# Python from google.adk.agents import LlmAgent from google.adk.memory import VertexAiMemoryBankService from google.adk.runners import Runner from google.adk.tools import ToolContext def generate_memories(tool_context: ToolContext): """Triggers memory generation to remember the session.""" # 选项 1:使用 ADK 记忆服务从完整的对话历史中提取记忆。 tool_context._invocation_context.memory_service.add_session_to_memory( session) # 选项 2:从最后的对话轮次中提取记忆。 client.agent_engines.memories.generate( name="projects/.../locations/...reasoningEngines/...", direct_contents_source={ "events": [ {"content": tool_context._invocation_context.user_content} ] }, scope={ "user_id": tool_context._invocation_context.user_id, "app_name": tool_context._invocation_context.app_name }, # 在后台生成记忆 config={"wait_for_completion": False} ) return {"status": "success"} agent = LlmAgent( ..., tools=[generate_memories] ) runner = Runner( agent=agent, app_name=APP_NAME, session_service=session_service, memory_service=VertexAiMemoryBankService( agent_engine_id=AGENT_ENGINE_ID, project=PROJECT, location=LOCATION ) )
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 55
另一种方法是利用内部记忆,其中 Agent 主动决定从对话中记住什么。在这个工作流中,Agent 负责提取关键信息。可选地,这些提取的记忆随后被发送到 Agent Engine Memory Bank 以与用户的现有记忆整合²²:
# Python def extract_memories(query: str, tool_context: ToolContext): """Triggers memory generation to remember information. Args: query: Meaningful information that should be persisted about the user. """ client.agent_engines.memories.generate( name="projects/.../locations/...reasoningEngines/...", # 有意义的信息已经从对话中提取出来了,所以我们 # 只是想把它与同一用户的现有记忆进行整合。 direct_memories_source={ "direct_memories": [{"fact": query}] }, scope={ "user_id": tool_context._invocation_context.user_id, "app_name": tool_context._invocation_context.app_name }, config={"wait_for_completion": False} ) return {"status": "success"} agent = LlmAgent( ..., tools=[extract_memories] )
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 56
后台操作与阻塞操作
记忆生成是一项昂贵的操作,需要 LLM 调用和数据库写入。对于生产环境中的 Agent,记忆生成几乎应始终作为后台进程异步处理²³。
在 Agent 发送其对用户的响应后,记忆生成管道可以并行运行而不阻塞用户体验。这种解耦对于保持 Agent 的快速响应感觉至关重要。阻塞(或同步)方法,即用户必须等待记忆写入后才能收到响应,会导致令人无法接受的缓慢和令人沮丧的用户体验。这使得记忆生成必须在架构上与 Agent 核心运行时分离的服务中进行。
记忆检索
随着记忆生成机制的到位,您的重点可以转移到检索的关键任务上。智能检索策略对于 Agent 的性能至关重要,包括关于应检索哪些记忆以及何时检索它们的决策。
检索记忆的策略很大程度上取决于记忆的组织方式。对于结构化用户档案,检索通常是直接查找完整档案或特定属性。然而,对于记忆集合,检索是一个更复杂的搜索问题。目标是从大量的非结构化或半结构化数据池中发现最相关、概念上相关的信息。本节讨论的策略旨在解决记忆集合的这一复杂检索挑战。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 57
记忆检索搜索与当前对话最相关的记忆。有效的检索策略至关重要;提供不相关的记忆会混淆模型并降低其响应质量,而找到完美的上下文片段则可能导致非常智能的交互。核心挑战是在严格的延迟预算内平衡记忆的“有用性”。
高级记忆系统超越了简单的搜索,并在多个维度上对潜在记忆进行评分以找到最佳匹配。
- 相关性(语义相似性): 这个记忆与当前对话在概念上的相关程度如何?
- 新近度(基于时间): 这个记忆是多久前创建的?
- 重要性(显著性): 这个记忆总体上有多关键?与相关性不同,记忆的“重要性”可能在生成时定义。
仅仅依赖基于向量的相关性是一个常见的陷阱。相似性分数可能会浮现出概念上相似但陈旧或琐碎的记忆。最有效的策略是混合方法,结合所有三个维度的分数。
对于准确性至关重要的应用程序,可以使用查询重写、重排序或专用检索器等方法来优化检索。然而,这些技术计算成本高昂且增加了显着的延迟,使其不适合大多数实时应用程序。对于必须使用这些复杂算法且记忆不会很快过时的场景,缓存层可能是一种有效的缓解措施。缓存允许临时存储检索查询的昂贵结果,从而为后续相同的请求绕过高延迟成本。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 58
通过查询重写,可以使用 LLM 来改进搜索查询本身。这可能涉及将用户模棱两可的输入重写为更精确的查询,或者将单个查询扩展为多个相关查询以捕获主题的不同方面。虽然这显着提高了初始搜索结果的质量,但它在流程开始时增加了额外 LLM 调用的延迟。
通过重排序,初始检索使用相似性搜索获取广泛的候选记忆集(例如前 50 个结果)。然后,LLM 可以重新评估和重新排序这个较小的集合,以产生更准确的最终列表²⁴。
最后,您可以使用微调训练专用检索器。然而,这需要访问标记数据,并且会显着增加成本。
归根结底,最好的检索方法始于更好的记忆生成。确保记忆语料库质量高且没有不相关信息,是保证任何检索到的记忆集都有用的最有效方法。
检索时机
检索的最终架构决策是何时检索记忆。一种方法是主动检索,即在每一轮开始时自动加载记忆。这确保了上下文始终可用,但对于不需要访问记忆的轮次会引入不必要的延迟。由于记忆在单轮中保持静态,因此可以有效地缓存它们以减轻这种性能成本。
例如,您可以使用内置的
PreloadMemoryTool 或自定义回调在 ADK 中实现主动检索²⁵:# Python # 选项 1:使用内置的 PreloadMemoryTool,它每轮都通过相似性搜索检索记忆。 agent = LlmAgent( ..., tools=[adk.tools.preload_memory_tool.PreloadMemoryTool()] ) # 选项 2:使用自定义回调以更好地控制记忆的检索方式。 def retrieve_memories_callback(callback_context, llm_request): user_id = callback_context._invocation_context.user_id app_name = callback_context._invocation_context.app_name response = client.agent_engines.memories.retrieve( name="projects/.../locations/...reasoningEngines/...", scope={ "user_id": user_id, "app_name": app_name } ) memories = [f"* {memory.memory.fact}" for memory in list(response)] if not memories: # 没有记忆要添加到系统指令中。 return # 将格式化的记忆追加到系统指令中 llm_request.config.system_instruction += "\nHere is information that you have about the user:\n" llm_request.config.system_instruction += "\n".join(memories) agent = LlmAgent( ..., before_model_callback=retrieve_memories_callback, )
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 60
或者,您可以使用反应式检索(“记忆作为工具”),即给 Agent 一个工具来查询其记忆,由其自己决定何时检索上下文。这更高效、更稳健,但需要额外的 LLM 调用,增加了延迟和成本;但是,仅在必要时检索记忆,因此产生延迟成本的频率较低。此外,Agent 可能不知道是否存在相关信息可供检索。然而,这可以通过让 Agent 意识到可用记忆的类型(例如,如果您使用的是自定义工具,则在工具描述中说明)来缓解,从而使其能够就何时查询做出更明智的决定。
# Python # 选项 1:使用内置的 LoadMemory。 agent = LlmAgent( ..., tools=[adk.tools.load_memory_tool.LoadMemoryTool()], ) # 选项 2:使用自定义工具,您可以在其中描述可能可用的信息类型。 def load_memory(query: str, tool_context: ToolContext): """Retrieves memories for the user. The following types of information may be stored for the user: * User preferences, like the user's favorite foods. ... """ # 使用相似性搜索检索记忆。 response = tool_context.search_memory(query) return response.memories agent = LlmAgent( ..., tools=[load_memory], )
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 61
基于记忆的推理
一旦检索到相关记忆,最后一步是将它们策略性地放入模型的上下文窗口中。这是一个关键过程;记忆的放置会显著影响 LLM 的推理,影响运营成本,并最终决定最终答案的质量。
记忆主要通过追加到系统指令或注入对话历史来呈现。在实践中,混合策略通常最有效。对始终存在的稳定、全局记忆(如用户档案)使用系统提示。否则,对仅与对话即时上下文相关的短暂、情景记忆使用对话注入或记忆作为工具。这平衡了对持久上下文的需求与即时信息检索的灵活性。
系统指令中的记忆
使用记忆进行推理的一个简单选项是将记忆追加到系统指令中。此方法通过将检索到的记忆与前言一起直接追加到系统提示中,保持对话历史的整洁,将其构建为整个交互的基础上下文。例如,您可以使用 Jinja 动态地将记忆添加到您的系统指令中:
# Python from jinja2 import Template template = Template(""" system_instructions }<MEMORIES>Here is some information about the user:{% for retrieved_memory in data %}* retrieved_memory.memory.fact {% endfor %}</MEMORIES>""") prompt = template.render( system_instructions=system_instructions, data=retrieved_memories )
在系统指令中包含记忆赋予了记忆很高的权威性,清晰地将上下文与对话分离,并且非常适合像用户档案这样稳定的“全局”信息。然而,存在过度影响的风险,即 Agent 可能会尝试将每个主题都联系回其核心指令中的记忆,即使在不合适的情况下也是如此。
这种架构模式引入了几个约束。首先,它要求 Agent 框架在每次 LLM 调用之前支持系统提示的动态构建;此功能并非总是现成支持的。此外,该模式与“记忆作为工具”不兼容,因为系统提示必须在 LLM 决定调用记忆检索工具之前定稿。最后,它处理非文本记忆的能力较差。大多数 LLM 仅接受文本作为系统指令,这使得将多模态内容(如图像或音频)直接嵌入提示中变得具有挑战性。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 63
对话历史中的记忆
在这种方法中,检索到的记忆直接注入到逐轮对话中。记忆可以放置在完整对话历史之前,或者紧接在最新的用户查询之前。
然而,这种方法可能会产生噪音,增加 Token 成本,如果检索到的记忆不相关,可能会混淆模型。其主要风险是对话注入,即模型可能会错误地将记忆视为对话中实际说过的内容。您还需要更加注意注入到对话中的记忆的视角;例如,如果您使用“用户”角色和用户级记忆,记忆应以第一人称视角编写。
将记忆注入对话历史的一个特例是通过工具调用检索记忆。记忆将作为工具输出的一部分直接包含在对话中。
# Python def load_memory(query: str, tool_context: ToolContext): """Loads memories into the conversation history...""" response = tool_context.search_memory(query) return response.memories agent = LlmAgent( ..., tools=[load_memory], )
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 64
程序性记忆
本白皮书主要关注陈述性记忆,这一重点反映了当前的商业记忆领域现状。大多数记忆管理平台也是为这种陈述性方法架构的,擅长提取、存储和检索“什么”——事实、历史和用户数据。
然而,这些系统并非设计用于管理程序性记忆,即改进 Agent 工作流程和推理的机制。存储“如何做”不是一个信息检索问题;它是一个推理增强问题。管理这种“知道怎么做”需要一个完全独立且专门的算法生命周期,尽管具有类似的高级结构²⁶:
- 提取: 程序性提取需要专门的提示,旨在从成功的交互中提炼出可重用的策略或“剧本”,而不仅仅是捕获事实或有意义的信息。
- 整合: 陈述性整合合并相关事实(“什么”),而程序性整合策划工作流程本身(“如何”)。这是一个主动的逻辑管理过程,专注于将新的成功方法与现有的“最佳实践”集成,修补已知计划中的缺陷步骤,并修剪过时或无效的程序。
- 检索: 目标不是检索数据来回答问题,而是检索一个指导 Agent 如何执行复杂任务的计划。因此,程序性记忆可能具有与陈述性记忆不同的数据模式。
Agent 这种“自我进化”逻辑的能力自然引出了与一种常见适应方法的比较:微调——通常通过人类反馈强化学习 (RLHF)²⁷。虽然这两个过程都旨在改善 Agent 行为,但它们的机制和应用有着根本的不同。微调是一个相对缓慢的、离线训练过程,它改变模型权重。程序性记忆通过将正确的“剧本”动态注入提示中提供快速、在线的适应,通过上下文学习指导 Agent,而无需任何微调。
测试与评估
现在您拥有了一个具有记忆能力的 Agent,您应该通过全面的质量和评估测试来验证您的具有记忆能力的 Agent 的行为。评估 Agent 的记忆是一个多层次的过程。评估需要验证 Agent 记住了正确的事情(质量),它可以在需要时找到这些记忆(检索),以及使用这些记忆实际上有助于它完成目标(任务成功)。虽然学术界专注于可复现的基准测试,但行业评估集中在记忆如何直接影响生产 Agent 的性能和可用性。
记忆生成质量指标评估记忆本身的内容,回答这个问题:“Agent 是否记住了正确的事情?”这通常通过将 Agent 生成的记忆与人工创建的理想记忆“黄金集”进行比较来衡量。
- 精确率 (Precision): 在 Agent 创建的所有记忆中,有多少比例是准确且相关的?高精确率可以防止“过度热切”的记忆系统用不相关的噪音污染知识库。
- 召回率 (Recall): 在它应该从源中记住的所有相关事实中,它捕获了多少比例?高召回率确保 Agent 不会错过关键信息。
- F1 分数 (F1-Score): 精确率和召回率的调和平均值,提供单一、平衡的质量度量。
记忆检索性能指标评估 Agent 在正确时间找到正确记忆的能力。
- Recall@K: 当需要记忆时,是否在前 ‘K’ 个检索结果中找到了正确的那个?这是检索系统准确性的主要衡量标准。
- 延迟: 检索位于 Agent 响应的“热路径”上。整个检索过程必须在严格的延迟预算内执行(例如,低于 200 毫秒),以避免降低用户体验。
端到端任务成功指标是最终测试,回答这个问题:“记忆实际上是否有助于 Agent 更好地完成工作?”这通过评估 Agent 使用其记忆在下游任务上的表现来衡量,通常使用 LLM“裁判”将 Agent 的最终输出与黄金答案进行比较。裁判确定 Agent 的答案是否准确,有效地衡量记忆系统对最终结果的贡献程度。
评估不是一次性事件;它是持续改进的引擎。上述指标提供了识别弱点并随时间系统地增强记忆系统所需的数据。这个迭代过程包括建立基线、分析失败、调整系统(例如,优化提示、调整检索算法),并重新评估以衡量变更的影响。
虽然上述指标侧重于质量,但生产就绪性也取决于性能。对于每个评估领域,测量底层算法的延迟及其在负载下的扩展能力至关重要。“在热路径上”检索记忆可能具有严格的、亚秒级的延迟预算。生成和整合虽然通常是异步的,但必须有足够的吞吐量来跟上用户需求。最终,一个成功的记忆系统必须是智能、高效且对现实世界的使用具有鲁棒性的。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 67
记忆的生产环境考量
除了性能之外,将具有记忆能力的 Agent 从原型过渡到生产环境需要关注企业级架构问题。此举引入了对可扩展性、弹性和安全性的关键要求。生产级系统不仅必须设计得智能,还必须具有企业级的鲁棒性。
为了确保用户体验永远不会被计算昂贵的记忆生成过程阻塞,健壮的架构必须将记忆处理与主应用程序逻辑解耦。虽然这是一种事件驱动模式,但它通常通过对专用记忆服务的直接、非阻塞 API 调用来实现,而不是通过自管理的消息队列。流程如下:
- Agent 推送数据: 在相关事件(例如会话结束)之后,Agent 应用程序对记忆管理器进行非阻塞 API 调用,“推送”原始源数据(如对话记录)以进行处理。
- 记忆管理器在后台处理: 记忆管理器服务立即确认请求,并将生成任务放入其自己的内部托管队列中。然后,它全权负责异步繁重的工作:进行必要的 LLM 调用以提取、整合和格式化记忆。管理器可能会延迟处理事件,直到经过一段时间的不活动。
- 记忆被持久化: 服务将最终记忆——可能是新条目或对现有条目的更新——写入专用的、持久的数据库。对于托管记忆管理器,存储是内置的。
- Agent 检索记忆: 当主 Agent 应用程序需要为新的用户交互检索上下文时,它可以直接查询此记忆存储。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 68
这种基于服务的非阻塞方法确保记忆管道中的故障或延迟不会直接影响面向用户的应用程序,使系统更具弹性。它也为在线(实时)生成(对话新鲜度的理想选择)和离线(批处理)处理(用于从历史数据填充系统)之间的选择提供了参考。
随着应用程序的增长,记忆系统必须处理高频事件而不发生故障。考虑到并发请求,当多个事件尝试修改同一记忆时,系统必须防止死锁或竞态条件。您可以使用事务性数据库操作或乐观锁来缓解竞态条件;然而,当多个请求尝试修改相同的记忆时,这可能会引入排队或节流。健壮的消息队列对于缓冲大量事件并防止记忆生成服务不堪重负至关重要。
记忆服务还必须对瞬态错误具有弹性(故障处理)。如果 LLM 调用失败,系统应使用具有指数退避的重试机制,并将持续失败路由到死信队列进行分析。
对于全球应用程序,记忆管理器必须使用具有内置多区域复制功能的数据库,以确保低延迟和高可用性。客户端复制是不可行的,因为整合需要数据的单一、事务一致的视图以防止冲突。因此,记忆系统必须在内部处理复制,向开发者呈现单一的逻辑数据存储,同时确保底层知识库在全球范围内一致。
托管记忆系统,如 Agent Engine Memory Bank,应帮助您解决这些生产考量,以便您可以专注于核心 Agent 逻辑。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 69
隐私与安全风险
记忆源自并包含用户数据,因此需要严格的隐私和安全控制。一个有用的类比是将系统的记忆视为由专业档案管理员管理的这种安全企业档案馆,其工作是保存有价值的知识,同时保护公司。
该档案馆的首要规则是数据隔离。就像档案管理员永远不会混合来自不同部门的机密文件一样,记忆必须在用户或租户级别严格隔离。服务于一个用户的 Agent 绝不能访问另一个用户的记忆,这需要使用限制性访问控制列表 (ACL) 来强制执行。此外,用户必须对其数据拥有程序控制权,并有明确的选项选择退出记忆生成或请求从档案馆删除其所有文件。
在归档任何文件之前,档案管理员会执行关键的安全步骤。首先,他们仔细检查每一页以编辑敏感的个人信息 (PII),确保在保存知识的同时不产生责任。其次,档案管理员受过训练,能够发现并丢弃伪造或故意误导的文件——这是防止记忆中毒²⁸的保障措施。同样,系统必须在将信息提交到长期记忆之前验证和清理信息,以防止恶意用户通过提示注入破坏 Agent 的持久知识。系统必须包含像 Model Armor 这样的保障措施,在将信息提交到长期记忆之前对其进行验证和清理²⁹。
此外,如果多个用户共享同一组记忆,如程序性记忆(教 Agent 如何做某事),则存在泄露风险。例如,如果来自一个用户的程序性记忆被用作另一个用户的示例——就像在全公司分享备忘录一样——档案管理员必须首先执行严格的匿名化,以防止敏感信息跨用户边界泄露。
Context Engineering: Sessions, Memory上下文工程:会话,记忆
2025年11月 | 70
结论
本白皮书探讨了上下文工程这一学科,重点关注其两个核心组件:会话和记忆。从简单的对话轮次到持久、可操作的智能片段的旅程受这一实践的支配,它涉及将所有必要信息——包括对话历史、记忆和外部知识——动态组装到 LLM 的上下文窗口中。这整个过程依赖于两个独特但相互关联的系统之间的相互作用:即时会话和长期记忆。