Agent 记忆架构设计:原理 × 业界三大范式 × XXL-AI 落地实践

1、引言:Agent 的"金鱼记忆"问题

大模型是无状态的:每次推理,它拿到的只有当前塞进上下文窗口的那点 token;请求一结束,说过什么、对方是谁、聊到哪,统统清零。这就是 Agent 的**"金鱼记忆"**------问题不在记性短,而在每次会话都从一张白纸重新开始。

单轮问答时代,这无关痛痒;但 Agent 的目标远不止于做一个随问随答的"工具"。一旦它要长期驻场、持续陪伴、独立推进任务,就必须成为真正意义上的长期协作者------懂你的偏好、记得共同的上下文、能接着上次的进度继续干。而能否撑起这个角色,全系于记忆:

  • 答非所问:不记得用户上一句刚说的背景,反复追问;
  • 重复劳动:不记得昨天已经得出的结论,重新推导一遍;
  • 缺乏个性化:不记得用户偏好,每次都给出"千人一面"的答案;
  • 知识断层:模型自身训练数据过时或缺失,回答不了私有知识。

因此,记忆系统是 Agent 从"一次性工具"跃迁为"长期协作者"的分水岭。它要回答四个朴素却根本的问题:记什么、存哪里、怎么取、何时忘。

本文不从某一框架的实现讲起,而是先建立一套通用的"记忆层次"坐标系,再对齐业界三大主流范式,最后落到 XXL-AI 的工程实现------它实际上已经实现了一套完整的"巩固式长期记忆",这是本文最值得读的部分。

2、原理:从认知科学拆解记忆层次(纵轴)

设计 Agent 记忆时,最自然的参照是人脑的记忆模型。认知科学将记忆按"信息能存多久"切分为若干层次,这一"生命周期"维度,正是本文用来组织全部内容的纵轴。

复制代码
记忆层次(纵轴:信息的生命周期)
┌───────────────────────────────────────────────────────────────┐
│  短期 / 工作记忆                                              │
│  = 上下文窗口内的即时上下文(易失、容量受限、随请求结束而丢) │
├───────────────────────────────────────────────────────────────┤
│  长期记忆(跨会话持久,按内容性质再细分)                     │
│  ├─ 语义记忆  semantic    事实 / 知识   → 知识库(向量检索)  │
│  ├─ 情景记忆  episodic    画像 / 偏好 / 经历 → 长期记忆实体   │
│  └─ 程序记忆  procedural  技能 / 流程   → 技能沙箱            │
└───────────────────────────────────────────────────────────────┘

2.1、短期 / 工作记忆(Short-term / Working Memory)

短期记忆是 Agent 维护"当前对话与任务"的即时上下文,一般就是上下文窗口里装的那些东西:本轮历史消息、中间推理、工具调用结果。

它的特点决定了它的局限:

  • 易失:请求一结束就丢失,跨请求不保留;
  • 容量受限:受模型上下文窗口上限(几 K 到几 M token)与成本双重约束,不可能无限塞;
  • 即时可用:无需检索,直接参与生成,是最"快"的一类记忆。

业界(Letta、AWS 等)的主流口径里,短期记忆 = 工作记忆 = 上下文窗口内的消息缓冲,两者不作区分。少数资料会再把"当前上下文(RAM)"与"单会话历史"切开,但工程上合并处理更实用,本文采用合并口径。

2.2、长期记忆的三种形态(Long-term Memory)

长期记忆是跨会话、跨任务持久保存的那部分,对应人脑中稳定存续的记忆。按"内容性质"可再细分为三种,这种细分在工程上极具指导意义,因为它直接对应三种不同的存储与检索手段:

  • 语义记忆(semantic) :事实与知识,如"公司报销制度""产品参数""行业术语"。特点是面向全体用户、可共享、相对静态 ,工程上对应知识库 + 向量检索(RAG)。
  • 情景记忆(episodic) :某个具体用户的画像、偏好、过往经历,如"张三是后端工程师""偏好精简回答""上周在推进 A 项目"。特点是面向个体、随交互持续更新 ,工程上对应用户长期记忆实体。
  • 程序记忆(procedural) :怎么做事,如"调用某接口的流程""使用某工具的步骤"。特点是可复用、可执行 ,工程上对应技能 / 工具沙箱。

把这三者分开,是为了避免一个常见的混乱:很多人把"知识库"当成"记忆"的全部,其实知识库只覆盖了语义记忆这一小块,用户的个性化情景记忆、可执行的程序记忆同样不可或缺。

3、业界三大范式(横轴)

如果说"记忆层次"回答的是存多久(纵轴) ,那么"范式"回答的则是怎么构建与存取(横轴)。按"记忆如何被构建、如何与模型交互"这条主线,业界方案可以收敛为三大范式。

说明:关于范式划分,学界有更细的分类(如 arXiv:2606.06448 将结构化记忆再拆成 append-only 与 consolidating 两小类,合计四类;Atlan 归纳为五种模式)。本文为聚焦主线,将"结构化记忆"统一为一大类,收敛为"三大",读者可据此再向下钻取。

3.1、范式一:上下文内记忆(Long-context / Prompt Stuffing)

核心思想:把历史内容原样(或经摘要压缩)塞进上下文窗口,模型上下文本身就是记忆载体,不引入任何外部存储。

  • 优点:零架构、零依赖,开箱即用;
  • 缺点:受窗口长度与 token 成本硬约束,历史一长就"装不下",且每次都要为全部历史付费。

这是最原始、也最普遍的起点。几乎所有 Agent 的第一版都长这样,随后都会因"窗口装不下"而被迫演进。

3.2、范式二:外部检索记忆(Flat RAG)

核心思想:记忆仍以原始片段(chunk)落外部存储(向量库或倒排索引),查询时按相关性召回 Top-K 注入上下文,而不是全量塞入。

  • 代表:embedRAG、BM25 等;
  • 优点:突破窗口上限,可扩展到海量知识,按需付费(只召回相关片段);
  • 缺点:只做了"平铺式"检索,缺乏结构;对"事实性、关系性、时序性"等复杂记忆查询力不从心。

这一范式是当前"知识库问答"的主流,但它本质上仍是查询驱动的被动召回------记忆本身没有被"整理",只是被"索引"了。

3.3、范式三:结构化自管理记忆(Structured + Consolidating)

核心思想 :不再被动索引原始片段,而是主动从交互流中抽取、提炼、结构化 出记忆,并由 Agent(或后台进程)自我维护与更新------即"巩固(consolidation)"。

  • 代表:Mem0、Letta(MemGPT)、GraphRAG、HippoRAG;

  • 经典参照是 MemGPT(arXiv:2310.08560)提出的 OS 式三层记忆:

    MemGPT / Letta 的 OS 式三层记忆(类比计算机存储)
    ┌───────────────────────────────────────────────────────────────┐
    │ Core Memory(核心记忆,类比 RAM) │
    │ = 常驻上下文的定长块:角色设定 + 用户画像 + 当前任务 │
    ├───────────────────────────────────────────────────────────────┤
    │ Recall Memory(召回记忆,类比磁盘缓存) │
    │ = 可检索的近期对话历史,按需换入上下文 │
    ├───────────────────────────────────────────────────────────────┤
    │ Archival Memory(归档记忆,类比冷存储) │
    │ = 长期压缩存储,向量检索按需换入 │
    └───────────────────────────────────────────────────────────────┘

  • 优点:把"记忆"从"原始片段"升级为"结构化、可巩固、自我更新"的知识,更接近人脑;

  • 代价:抽取需额外调用模型(有延迟与幻觉污染风险),且引入了巩固时机、一致性、遗忘策略等新复杂度。

这一范式的关键词是**"巩固式"**------它不是简单地"存对话",而是"把对话蒸馏成记忆"。XXL-AI 的长期记忆正落在这个范式上。

3.4、三范式对照与取舍

维度 范式一 上下文内 范式二 外部检索(RAG) 范式三 结构化自管理
记忆载体 模型上下文窗口 外部向量/倒排索引 结构化记忆实体
记忆形态 原始历史片段 原始 chunk(索引) 抽取/巩固后的结构化记忆
交互方式 全量注入 查询时 Top-K 召回 主动抽取 + 按需注入
突破窗口上限 ✗ ✓ ✓
个性化 / 跨会话 弱 弱(偏知识) 强
实现复杂度 极低 中 高
代表 原生对话 embedRAG / BM25 Mem0 / Letta / GraphRAG

需要特别强调:三者并非互斥的"三选一",而是可叠加的。一个成熟的 Agent 通常三者并用------范式一承载即时上下文、范式二承载共享知识、范式三承载个体化的长期记忆。XXL-AI 正是这样一个混合体。

4、桥梁:记忆的消费------上下文工程(Context Engineering)

记忆"存"下来只是第一步,真正决定 Agent 表现的是**"怎么用"。Letta 有一句精辟的论断:记忆的本质,是决定在每一个时刻往上下文窗口里放哪些 token**。

这就引出了"上下文工程(Context Engineering)"------它是记忆系统的"调度员",负责在生成前,把记忆检索、组织、注入到上下文里:

  • 检索触发:什么时候去取记忆?取多少?(如知识库的 Top-K、相似度阈值)
  • 注入组织:取回的记忆以什么形式拼进上下文?(追加到系统指令?还是作为参考资料?)
  • 冲突消解:记忆与用户当前表述冲突时以谁为准?
  • 压缩与遗忘:上下文超限时如何摘要、卸载、淘汰?

XXL-AI 对"注入"的处理很有代表性(下文第 5 节):把长期记忆以 Markdown 追加到系统指令末尾,并明确约定**"若与用户当前表述冲突,以当前表述为准"**------这一句看似简单,却是防止"记忆反噬"的关键护栏。

5、XXL-AI 落地实践

下面落到 XXL-AI 的真实实现。它的记忆体系可以概括为一句话:短期记忆靠会话消息、长期记忆靠"巩固式"实体 + 异步归档、语义记忆靠知识库向量检索、程序记忆靠技能沙箱,四者各归其位,通过 harness 运行时层统一调度。

5.1、整体架构

css 复制代码
                    ┌─────────────────────────────────────────────┐
                    │            对话请求(用户 / 访客)          │
                    └──────────────────────┬──────────────────────┘
                                           ▼
        ┌──────────────────────────────────────────────────────────────┐
        │  ChatStreamTool(对话生成 worker,harness)                  │
        │  ① 历史消息       SessionMsg(短期记忆,按会话装载)         │
        │  ② 系统指令       Agent.systemPrompt                         │
        │  ③ 长期记忆注入   MemoryTool.loadMemory + mergePrompt        │
        │  ④ 工具装配       MCP / Skill / 终端·文件沙箱                │
        │  ⑤ RAG Advisor    RagTool.buildAdvisor(知识库语义检索)     │
        └──────────────┬──────────────────────────────┬────────────────┘
                       ▼                              ▼
            ┌────────────────────┐   ┌─────────────────────────────────┐
            │   LLM 流式生成     │   │  Milvus 向量库(语义记忆)      │
            └──────────┬─────────┘   └─────────────────────────────────┘
                       ▼
            ┌────────────────────┐
            │  SessionMsg 落库   │   短期记忆持久化(reasoning+content)
            └──────────┬─────────┘
                       ▼
        ┌──────────────────────────────────────────────────────────────┐
        │  MemoryArchiveTool(异步归档,60s 心跳 + Redis 抢锁)        │
        │  新消息 > 水位线?→ MemoryTool.generate → upsert + 推进水位线│
        └────────────────────────┬─────────────────────────────────────┘
                                 ▼
                ┌──────────────────────────────────┐
                │  Memory 长期记忆(Agent×访客)   │
                │  画像 / 偏好 / 事实 / 目标 / 进展│
                └──────────────────────────────────┘

整条链路分三环:对话侧(同步注入记忆并生成)→ 存储侧(消息落库)→ 归档侧(异步把消息蒸馏成长记忆)。记忆的生成与消费解耦------对话时只"读"记忆,绝不阻塞生成去做"写"记忆,后者交给后台定时器异步完成。

5.2、短期记忆:会话消息(SessionMsg)

短期记忆由会话消息承载。每条消息记录角色、正文、思考过程与状态:

bash 复制代码
SessionMsg 实体(短期记忆)
  id         消息ID
  sessionId  对话ID
  role       角色:user-用户 / assistant-助手
  reasoning  思考过程(推理模型 reasoning_content)
  content    消息内容
  status     状态:0-生成中 / 1-完成 / 2-失败

对话发起时,ChatStreamTool 按会话装载历史消息(角色序列 + 内容序列)作为短期记忆,与系统指令、长期记忆、工具、RAG 上下文一起拼成最终的生成输入。

5.3、长期记忆:实体模型 + 运行时工具

长期记忆是本文的"巩固式"核心。它由两部分构成:元数据 CRUD(业务层)+ 运行时生成/注入(harness 层)。

(1)实体模型 :以 Agent × 访客 为唯一维度,单字段 Markdown 维护记忆内容,并按固定维度分节:

shell 复制代码
Memory 实体(长期记忆,Agent × 访客 维度)
  id         记忆ID
  agentId    AgentID
  visitorId  访客标识
  content    记忆内容(Markdown,按维度分节,见下)
  lastMsgId  最后归档处理的消息ID(增量水位线)
  addTime    新增时间
  updateTime 更新时间

content 的固定维度(无内容的维度整节省略):
  ## 用户画像      身份、称呼、职业、所在地等
  ## 偏好习惯      沟通偏好、回答风格、常用语言与工具等
  ## 关键事实      用户明确告知、需长期记住的事实性信息
  ## 目标与意图    核心诉求、长期目标与待办事项
  ## 近期进展      最近对话中已推进的事项、结论与下一步

之所以用"单字段 Markdown + 固定维度",而非拆成多张表、多个字段,是因为:记忆要直接拼进系统指令给模型看,Markdown 天然就是模型的"母语",且维度枚举约束了抽取的稳定性,可读可控。

(2)运行时工具 MemoryTool(harness 层):承载三项底层能力,与业务解耦:

  • loadMemory(agentId, visitorId):按 Agent×访客 读取已归档记忆;
  • mergePrompt(basePrompt, memory):把记忆追加到系统指令末尾(记忆为空则原样返回);
  • generate(agent, oldMemory, newMsgs, maxLen):以「历史记忆 + 最新对话」为输入,调模型按固定维度抽取、合并、去重、淘汰过时内容,并定长截断(默认 2000 字符)。

注入与抽取的提示词关键约束如下(节选),它保证了抽取结果的格式稳定:

复制代码
你是长期记忆归档助手。请基于【历史记忆】与【最新对话】,按下列维度抽取并更新用户长期记忆。
要求:合并历史记忆与新对话信息,删除重复与已过时内容,保持精炼;总长度不超过 {maxLen} 字。

5.4、记忆归档:增量水位线 + 定时调度

记忆的"写"由 MemoryArchiveTool(harness 层)异步完成,是一条不打扰对话主流程的后台流水线:

ini 复制代码
调度节奏:CyclicThread 固定心跳(60s)
互斥竞争:Redis SETNX 抢锁(TTL=心跳间隔,仅作互斥;抢不到直接跳过)
增量判断:遍历开启记忆的 Agent → 每个访客 → 比较 max_msg_id 与水位线 last_msg_id
抽取生成:取水位线之后的新消息 → MemoryTool.generate(历史记忆 + 新消息) → 定长记忆
落库推进:MemoryMapper.upsert(按 agent_id + visitor_id 唯一键)→ 推进 last_msg_id

其精髓在"增量水位线":

ini 复制代码
水位线增量归档:
  SessionMsg:  ...  [id=100] [id=101] [id=102] [id=103] ...   (时间正序)
  上次归档水位线 last_msg_id = 101
                        └──────────┬──────────┘
                           本次归档:读取 id > 101 的新消息
                           generate(历史记忆 + 新消息) → upsert
                           推进水位线 last_msg_id = 103

last_msg_id 记的是"已处理到哪",于是每次归档只增量处理新增消息,而不是重扫全量历史;upsert(按 agent_id + visitor_id 唯一键)则保证同一用户只有一份最新记忆,天然幂等。这套设计在成本与正确性之间取得了很好的平衡。

5.5、语义记忆:知识库 RAG(Milvus)

语义记忆(共享知识)走知识库 + 向量检索,由 RagTool(harness 层)统一收敛,底层是 spring-ai + Milvus:

  • 隔离 :每个知识库一个集合 kb_base_{baseId},向量存储实例按知识库 ID 缓存复用(LRU 上限 128);
  • 向量化:分片(chunkSize / chunkOverlap)→ Document(含 docId / chunkIndex 元数据)→ 写入 Milvus(先清旧向量,支持重复向量化);
  • 检索 :similaritySearch 按 COSINE 相似度召回 Top-K,返回 {text, docId, chunkIndex, score};
  • 注入 :为对话装配 QuestionAnswerAdvisor,检索上下文自动注入系统提示。

值得注意的是降级策略:单库 RAG 装配失败(如向量库不可达)时跳过该库继续对话,并把降级提示写入思考流------这与长期记忆"注入失败则降级为原始系统指令"是同一套"记忆永不阻塞主流程"的容错哲学。

5.6、落地小结:XXL-AI 属于哪种范式

把 XXL-AI 的记忆体系对回第 3 节的坐标系,结论很清晰------它是一个以"范式三(巩固式)"为主、范式二(知识 RAG)为辅的混合架构:

记忆类型 XXL-AI 落点 对应范式
短期/工作记忆 SessionMsg(含 reasoning、状态机) 范式一(上下文内)
语义记忆(知识) knowledge 模块 + RagTool + Milvus 范式二(外部检索)
情景记忆(画像/偏好) Memory 实体 + MemoryTool + MemoryArchiveTool 范式三(巩固式)
程序记忆(技能) skill 模块 + SkillToolFactory 沙箱 范式三(可执行)

6、权衡与展望

巩固式记忆并非没有代价,值得在每个工程决策时反复掂量:

  • 抽取延迟:归档需额外调模型,故 XXL-AI 选择异步定时而非对话内同步,牺牲实时性换取主流程流畅;
  • 幻觉污染:模型抽取记忆可能"编造"或"误解",因此用固定维度 + 定长截断 + Markdown 规范化来约束,但仍需人工可干预(管理端支持查看/修改/删除记忆);
  • 定长截断丢信息:2000 字符上限意味着"近期进展"会不断覆盖旧的,本质是"滚动窗口式遗忘",这是有意的取舍而非缺陷;
  • 一致性:记忆与事实可能漂移,故注入时约定"冲突以当前表述为准",但更长期的纠偏仍是开放问题。

展望几个方向:遗忘策略 (按重要性/时效主动淘汰,而非简单定长截断)、多 Agent 共享记忆 (团队级 memory,如 2026 年兴起的 fleet-memory / RCLL 等共享记忆层)、记忆一致性治理(来源可追溯、可回滚)。这些也正是 Agent 记忆从"能用"走向"可靠"的下半场。

记忆系统的本质,是把 Agent 从"无状态函数"改造成"有状态的长期协作者"。而一条清晰的坐标轴------纵轴看层次、横轴看范式------是设计任何记忆系统时都值得先铺好的那张地图。

资料

复制代码
相关推荐
hpoenixf1 小时前
如何给投研 Agent 配上 Subagent:从上下文隔离到专业化协作
agent
墨心@2 小时前
图片归一化
agent·pi·coding agent·harness
黄鹂鸟科技3 小时前
进销存系统设计要点:从采购计划、库存监控到成本核算
后端·物联网·系统架构
撸串-研究生3 小时前
基于Spring Boot的智慧社区垃圾分类与回收系统的设计与实现【附源码】
spring boot·后端·分类·垃圾分类·社区管理
墨心@3 小时前
Pi 项目分析
agent·coding agent
技术小结-李爽4 小时前
【工具】怎么在终端中启动springboot项目?
java·spring boot·后端·maven
漂流瓶jz4 小时前
【AI】大模型参数训练原理:Softmax/损失函数交叉熵/反向传播/梯度下降优化器/学习率调度器/训练数据划分
人工智能·神经网络·llm
今年下半年4 小时前
AI智能体项目实战记录(05):RAG项目实战之向量知识库milvus部署
人工智能·llm·milvus·rag
乌暮4 小时前
从 `println` 到生产级日志:Spring Boot 日志体系完全指南
java·开发语言·jvm·spring boot·后端·学习·面试