独立 Memory Agent 模式
独立 Memory Agent 模式
学习目标
读完本章后,你将能够:
- 理解独立 Memory Agent 与主对话 Agent 解耦的架构优势
- 掌握 Memory Agent 的专用工具设计(
set_memory/delete_memory) - 实现 Token 预算管理与溢出保护机制
- 处理不同模型提供商的 Memory Agent 适配
前置知识
核心概念
1. 为什么需要独立的 Memory Agent
大多数聊天系统将记忆处理嵌入主对话流程:模型在生成回复的同时决定是否存储记忆。这种做法有几个问题:
- 上下文污染:记忆管理指令占用主 Agent 的 prompt 空间
- 性能影响:记忆操作(DB 写入、Token 计数)阻塞主回复的流式输出
- 模型负担:主模型同时承担对话生成和记忆管理两个不同任务
独立 Memory Agent 模式通过解耦解决这些问题:
2. Memory Agent 的架构设计
独立的 Memory Agent 拥有完整的 Agent 栈,但配置与主 Agent 不同:
关键隔离点:
| 维度 | 主对话 Agent | Memory Agent |
|---|---|---|
| Run 实例 | 独立 | 独立 |
| LLM 配置 | 用户选择 | 固定小型模型(如 gpt-4.1-mini) |
| 流式输出 | 是 | 否(disableStreaming: true) |
| 工具集 | 业务工具 | 仅 set_memory + delete_memory |
| 执行时机 | 同步阻塞 | 异步后台 |
| 温度 | 用户配置 | 固定低温度(如 0.4) |
3. 专用工具设计
Memory Agent 的工具与常规工具不同,采用 content_and_artifact response format:
工具: set_memory参数: { key: string, value: string }返回: [content: 确认消息, artifact: 结构化操作结果]Artifact 的结构化设计允许前端展示记忆操作的可视化反馈:
双错误类型设计:
already_exceeded:Token 预算已完全耗尽,不再接受任何新记忆would_exceed:当前操作会导致超限,拒绝本次写入
4. Token 预算管理
Memory Agent 实现了精细的 Token 预算控制:
remainingTokens = tokenLimit - totalTokens预算检查发生在两个时机:
- 预处理阶段:如果
remainingTokens <= 0,直接进入isOverflowing状态,拒绝所有新写入 - 写入阶段:计算
newTotalTokens = totalTokens + tokenCount,如果超出则拒绝
预算感知指令:当接近预算上限时,Memory Agent 的系统提示中会注入预算状态:
# Memory Status:Current memory usage: 850 tokensToken limit: 1000 tokensRemaining capacity: 150 tokens5. 模型适配策略
不同模型提供商对 Memory Agent 的配置要求不同:
Bedrock 适配:
- Bedrock 的 Converse API 要求对话以用户消息开始,不支持纯系统提示
- 解决方案:将系统提示和记忆状态合并到第一个用户消息中
GPT-5+ 适配:
- GPT-5+ 模型不支持
temperature参数 maxTokens需要迁移到modelKwargs中(max_completion_tokens或max_output_tokens)
Anthropic Thinking 模式:
- 当启用 thinking 模式时,必须删除
temperature参数 - 否则 API 会返回参数冲突错误
陷阱与对策
陷阱 1:记忆内容污染主对话上下文
问题:SKILL.md 或记忆指令直接注入主 Agent 的 prompt,挤占了用户的实际对话内容。
对策:Memory Agent 完全独立运行,不占用主 Agent 的 prompt 空间。记忆结果通过异步回调写入 DB,主 Agent 在后续 turn 中从 DB 读取格式化后的记忆。
陷阱 2:Token 计数不一致
问题:Memory Agent 使用的 Tokenizer 与主 LLM 的 Token 计算方式不同,导致预算不准确。
对策:统一使用相同的 Tokenizer(如 o200k_base),并在写入后验证实际 Token 数与预算的一致性。
陷阱 3:Memory Agent 失败阻塞主流程
问题:Memory Agent 执行失败(如 DB 连接超时)导致主回复延迟。
对策:Memory Agent 异步执行,失败仅记录日志,不影响主回复的流式输出。使用 try-catch 包裹整个 processMemory 调用。
陷阱 4:记忆操作 Artifacts 在 headersSent 后无法发送
问题:主回复已经开始流式输出(res.headersSent === true),Memory Agent 的 artifact 无法通过常规 HTTP 响应发送。
对策:检测 headersSent 状态,如果已发送,通过 GenerationJobManager.emitChunk 走可恢复流式通道发送 attachment 事件。
设计权衡
独立 Agent vs 内嵌记忆
| 维度 | 独立 Memory Agent | 内嵌记忆处理 |
|---|---|---|
| 上下文占用 | 零(独立 prompt) | 高(占用主 prompt) |
| 实现复杂度 | 高(两套 Agent 栈) | 低 |
| 故障隔离 | 完全隔离 | 共享故障域 |
| 可观测性 | 独立指标和日志 | 混合在主日志中 |
| 模型选择灵活性 | 可为记忆选择最优模型 | 受限于主模型 |
| 适用场景 | 大规模、多用户、高频记忆 | 小规模、简单记忆需求 |
何时选择独立 Memory Agent
适合:
- 用户数量多,记忆操作频繁
- 需要使用不同于主模型的小型/低成本模型处理记忆
- 需要精细的 Token 预算和配额管理
- 需要独立的记忆操作可观测性
不适合:
- 简单的”记住我说的最后一句话”场景
- 系统资源极度受限(维护两套 Agent 栈有开销)
- 对延迟极度敏感,无法承受异步处理