博客

多 Agent 记忆设计实现思路

围绕每个 Agent 的独立记忆、项目总记忆,以及短期、长期、重要记忆分层的实现草案。

发布: 分类: 运行时

一个可用的多 Agent 记忆系统,不应该像所有 Agent 都能随意改写的共享笔记。Eva-CLI 可以把记忆作为 Runtime 托管服务来设计:每个 Agent 有自己的独立记忆空间,项目本身有一个总的记忆模块,并且只有经过提升和校验的事实才能进入项目级共享记忆。

每个 Agent 的私有记忆通过提升策略进入短期、长期和重要项目记忆,并由 ContextBuilder 检索。
每个 Agent 保留私有记忆,Runtime 将通过校验的事实提升到短期、长期或重要项目记忆层。

记忆归属

第一层边界是所有权。Agent 记忆归属于单个 Agent 身份,用来记录本地偏好、任务历史、能力观察和工作假设。项目记忆归属于当前 workspace,用来保存跨 Agent 都应该继承的事实,例如架构决策、可复用约束、发布记录、用户偏好和已知风险。

Agent 可以通过 Runtime 读取项目记忆,但不应该直接写入项目记忆。写入需要走提升路径,记录来源 Agent、证据、置信度、时效性和提升原因。这样项目记忆不会退化成未经整理的对话流水账。

项目记忆分层

项目总记忆模块可以按保留策略和检索策略拆成多个层。短期记忆是会话或任务窗口,保存当前目标、最近工具结果、未解决问题和临时假设。长期记忆保存稳定事实,包括仓库约定、架构决策、依赖选择和重复工作流。重要记忆是受保护的高信号约束层,应该优先于普通长期记忆被检索,例如安全规则、不可逆操作限制和用户级偏好。

这些层可以使用同一种记录结构,但采用不同策略。一条记忆记录可以包含 scope、layer、owner、title、body、tags、source、confidence、priority、created_at、last_accessed_at、expires_at 和 revision。短期记忆可以积极过期。长期记忆需要去重和周期性摘要。重要记忆需要显式提升、更强的来源证明和更小的评审入口。

写入路径

Runtime 应该在持久化前规范化每一次写入请求。一个清晰的写入路径是:捕获事件,判断候选记忆层,检查权限,与相似记录合并,附加来源信息,然后写入追加式 revision。对于项目记忆,Agent 可以提出候选记忆,但最终由 memory policy 决定它进入短期、长期还是重要记忆层。

这样冲突处理会更具体。如果两个 Agent 的判断不一致,记忆模块先保留独立 claim,直到证据能消解冲突。如果事实过期,系统应该标记为 superseded,而不是静默删除。Agent 读取时看到当前摘要,调试时仍然可以追溯历史。

读取路径

上下文构建必须有选择性。ContextBuilder 可以先检索重要项目记忆,再检索相关长期项目记忆,然后检索请求方 Agent 的私有记忆,最后补充与当前任务相关的短期记忆。排序可以综合 tags、语义相似度、最近访问时间、优先级、置信度和当前 topic。

关键规则是控制上下文预算:记忆检索输出的应该是紧凑 context pack,而不是完整 dump。每个 context pack 可以包含必须遵守的约束、可能有用的事实、开放问题和来源。这样 Agent 能保持上下文连续,同时不会挤占当前任务信息。

实现草案

务实的实现可以从 Rust 托管的 memory service 开始,并暴露一组很小的 API:write memory、propose project memory、promote memory、search memory、summarize memory 和 expire memory。存储层可以先使用结构化 JSON 或 SQLite 记录,等语义检索需求明确后再加入向量索引。

Lua Agent 通过能力校验后的函数调用这些 API。Rust Runtime 负责权限、持久化、提升规则和压缩任务。这样 Agent 行为仍然可以热更新,而记忆完整性留在稳定的 Runtime 边界内。

为什么这样设计

每个 Agent 的独立记忆保留了专业化能力。项目总记忆让整个 workspace 拥有连续性。短期、长期和重要记忆分层,可以避免临时上下文、持久知识和强约束挤在同一个桶里互相干扰。最终得到的是一个能随 Agent 数量增长、同时仍然可追溯、可控制的记忆系统。