Skip to content

jasonno1/multi-agent-memory

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

多Agent记忆管理方法论

License: MIT Status: Stable

面向多智能体系统的记忆管理方案文档。解决 Agent 记忆隔离、子 Agent 结果丢失、会话上下文断裂和记忆膨胀四大痛点。适用于 Agent 开发者、多智能体系统架构师,以及 Hermes / LangChain / CrewAI 等框架的用户。


目录

  1. 问题陈述:为什么需要多Agent记忆管理
  2. 方案B架构概览
  3. 五大核心原则详解
  4. 方案A vs 方案B 对比
  5. 记忆页结构规范
  6. 子Agent生命周期管理
  7. GBrain作为可选后端
  8. 快速开始 / 迁移指南

1. 问题陈述:为什么需要多Agent记忆管理

在 Hermes 多智能体体系中,主Agent(如 lee)通过 agency-agents-zh 角色库调度 305 个专业角色Agent来完成不同任务。这个架构在分工专业化方面表现出色,但随之而来的是四个核心痛点:

痛点一:Agent记忆隔离导致重复提问

每个角色Agent以独立会话方式运行,会话之间不共享任何记忆。当用户连续两次调度同一个角色Agent(例如让"前端审查Agent"审查两个不同的组件),第二次调度时Agent对用户偏好、上次审查中发现的问题模式、既定的代码风格偏好一无所知。用户不得不重复告知相同的上下文信息,这是时间和token的双重浪费

痛点二:子Agent工作结果丢失

主Agent通过 delegate_task 创建的子Agent在工作完成后,其结果仅存在于该子Agent的瞬时会话中。一旦会话结束,子Agent被销毁,其产出的分析结论、代码片段、决策依据也一并消失。后续如果需要回溯"这个决定是谁做的、基于什么理由做的",无迹可寻。

痛点三:会话切换后上下文断裂

每次主Agent开启新会话时,之前调度过的角色Agent积累的经验和教训全部归零。Agent体系没有"成长"可言——这意味着第100次使用和第1次使用没有任何区别

痛点四:记忆膨胀与无关信息污染

如果不加控制地将所有历史信息塞进Agent上下文,又会走向另一个极端:上下文窗口被大量无关信息占据,推理质量下降,token消耗飙升,响应速度变慢。

需要解决的核心问题

如何让每个角色Agent拥有"个人记忆"并能持续成长,同时避免记忆膨胀污染上下文,还要确保子Agent的工作成果不丢失?

这正是方案B要系统化解决的问题。


2. 方案B架构概览

2.1 记忆流动全景

方案B的核心设计理念是:每种一级Agent拥有一块独立的、持久化的记忆空间,主Agent作为记忆的调度者和守门人

                    ┌─────────────────────────────────┐
                    │          GBrain 向量数据库         │
                    │  ┌─────────────────────────────┐ │
                    │  │ agents/前端审查              │ │
                    │  │  语义索引 + 知识图谱          │ │
                    │  ├─────────────────────────────┤ │
                    │  │ agents/后端架构              │ │
                    │  │  语义索引 + 知识图谱          │ │
                    │  ├─────────────────────────────┤ │
                    │  │ agents/安全审计              │ │
                    │  │  语义索引 + 知识图谱          │ │
                    │  ├─────────────────────────────┤ │
                    │  │ ... (仅已调度的Agent有页面)   │ │
                    │  └─────────────────────────────┘ │
                    └──────────┬──────────────────────┘
                               │
                    语义检索 ↑↓ 写入维护
                               │
                    ┌──────────┴──────────────────────┐
                    │          主Agent (lee)            │
                    │   - 调度前语义检索提取记忆          │
                    │   - 压缩打包为结构化简报            │
                    │   - 注入子会话context               │
                    │   - 回收子Agent工作结果             │
                    │   - 写入角色Agent记忆页              │
                    │   - 完全的记忆主权管理              │
                    └──┬────────────┬──────────────────┘
                       │            │
              按需注入  │            │  结果回收
                       ↓            ↓
              ┌────────┴──┐   ┌────┴──────────┐
              │ 角色Agent  │   │  子Agent       │
              │ (一级Agent) │   │  (delegate)    │
              │ 独立会话    │   │  无独立记忆页   │
              └────────────┘   └───────────────┘

2.2 三角关系说明

  • 主Agent ↔ GBrain:主Agent是唯一与记忆库直接交互的角色。它负责检索、写入、审核、诊断所有Agent记忆。
  • GBrain ↔ 角色Agent:不直接通信。角色Agent无法自主访问记忆库,所有记忆操作必须经过主Agent。
  • 主Agent ↔ 角色Agent:主Agent在调度角色Agent前,从GBrain检索该角色的相关记忆,压缩为结构化简报后注入到角色Agent的独立会话context中。

2.3 惰性索引的"不调不用"哲学

这是方案B最核心的设计哲学之一:一个角色Agent不被调度,就永远不会创建它的记忆页。305个角色库中,用户实际常用的可能只有10-20个。如果每个都预先创建记忆页,会产生大量空页面和无意义的索引开销。惰性索引确保了零开销默认——只有真正被使用过的Agent才会占用存储和计算资源。


3. 五大核心原则详解

原则一:隔离存储

原理:每种一级Agent拥有独立的、边界清晰的记忆页,路径格式为 agents/<角色名>。不同Agent的记忆在物理和逻辑上完全隔离,一个Agent无法读取另一个Agent的记忆内容。

机制

  • 每个记忆页是GBrain中的一个独立页面(slug: agents/<角色名>
  • 页面包含该Agent专属的frontmatter、工作记忆、项目上下文、子Agent记录
  • 向量嵌入按页索引,检索时限定在目标Agent的页面范围内

示例

agents/前端审查    → 前端审查Agent的独立记忆空间
agents/后端架构    → 后端架构Agent的独立记忆空间
agents/安全审计    → 安全审计Agent的独立记忆空间

为什么需要隔离:不同角色的知识域完全不同。前端审查Agent不需要知道后端架构Agent的数据库选型讨论,安全审计Agent不需要知道UI风格偏好的演变。隔离确保了检索精度和记忆纯度。


原则二:惰性索引

原理:Agent首次被主Agent调度时,才由主Agent为其创建记忆页。创建时机 = "即用即建",不用则不建。

机制

  1. 主Agent决定调度角色Agent X
  2. 检查 agents/X 页面是否存在
  3. 若不存在 → 创建初始记忆页(含frontmatter和基础结构)
  4. 若已存在 → 进行语义检索,提取相关记忆
  5. 将检索结果注入本次会话context

关键意义

  • 零开销默认:305个角色库,实际常驻记忆页可能只有十几个
  • 自动扩展:随着用户使用,记忆页自然增长,无需手动配置
  • 无需维护矩阵:不存在"需要预置哪些Agent记忆"的决策负担

示例场景

用户: "帮我审查这个React组件的性能"
主Agent: 
  1. 决定调度"前端性能审计"角色Agent
  2. 检查 agents/前端性能审计 → 不存在
  3. 创建记忆页 agents/前端性能审计
  4. 注入用户偏好(如React 18、TypeScript严格模式等全局上下文)
  5. 调度执行

原则三:按需注入

原理:主Agent在每次调度前,通过语义检索从目标Agent的记忆页中提取与当前任务最相关的记忆片段,压缩打包为结构化简报,注入到独立会话的上下文中。注入量严格限制在上下文窗口的30%以内

机制

  1. 主Agent解析用户指令,提取任务关键语义
  2. 调用GBrain语义检索(mcp_gbrain_query),以任务语义为查询向量,在 agents/<角色名> 页面范围内检索
  3. 取 top-k 相关记忆片段
  4. 压缩为结构化简报(去除冗余、摘要化长文本)
  5. 注入独立会话context,配合 ≤30%窗口 硬约束

≤30%窗口约束的合理性

  • 为当前任务留出70%以上的空间
  • 防止历史记忆挤压当前推理能力
  • 确保Agent不会"活在过去"

注入简报格式示例

[记忆简报 - 前端审查Agent]
- 用户偏好:React 18 + TypeScript严格模式,函数组件优先
- 上次审查模式:重点关注useMemo/useCallback滥用、Props drilling
- 已知问题类型:大列表无虚拟滚动(3次警告)、useEffect清理函数缺失(2次警告)
- 项目约定:组件文件命名 PascalCase,样式使用CSS Modules

原则四:工作回收

原理:子Agent(通过delegate_task创建的临时Agent)工作完成后,由创建它的主Agent回收其工作结果,将关键产出写入对应角色Agent记忆页的"子Agent记录"段落,然后子Agent被销毁。

机制

子Agent生命周期:
  创建(delegate_task) → 继承记忆(context) → 执行工作 → 
  返回结果 → 主Agent回收结果 → 写入记忆页 → 子Agent销毁

回收记录格式

## 子Agent记录

### 2026-05-08 性能分析任务
- **任务**:分析 Dashboard 组件的渲染性能瓶颈
- **结论**:主要瓶颈在 DataTable 缺少 React.memo 包裹,建议添加虚拟滚动
- **产出**:性能分析报告 + 优化建议清单
- **关键决策**:暂不引入 react-window(依赖体积考虑)

为什么子Agent无独立记忆页:子Agent是临时性的、任务粒度的执行单元。给它独立记忆页会导致页面爆炸(每次delegate都产生新页面),且子Agent的工作结果应该归属到发起它的角色Agent名下,而非独立存在。


原则五:主权管理

原理:主Agent对所有角色Agent的记忆拥有完全的管理权,涵盖查询、审核、诊断三种操作模式。角色Agent不能自主修改自己的记忆页。

三种管理场景

场景 触发条件 主Agent操作
快速问答 用户问"前端审查Agent之前提过什么问题?" 检索目标Agent记忆页,直接回答
任务定位 用户说"检查安全审计Agent上次的遗留问题" 检索 + 提取待办/遗留问题列表
错误诊断 某Agent出现异常行为 审查该Agent记忆页的历史记录,定位根因

主权管理的意义

  • 防止记忆污染:角色Agent不能自行篡改记忆
  • 保证一致性:所有记忆变更经过主Agent统一审核
  • 可追溯性:每次记忆操作都有记录可查

4. 方案A vs 方案B 对比

在方案选型过程中,曾提出两种候选方案:

维度 方案A(项目日志+Git版本管理) 方案B(独立GBrain记忆页+惰性索引)
Agent成长性 ❌ 无个人记忆,Agent无法成长 ✅ 每个Agent有独立记忆,持续积累经验
项目稳定性 ❌ 项目日志过于主观,依赖书写者习惯,不利于中长期项目 ✅ 语义检索 + 结构化记忆页,客观且稳定
运维成本 ⚠️ 低(依赖现有Git),但日志维护靠人工 ⚠️ 需要向量数据库,但自动化程度高
迁移成本 ✅ 极低(纯Git) ⚠️ 需要引入GBrain或替代向量库
检索精度 ❌ 纯关键词/文件名检索,无法语义匹配 ✅ 语义检索 + 重排,精准匹配
记忆膨胀控制 ❌ 无机制,日志无限增长 ✅ 按需注入 + ≤30%窗口硬约束
子Agent结果保留 ❌ 无回收机制,结果可能遗失在commit中 ✅ 结构化回收 + 写入记忆页
跨会话连续性 ❌ 依赖人工翻阅日志 ✅ 自动语义检索注入

方案A被否决的核心原因

方案A的核心问题是忽略了"Agent自身"这个主体。项目日志记录的是"项目发生了什么",而不是"Agent学到了什么"。在一个多Agent体系中,Agent应该像人类专家一样拥有自己的经验和判断力积累,而非每次都从零开始翻阅项目历史。


5. 记忆页结构规范

每个一级Agent的记忆页(agents/<角色名>)遵循统一的四段式结构:

完整模板

---
name: <角色名(中文)>
category: <角色分类,如"前端开发">
first_used: 2026-05-08
projects:
  - <关联项目1>
  - <关联项目2>
tags: [agent-memory]
type: agent-page
---

# <角色名> Agent 记忆

## 项目上下文
<!-- 与该Agent相关的项目背景、技术栈、用户在此项目上的偏好 -->

### <项目名>
- **技术栈**:React 18 + TypeScript + Vite
- **用户偏好**:函数组件优先、CSS Modules、严格类型检查
- **关键约束**:Node 18+、ESM only

## 工作记忆
<!-- Agent在工作过程中积累的经验、教训、模式认知 -->

- 2026-05-08 | 发现Dashboard组件存在useEffect清理函数缺失问题,后续审查需重点关注此模式
- 2026-05-08 | 用户明确偏好使用React.memo而非useMemo进行组件级优化

## 子Agent记录
<!-- 通过delegate_task创建的子Agent的工作回收记录 -->

### 2026-05-08 Dashboard性能分析
- **任务**:分析Dashboard组件的渲染性能
- **结论**:DataTable缺少React.memo,大列表无虚拟滚动
- **产出**:性能报告 + 优化建议
- **关键决策**:暂不引入react-window

各段落用途说明

段落 存放内容 更新频率 更新触发
frontmatter 角色元信息(名称、分类、首次使用时间、关联项目) Agent首次被调度时创建,项目变更时更新
项目上下文 项目级背景信息:技术栈、用户偏好、关键约束 项目配置变更、用户偏好调整
工作记忆 Agent个人经验积累:发现问题、认知模式、经验教训 每次调度结束后,主Agent评估是否需要更新
子Agent记录 delegate_task子Agent的工作回收摘要 每次子Agent完成任务后立即回收写入

6. 子Agent生命周期管理

6.1 完整生命周期

                   主Agent收到任务
                         │
                         ▼
              ┌──────────────────────┐
              │ 判断:是否需要子Agent? │
              └──────┬───────────────┘
                     │ 是
                     ▼
              ┌──────────────────────┐
              │ ① 创建子Agent        │
              │   delegate_task()    │
              └──────┬───────────────┘
                     │
                     ▼
              ┌──────────────────────┐
              │ ② context继承记忆    │
              │   注入角色简报        │
              └──────┬───────────────┘
                     │
                     ▼
              ┌──────────────────────┐
              │ ③ 子Agent执行工作    │
              │   独立会话中完成      │
              └──────┬───────────────┘
                     │
                     ▼
              ┌──────────────────────┐
              │ ④ 子Agent返回结果    │
              │   → 创建者(主Agent)  │
              └──────┬───────────────┘
                     │
                     ▼
              ┌──────────────────────┐
              │ ⑤ 主Agent回收结果    │
              │   - 提取关键结论      │
              │   - 摘要化产出内容    │
              │   - 记录关键决策      │
              └──────┬───────────────┘
                     │
                     ▼
              ┌──────────────────────┐
              │ ⑥ 写入记忆页         │
              │   agents/<角色>      │
              │   "子Agent记录"段落   │
              └──────┬───────────────┘
                     │
                     ▼
              ┌──────────────────────┐
              │ ⑦ 销毁子Agent        │
              │   会话结束,无残留    │
              └──────────────────────┘

6.2 关键规则

  1. 子Agent不创建独立记忆页 — 每个子Agent是临时的,它的记忆归属到创建它的角色Agent名下
  2. context继承是单向的 — 子Agent接收主Agent注入的记忆上下文,但不会反向修改角色Agent的记忆页
  3. 回收是主Agent的职责 — 子Agent不可自己写记忆
  4. 回收记录包含四要素:任务描述、结论、产出、关键决策
  5. 主Agent定期抽查回收完整性 — 确保无遗漏

7. GBrain作为可选后端

7.1 协议不绑定任何向量数据库

本记忆管理方法论定义的是协议层规范(记忆页结构、检索-注入-回收流程、主权管理规则),而非绑定特定技术实现。任何支持以下能力的向量数据库均可作为后端:

  • 语义检索(向量相似度搜索)
  • 分区/命名空间隔离(对应 agents/<角色名> 页面隔离)
  • 结构化元数据存储(对应frontmatter)

7.2 GBrain的优势

GBrain是本体系的推荐后端(也是当前生产环境使用的后端),其优势:

特性 说明
本地化零依赖 PGLite嵌入式Postgres,无需独立数据库服务,一个二进制即可运行
pgvector原生 向量存储和检索内建在数据库层,无需额外中间件
OMLX本地推理 bge-m3 1024-dim 向量 + jina-reranker-v3-mlx 重排,全本地化
MCP协议原生 51个MCP工具,Agent可直接通过函数调用操作记忆
增量同步 git仓库增量索引,Obsidian vault原生支持
知识图谱 页面间链接关系、timeline自动提取

7.3 可替代方案

方案 适用场景 注意点
Milvus 大规模向量检索(百万级+) 需独立部署和维护
Pinecone 全托管,不想维护基础设施 云端服务,数据出境注意合规
Chroma 轻量级嵌入,适合原型开发 生产环境稳定性待验证
LanceDB 本地化列式向量存储 生态较新,工具链不如pgvector成熟

7.4 最小化接入配置

如果使用GBrain,最小化配置如下:

# 1. 安装GBrain
npm install -g @gbrain/cli

# 2. 初始化(关联Obsidian vault作为知识源)
gbrain init --vault /path/to/obsidian/vault

# 3. 安装向量模型
gbrain models install bge-m3
gbrain models install jina-reranker-v3-mlx

# 4. 生成向量嵌入
gbrain embed --all

# 5. 启动MCP服务
gbrain serve --mcp

MCP客户端配置(~/.hermes/mcp.json):

{
  "mcpServers": {
    "gbrain": {
      "command": "gbrain",
      "args": ["serve", "--mcp"]
    }
  }
}

Agent侧调用示例(语义检索Agent记忆):

{
  "tool": "mcp_gbrain_query",
  "parameters": {
    "query": "前端性能审查 React 组件优化 useMemo",
    "path": "agents/前端审查",
    "limit": 5
  }
}

8. 快速开始 / 迁移指南

8.1 如果你已经在使用Hermes + agency-agents-zh

第一步:确认GBrain可用

gbrain --version
# 预期输出: gbrain v0.28.6 或更高

第二步:确认MCP连接

在Hermes Agent会话中测试:

调用 mcp_gbrain_get_stats,确认返回正常的页面数和chunk统计。

第三步:验证惰性索引机制

让主Agent调度一个新角色(之前从未调度过的),观察日志:

主Agent: 检查 agents/<新角色> → 不存在 → 创建记忆页 → 调度执行

第四步:验证记忆持久化

连续两次调度同一个角色Agent,第二次调度前主Agent应该检索到第一次产生的记忆并注入。

8.2 关键文件路径

文件 路径 用途
记忆协议规范 ~/.hermes/skills/AGENT-MEMORY-PROTOCOL.md 全局记忆管理协议
主Agent灵魂规范 ~/.hermes/skills/SOUL.md 主Agent的行为规范(含记忆管理职责)
Agent记忆页 在GBrain中,slug格式为 agents/<角色名> 每个一级Agent的独立记忆空间
角色库 ~/.hermes/skills/agency-agents-zh/ 305个角色定义

8.3 配置检查清单

  • GBrain已安装并运行MCP服务
  • 主Agent拥有 mcp_gbrain_querymcp_gbrain_put_pagemcp_gbrain_get_page 工具权限
  • 主Agent的SOUL.md中已包含记忆管理职责(§八)
  • agency-agents-zh角色库已安装
  • 首次调度任一Agent后,确认 agents/<角色名> 记忆页已自动创建

8.4 常见问题

Q: 需要事先为所有305个角色创建记忆页吗? A: 不需要。惰性索引机制确保只有真正被调度过的Agent才创建记忆页。

Q: 子Agent的结果一定会被回收吗? A: 主Agent在SOUL.md中有明确的回收监督职责。建议主Agent在每次会话结束前主动抽查回收记录的完整性。

Q: 可以用Milvus/Pinecone替代GBrain吗? A: 可以。只要实现相同的检索-注入-回收流程,协议层不绑定具体后端。

Q: 记忆页会无限膨胀吗? A: 不会。按需注入的≤30%窗口约束确保每次只注入最相关的记忆片段,旧记忆自然衰减。同时主Agent可以定期对记忆页进行摘要化压缩。


附录:术语表

术语 定义
一级Agent 角色库中定义的、拥有独立记忆页的Agent(如"前端审查"、"后端架构")
子Agent 通过delegate_task创建的临时Agent,无独立记忆页,任务完成后销毁
GBrain 本地化向量知识库,基于PGLite+pgvector+OMLX
惰性索引 "不调不用"的Agent记忆页创建策略,首次调度时才创建
按需注入 语义检索 → 压缩打包 → 注入context,限制≤30%窗口
工作回收 子Agent完成 → 创建者回收结果 → 写入记忆页 → 子Agent销毁
主权管理 主Agent对所有Agent记忆的完全管理权

文档版本: v1.0 | 最后更新: 2026-05-08

About

多Agent记忆管理方法论 — 解决 Agent 记忆隔离、子 Agent 结果丢失、会话上下文断裂和记忆膨胀

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors