在大语言模型(LLM)驱动的 Agent(智能体)开发中,人们常说:“上下文即视野,记忆即灵魂”。大语言模型本质上是无状态的(Stateless),它无法自动记住以往的对话与交互。因此,构建一个高效、安全、具备认知连续性的 Agent,必须依赖坚实的底层基础设施——上下文工程(Context Engineering)与记忆系统(Memory System)。
本文结合学术理论、业界大厂最佳实践(如 AWS Bedrock AgentCore Memory, Letta/MemGPT, Mem0, LangMem)以及具体开源项目 Domour 架构的设计细节,深入剖析 AI 智能体上下文与记忆的设计逻辑与工程落地路径。
一、 上下文工程与记忆系统概述
在工程上,我们可以对上下文工程做一个明确的定义:
上下文工程是将复杂的非结构化/半结构化信息重新概念化为一组动态、结构化的信息组件,通过来源获取、过滤、脱敏、压缩等管道处理,并在推理前进行编排,使其符合 LLM 输入规范的全部过程。
简单来说:上下文工程 = 视野控制 + 通信协议 + Token 经济 + 持久化方案。
而记忆系统则作为上下文的“仓库”,负责跨会话、跨任务沉淀知识和经验。两者紧密共生:记忆系统是静态的“知识仓库”;上下文工程则是动态的“调度员”与“优化器”。
1.1 记忆的分类体系
业界(如 LangMem、AWS 实践)通常借鉴人类心理学对记忆的分类,将 Agent 的记忆分为三大类:
| 记忆类型 | 人类心理学对应 | 智能体实现方式 | 作用与应用场景 |
|---|---|---|---|
| 短期工作记忆 (STM) | 即时处理与瞬时记忆 | 滑动窗口缓存、工作缓冲区内临时变量 | 维护当前对话主题、暂存中间推理步骤与工具执行结果。 |
| 长期情节记忆 (Episodic) | 过去的经历与事件记录 | 历史完整对话及推理链的结构化存储 | 从过往经验中学习。例如客服系统回忆起上一次的修改方案。 |
| 长期语义记忆 (Semantic) | 事实知识、客观规律、用户画像 | 向量存储(向量检索)、语义提取的 Profile 键值对 | 跨会话的背景知识,如用户的个人偏好、命名习惯、架构规范。 |
| 长期程序记忆 (Procedural) | “如何做”的实操技能与动作指南 | 系统提示词演进、微调 (Fine-Tuning) | 帮助 Agent 学习最有效的行为模式,指导具体的任务执行序列。 |
二、 行业前沿:主流记忆框架分析
针对上述记忆模型,业界涌现出多种优秀的开源及商业实践:
- Mem0(双 LLM 架构)
- 机制:通过双 LLM 架构分工(一个提取信息,一个判断决策),对用户输入进行上下文感知的智能提取。
- 特点:具备智能去重和冲突解决能力。当发现与已有记忆冲突的信息时(如用户改变了偏好),能自动更新或擦除旧记忆。
- 存储:支持集成 Aurora Serverless(向量存储)及 Neptune Analytics(图数据库关系)。
- Letta / MemGPT(虚拟内存机制)
- 机制:将 LLM 类比为 CPU,把上下文窗口视为“内存”,外部数据库视为“外存”。
- 特点:当内存写满时,系统通过工具(如
core_memory_append/core_memory_replace)将老对话压缩存入“外存”,在需要时再捞回。
- LangMem(长短期个性化进化)
- 机制:专注于 LangGraph 系统的记忆管理,通过后台异步服务提取、汇总和清理记忆。
- 特点:提供语义记忆与情节记忆 of 优雅提取,支持跨 Agent 的共享内存。
- Amazon Bedrock AgentCore Memory(完全托管)
- 机制:开箱即用的分层托管记忆。支持
SemanticMemoryStrategy(提取事实)与UserPreferenceMemoryStrategy(捕获偏好)。 - 特点:服务在后台异步提炼知识,无需开发者运维底层资源,并支持将记忆包装为标准工具(Memory as a Tool),让模型自主决定何时读写记忆。
- 机制:开箱即用的分层托管记忆。支持
三、 Domour 双层两级上下文架构设计
Domour 是一个多 Agent 协同的开发框架。为解决 Token 爆炸、多模型适配、跨 Agent 视野安全控制等痛点,其上下文系统采用了**“全局共享 + 实例独占”**的两级架构。
具体架构设计请参见:
- 总体设计文档:agent-context.md
- 数据流设计文档:context-data.md
- 源码借鉴自 Gemini CLI 的上下文图分析:gemini-context.md
3.1 双层两级存储结构
MemoryContextManager (全局共享记忆层 — 跨所有 Agent 共享同一个实例)
├── Tier 1: 全局规则 (~/.domour/*.md) & 技能元数据 [L1 缓存: 30min TTL]
├── Tier 2: 项目记忆 (<.project>/.domour/*.md) [L1 缓存: 30min TTL]
└── Tier 3: JIT 动态文件发现 (discoverContext) [L1 缓存: 5min TTL]
│
▼ 组装与共享 (System Prompt, L1/L2 Cache)
ContextManager (每个 Agent 实例独占 — 隔离的会话工作区)
├── Pristine Graph: 不可变备份图(记录“发生了什么”,用于回滚与容错)
├── STM 环状缓冲区: 活跃工作区(包含不受 Pipeline 压缩的最近 N 轮保护区)
└── Pipeline 处理器链: ToolMasking → BlobDegradation → NodeDistillation → NodeTruncation
- MemoryContextManager(全局共享层):
- 管理 Tier 1~3 的知识与文件。
- 采用 Otter(基于 W-TinyLFU 淘汰算法)实现的双 TTL L1 缓存体系。Tier 1/2 使用 30 分钟长缓存,Tier 3 的 JIT(Just-In-Time)临时发现文件使用 5 分钟短缓存。
- ContextManager(Agent 实例独占层):
- 维护专属的 Pristine Graph(不可变原始图记录)与 STM 环状缓冲区。
- 动态匹配 Agent 脑区角色与 LLM 上下文窗口限制,进行数据流的加工与组装。
3.2 跨脑区隔离与通信协议
为了安全拦截与规避不必要的 Token 开销,各脑区(组件)之间的上下文可见性被严格限制。它们通过 ContextBridge 的 Pub/Sub Channel 模型异步传递消息,并使用不同的 RenderFor* 函数导出精简版上下文:
- Brain (Cerebrum - 认知推理):使用
RenderForAPI()导出完整消息,拥有最大的视野,进行规划与自省。 - Cerebellum (小脑 - 逻辑编排):使用
RenderForCerebellum(),仅能看到任务描述、意图及相关的工具 schema。小脑执行战术时无需理解大脑沉重的推理细节。 - Diencephalon (间脑 - 格式中继):使用
RenderForDiencephalon()获得精简的 LLM Content[]。间脑只作路由中继,不存储具体推理过程。 - Brainstem (脑干 - 运动与拦截):零上下文。不持有
ContextManager,仅接收来自小脑的具体执行指令,并进行安全策略(Veto)校验。
四、 Dapr Durable Agents:分布式状态与长周期记忆
Dapr Agents 是 Dapr 社区为了解决多智能体在分布式、异构生产环境下的可扩展性、状态持久性而设计的一套框架。在 Domour 项目的架构目标中,Dapr 充当了“宏观外壳”与“分布式神经系统”,为其提供健壮的长周期运行体质。
在记忆与上下文处理方面,Dapr Durable Agents 具备以下核心特征:
- 工作流状态持久化 (Workflow State & Durable Memory): DurableAgent 基于 Dapr Workflows 构建,具有“确定性执行”和“事件回溯”特性。Agent 的执行进度、工具调用历史与中间状态会被自动作为事件日志进行事件溯源(Event Sourcing)。在进程因网络或资源原因意外中断重启后,Dapr 可以通过状态重放,在不重复调用 LLM 的情况下,让 Agent 极其精确地从上次中断位置“原地复活”。
- 底层状态存储解耦 (Conversation Memory Backend): Dapr 屏蔽了底层数据库细节,支持 CosmosDB、PostgreSQL、Redis 等 28+ 种主流状态存储。Durable Agents 采用虚拟 Actor 架构封装,将会话历史和状态作为一个 Actor 实例的属性进行持久化,高并发场景下能由 Placement 服务自动在宿主集群中调度和隔离。
- 运行时基础设施要求:
- 状态组件 (
state.*):强制要求存储组件支持多事务(Transactions API),且 yaml 声明中必须显式设置actorStateStore: "true"。 - 感官中继 (
conversation.*):Dapr 1.17+ 提供了统一的 Conversation API,屏蔽了 OpenAI、Gemini、DeepSeek 等不同 LLM 提供商接口差异,由 Sidecar 统一进行速率限制与 Key 轮转,这与 Domour 中的间脑(Diencephalon)设计高度契合。 - 异步反射弧 (
pubsub.*):通过异步发布订阅总线在各个 Agent 节点之间以事件驱动(Pub/Sub)模式传递触发条件与数据。
- 状态组件 (
五、 Eino 框架:微观思维图与强类型上下文
相比于 Dapr 处理宏观的节点通信和持久化,Eino(字节跳动开源的 Go 语言 Agent 框架)则专注于微观思维的编排。在 Domour 的定位中,Eino 类似于“大脑皮层褶皱”,代表了智能体的“智商”。
在上下文管理和推理流程中,Eino 通过以下机制提供支持:
- 基于 DAG 的状态与思维编排 (Reasoning Graph & State Orchestration): Eino 的核心是类型安全的图(Graph)编排引擎。它允许开发者通过定义 Node、Edge 和动态 Branch 来组装 Prompt 链、Tool Call 路由和反思循环(Reflection Loop)。
- 细粒度强类型上下文传递 (Context & State Flow):
在 Eino 图中流转的不仅是 Go 标准的
context.Context,还包含强类型的思维状态(State)。在执行推理图的不同分支(例如,从“规划Node”路由至某个具体的“工具Node”)时,微观的输入与输出参数能够被局部裁剪并强类型还原,避免了由于通配interface{}导致的运行时解析错误。 - Eino Inside, Dapr Outside 的协作模式:
- Eino 负责微观推理:构建 ReAct 图、Prompt 组装、敏感字段的脱敏,控制局部 Token 消费。
- Dapr 负责宏观包装:包装 Eino 逻辑,为多实例提供服务发现、分布式追踪、工作流中断恢复和异步事件接收。
- 平滑降级:在单机、边缘或嵌入式设备等无 Dapr 运行时的局限环境下,Domour 可以抛弃 Dapr 外壳,依靠 Eino 的微观编排原地退化运行(降级为本地 Go Channels 和 MemoryStore),提供了极佳的跨设备灵活性。
六、 关键工程落地细节与优化博弈
在将上述设计落地为代码时,需要面临性能、成本、吞吐量和准确性之间的多重博弈。结合专家的评审反馈与 critique,我们总结了以下 6 大工程优化点:
6.1 Pristine Graph 与 Working Buffer 的“双活”容错设计
在多步工具调用或长链路任务中,Agent 极易因为 LLM 幻觉或外部异常陷入死循环。
- 设计:ContextManager 同时维护不可变备份
Pristine Graph和可变的Working Buffer。 - 价值:一旦发现任务失败,系统可以直接基于 Pristine Graph 回滚至第 $N$ 步状态重试,重新选择执行分支,实现极高的容错性。
6.2 缓存友好型提词布局(Cache-Friendly Layout)
对于目前主流大模型(如 DeepSeek, Gemini),其 Context Caching (提示词缓存) 采用“严格前缀匹配”(Prefix Matching)原则。如果前部有 1 个 Token 发生变化,后面的全量缓存就会雪崩式失效(Bust)。
- 反面教材:把频繁变动的 JIT(Tier 3)和 NodeIntent(意图识别)作为
Front Matter置于提词最前端。哪怕只变动了 1 毫秒的时间戳,也会摧毁后续几万 Token 的缓存。 - 黄金法则:“静态在前,动态在后;历史递增,动态垫底”。
[System Message] <- Tier 1 + Tier 2 (绝对静态系统提示词,100% 缓存命中)
[User/Model Msg] <- History Message Stream (多轮历史递增,前缀稳定,高命中率)
[Last User Msg] <- JIT Context + NodeIntent + User Prompt (高频变动的当前输入,放置于最后,不破坏前面的前缀)
6.3 避免 Payload interface{} 的多模型适配阵痛
- 隐式隐患:如果在 Go 中将
ConcreteNode.Payload定义为interface{}直接存储 LLM SDK 返回的 Content 对象,当持久化层(Dapr/Redis)进行反序列化时,结构体类型会丢失并退化为map[string]interface{},且不同 LLM 厂商的结构体差异巨大。 - 优化策略:在 ConcreteNode 中使用 Domour 自研解耦的通用数据结构(如
Text,ToolCalls),只在最终发送给模型的最后一步(Render动作中),通过专门的Adapter翻译为对应厂商 SDK 的具体对象。
6.4 解决 Pipeline 压缩的延迟爆炸问题
- 隐式隐患:Pipeline 管道执行的
NodeDistillation(节点蒸馏)和StateSnapshot(摘要合成)通常需要调用一次轻量级 LLM。如果在同步请求链路中触发,会造成严重的卡顿(推理延迟 + 摘要延迟)。 - 优化策略:
- 保证摘要更新是增量/滚动式的(
RollingSummary_New = Summarize(Old_Summary + Expired_Turn))。 - 将 Pipeline 的压缩行为设计为异步 (Async) 或懒加载 (Lazy),移交后台工作流异步处理,不阻塞主会话逻辑。
- 阶梯式触发:例如限制安全水位为 32 轮,1~32 轮只追加,一旦达到 32 轮,一次性把前 16 轮打包成 Snapshot。
- 保证摘要更新是增量/滚动式的(
6.5 锁冲突与 MCM 只读化原则
- 隐式隐患:由于
MemoryContextManager是跨所有子 Agent 共享的。若多个并发的子 Agent 通过discoverContext同时写入项目记忆,Version 的乐观锁会导致频繁的写入冲突。 - 优化策略:明确在单轮会话中,所有的 Agent 对 MCM 都是只读 (Read-Only) 的。所有的中间状态只写入自己独占的工作区。会话结束或达到某一里程碑时,再由主编排器(Orchestrator)合并去重后原子化写回。
6.6 复杂图遍历性能退化问题
- 隐式隐患:当节点存在 1:1 替换(Masking)或 N:1 摘要时,Graph 拓扑结构会极为复杂。如果每次 Render 都要遍历关系链去寻找原始节点,算法复杂度将退化为链表遍历。
- 优化策略:在 Working Buffer 中提供扁平化的索引视图
ActiveNodeIDs []string,记录当前生效的节点 ID。Pipeline 处理后直接更新此数组,Render 阶段即可 $O(1)$ 通过 map查询节点。
七、 总结与展望
在 Agentic Workflow 成为行业主流 of 今天,如何精细化地设计上下文工程和记忆系统,是把 Agent 从“Demo玩具”推向“工业级生产系统”的分水岭。
Domour 框架所实践的“双活图结构(Pristine vs Working)”、“缓存友好提词重构”以及“多脑区隔离的 Bridge 设计”,不仅完美契合了 Dapr Sidecar 持久化的分布式演进,更通过细致入微的 Token 预算管理降低了生产成本。未来,随着向量存储及 LTM 后端的原生融合,智能体将拥有更加强大的跨越时间和空间的自我演进能力。
本文参考自:
- [Agentic AI 基础设施实践经验系列(三):Agent 记忆模块的最佳实践]
- [多 Agent 上下文共享模式探讨 - Google Gemini 评估报告]
- Domour 内部设计文档集:docs/design/