/always-on-agent-architecture — 构建永不遗忘的代理
你正在为一个始终在线的AI代理设计架构,该代理具备情景记忆。这不是一个拥有长上下文窗口的聊天机器人。这是一个跨会话持久化状态、管理自身记忆层次、作为服务运行,并在数周数月内保持身份的系统。核心洞察:将LLM视为一个在受管内存上运行的CPU,而不是一个无状态函数。
决策点
记忆框架选择树
Q1: 你需要一个完整的代理运行时(服务器、API、工具)吗?
├─ 是 → 使用 Letta(最完整、生产就绪)
└─ 否,我有自己的代理循环
├─ Q2: 你需要时间/关系追踪吗?
│ ├─ 是 → 使用 Zep/Graphiti(最佳时间知识图谱)
│ └─ 否 → 前往 Q3
│ ├─ Q3: 你需要图+向量的混合吗?
│ │ ├─ 是 → 使用 Mem0(图模式)
│ │ └─ 否 → 前往 Q4
│ │ ├─ Q4: 已经在用 LangGraph 了吗?
│ │ │ ├─ 是 → 使用 LangMem
│ │ │ └─ 否 → 使用 pgvector 或 Chroma
└─ 想要零依赖? → 自定义 SQLite + 本地嵌入
核心记忆驱逐触发器
| 触发器 | 阈值 | 操作 |
|---|---|---|
| 大小溢出 | 核心记忆 > 4KB | 总结最近最少使用的块,将摘要移至存档 |
| 时间衰减 | 数据超过30天未使用 | 标记为压缩审查 |
| 相关性下降 | 访问分数 < 0.3 | 移至存档记忆并附带衰减标签 |
| 用户覆盖 | 用户说“忘记X” | 立即移除 + 存档墓碑标记 |
| 冲突检测 | 存储了矛盾的事实 | 提示代理协调或询问用户 |
向量数据库选择标准
如果 查询延迟要求 < 10ms AND 数据量 > 100M 向量:
→ 使用 Qdrant(针对速度优化)
否则如果 已经在使用 PostgreSQL:
→ 使用 pgvector(单一数据库,更简单的运维)
否则如果 需要混合搜索(关键词 + 语义):
→ 使用 Weaviate(最佳混合)
否则如果 偏好零运维:
→ 使用 Pinecone(完全托管)
否则:
→ 使用 Chroma(本地优先,简单API)
记忆层路由决策
输入: 用户消息或代理观察
│
├─ 包含身份/偏好更新?
│ └─ 是 → 更新核心记忆,立即持久化
├─ 需要对话上下文?
│ └─ 是 → 搜索回忆记忆(对话历史)
├─ 需要事实知识?
│ └─ 是 → 搜索存档记忆(向量存储)
└─ 需要外部数据?
└─ 是 → 使用外部工具(API、文件等)
故障模式
记忆损坏级联
症状: 代理人格漂移、矛盾响应、核心记忆冲突 根本原因: 对核心记忆的并发写入未加锁,或部分更新失败 检测规则: 如果核心记忆大小突然下降超过50%或包含格式错误的JSON/YAML 恢复步骤:
- 立即停止代理以防止进一步损坏
- 从最近已知的良好备份(1小时以内)恢复核心记忆
- 回放自备份以来的对话日志以重建丢失的更新
- 在重启前对核心记忆更新实施写锁定
向量搜索退化
症状: 搜索结果越来越不相关,代理找不到最近存储的事实 根本原因: 嵌入模型漂移、索引损坏、或缺少记忆压缩 检测规则: 如果对已知查询,前3个结果的平均余弦相似度 < 0.7 恢复步骤:
- 对100个向量的随机样本运行嵌入一致性检查
- 如果超过10%显示异常嵌入,重建整个索引
- 实施嵌入模型版本固定
- 添加嵌入漂移监控以防止复发
持久化层死锁
症状: 代理在记忆操作上挂起,数据库连接超时 根本原因: 同时读写相同记忆块,连接池不足 检测规则: 如果记忆操作耗时超过30秒或数据库显示锁等待超时 恢复步骤:
- 杀死挂起的连接以释放锁
- 对记忆操作实施指数退避重试逻辑
- 添加具有最大连接限制的连接池
- 审查记忆更新的事务隔离级别
上下文窗口爆炸
症状: API成本飙升、响应延迟增加、令牌限制错误 根本原因: 核心记忆膨胀,每次查询检索过多存档块 检测规则: 如果每次请求的平均令牌数超过模型上下文限制的80% 恢复步骤:
- 审计核心记忆大小 - 压缩或归档过大的块
- 减少存档搜索结果数量(从10减少到5)
- 在LLM调用前实施令牌计数
- 添加成本监控警报,超过$1/对话时触发
内存泄漏 - 无限制增长
症状: 数据库大小线性增长,搜索性能随时间下降 根本原因: 无记忆压缩、重复事实插入、缺少垃圾回收 检测规则: 如果正常使用下总记忆大小每月增长超过100MB 恢复步骤:
- 跨存档记忆运行事实去重(余弦相似度 > 0.92)
- 对超过7天的回忆记忆实施对话摘要
- 添加相关性评分,自动修剪低分记忆
- 安排每周压缩任务
实战案例
示例:构建个人研究助手
场景: 设计一个代理的架构,它可以帮助进行技术研究,记住你的偏好,并在数月内积累知识。
步骤 1 - 记忆层设计
核心记忆 (2KB):
- 用户名: "Sarah"
- 研究领域: ["机器学习", "分布式系统"]
- 首选论文来源: ["arxiv", "acm digital library"]
- 写作风格: "详细且包含代码示例"
- 当前项目: "分布式训练优化"
回忆记忆:
- PostgreSQL 中的所有对话,支持全文搜索
- 30天保留窗口,之后摘要化
存档记忆:
- 论文摘要、提取的见解、代码片段
- PostgreSQL 上的 pgvector(已在回忆记忆中使用)
- nomic-embed-text 用于本地嵌入(隐私 + 成本)
步骤 2 - 框架选择决策 按照决策树:
- 需要完整代理运行时?否(构建自定义)
- 需要时间追踪?否(研究事实大多与时间无关)
- 需要图+向量?否(简单的语义搜索就足够了)
- 已经在用 LangGraph?否
- → 决策:pgvector + PostgreSQL
步骤 3 - 代理循环实现
async def research_step(user_query: str):
# 加载核心记忆
core = load_core_memory() # 用户偏好、活跃项目
# 检查查询是否与当前项目相关
if "optimization" in user_query.lower():
# 搜索存档中的项目特定知识
relevant_papers = search_archival("distributed training optimization")
context = f"当前项目上下文: {relevant_papers}"
else:
# 搜索通用领域知识
context = search_archival(user_query)
# 使用核心记忆 + 检索到的上下文构建提示
system_prompt = f"""
你是 Sarah 的研究助手。
用户偏好: {core['preferences']}
当前项目: {core['current_project']}
检索到的上下文: {context}
"""
response = await llm.chat([
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query}
])
# 持久化交互
save_to_recall(user_query, response)
return response
新手可能会遗漏的:
- 在存档中存储原始论文而不是提取的见解
- 没有实现对话搜索(回忆记忆)
- 在核心记忆中放入过多内容(包含50个条目的研究领域列表)
- 没有记忆压缩策略
专家会注意到的:
- 核心记忆专注于“工作身份”而非知识
- 存档记忆存储经过整理的事实,而非原始文档
- 在检索之前实现搜索(代理决定什么相关)
- 从第一天开始规划记忆增长
质量门禁
部署验证检查清单
- 记忆延迟 SLO: 核心记忆加载 < 100ms,存档搜索完成 < 500ms
- 记忆一致性: 核心记忆在代理重启后无损坏地存活(通过故意关闭进程测试)
- 搜索相关性: 对于已知查询,前3个存档结果的余弦相似度 > 0.6
- 记忆大小规则: 核心记忆 ≤ 4KB,回忆保留 ≤ 30天,每个存档块 ≤ 1KB
- 持久化耐久性: 所有记忆更新在数据库重启后存活(已验证ACID合规性)
- 成本控制: 在每天100次对话的情况下,记忆操作成本 < $0.01/对话
- 压缩计划: 记忆压缩每周运行,并将总大小减少 ≥ 10%
- 身份一致性: 代理人格在50+次对话会话中保持稳定
- 冷启动恢复: 代理优雅地处理空记忆状态(引导流程正常工作)
- 备份验证: 记忆备份成功恢复并保留代理身份
非此技能边界
请勿将此技能用于:
- 选择代理训练数据 → 使用
/always-on-agent-inputs——该技能涵盖向代理提供什么数据,本技能涵盖如何存储和检索它们 - 头脑风暴代理应用 → 使用
/always-on-agent-applications——该技能涵盖用例构思,本技能涵盖技术实现 - 代理安全与隐私 → 使用
/always-on-agent-safety——该技能涵盖数据治理、同意和安全;本技能假设这些已经设计好 - 通用代理模式 → 使用
/agentic-patterns——该技能涵盖ReAct循环、工具使用、规划;本技能涵盖底层的持久化层 - 一次性代理任务 → 使用
/agent-creator——如果代理不需要跨会话记忆,就不需要始终在线的架构 - 数据库模式设计 → 本技能假设你理解基本数据库概念;模式优化请使用特定数据库的技能
- 成本优化策略 → 本技能提到了成本考量但未深入优化;请委托给特定于成本的技能