Agent 分层存储架构设计:从记忆方法到中间件选型
1. 为什么 Agent 需要分层存储
一个 Agent 在单轮对话中看起来像是"模型 + Prompt + 工具"。但当它需要跨会话工作、长期学习、恢复任务、审计行为、管理多个用户,问题很快会变成一个存储系统问题:
- 当前任务执行到了哪一步?
- 最近调用了哪些工具?哪些结果必须保留在上下文中?
- 用户偏好、业务事实和历史事件如何跨会话复用?
- 旧事实被新事实推翻时,如何避免检索出过期答案?
- Agent 是否可以从失败中总结经验,并在下一次执行时复用?
- 原始证据如何留存,以便复盘、合规审计和重新构建索引?
- 数据规模增长后,如何控制检索延迟、Token 成本和存储成本?
如果把所有数据都塞进上下文窗口,成本和噪声会持续上升;如果把所有数据都写进向量库,事务状态、时间关系、权限隔离和审计又会变得脆弱。
正确的设计思路是:用分层存储管理 Agent 的上下文、状态、记忆、技能和证据,并让数据在层级之间按策略流动。
2. 主流设计方法全景
业界和研究界已经形成了一组互补的方法。它们不是互斥方案,而是可以组合使用的设计积木。
2.1 上下文窗口:最昂贵但最快的"寄存器"
模型当前可见的 Prompt、最近消息、工具结果和临时草稿,构成 Agent 的即时上下文。它的特点是:
- 延迟最低,因为数据已经在推理输入中。
- 成本最高,因为每次推理都可能重复携带。
- 容量有限,而且信息越多不一定效果越好。
- 适合保存当前任务必须立即使用的数据,不适合保存完整历史。
工程上应把上下文窗口视为一个有严格预算的缓存,而不是数据库。
2.2 MemGPT / Letta:借鉴操作系统的虚拟内存
MemGPT 论文把长对话问题类比为操作系统的虚拟内存管理:有限的上下文窗口类似内存,外部存储类似磁盘,系统需要在快层和慢层之间移动数据。
Letta 文档进一步将其产品化为两大层:
- In-context memory:系统指令、始终可见的 memory blocks、最近消息。
- Out-of-context memory:可搜索的历史消息和长期归档记忆。
其中,memory blocks适合保存用户画像、Agent 身份、当前工作状态和共享规则;archival memory适合保存需要按需搜索的大规模长期信息。
这套方法给出的关键启示是:高价值、低容量信息应固定在上下文中;大容量信息应留在上下文外按需召回。
2.3 Generative Agents:观察、反思、计划
Generative Agents 论文提出了一条影响广泛的记忆链路:
- 保存 Agent 的观察记录。
- 按相关性、时效性和重要性检索记忆。
- 将多条低层观察综合成高层反思。
- 使用记忆和反思支持后续计划。
它解决的不是简单的"聊天历史搜索",而是如何从大量经历中提炼更稳定、更有复用价值的认知。
2.4 Reflexion:把失败复盘写入情景记忆
Reflexion 论文提出:Agent 不一定要通过训练更新模型权重,也可以把任务反馈转化为文字反思,写入 episodic memory(情景记忆),供后续尝试复用。
适合保存的内容包括:
- 哪种执行路径失败了,为什么失败。
- 哪个工具在什么条件下不可靠。
- 哪个验收条件被遗漏。
- 下次遇到类似任务时应先检查什么。
这类记忆应当带上任务类型、失败原因、验证证据和适用范围,而不是简单保存一段自由文本。
2.5 Voyager:把成功经验固化为技能库
Voyager 论文将长期学习实现为可复用的技能库:Agent 从环境反馈和执行错误中改进代码技能,再在后续任务中检索并组合技能。
这给生产系统一个重要启示:成功经验不应只留在对话摘要中,还应升级为程序记忆。
程序记忆可以是:
- 版本化 Prompt。
- 可调用工具定义。
- SOP 和检查清单。
- 经过验证的代码片段或工作流模板。
- 适用条件、输入输出 Schema 和评估结果。
2.6 LangGraph:区分 thread 状态和跨会话记忆
LangGraph 持久化文档通过 checkpointer 保存图执行过程中的状态快照,并按 thread 组织。LangChain 长期记忆文档则把跨会话记忆保存为按 namespace 和 key 组织的 JSON 文档。
LangGraph memory 文档进一步借用了人类记忆分类:
- Semantic memory:事实、概念和偏好。
- Episodic memory:过去发生过的事件和任务经历。
- Procedural memory:完成任务的方法、规则和 Prompt。
这套划分非常适合作为业务数据模型,而不是只把所有记忆统一存成文本块。
2.7 LlamaIndex:FIFO 短期记忆 + 可组合长期记忆块
LlamaIndex Memory 文档提供了一个工程化实现:
- 短期记忆默认是按 Token 限制的 FIFO 消息队列。
- 队列超出阈值后,较旧消息被 flush 到长期 memory blocks。
- 长期块可以保存静态信息、抽取事实,或把消息写入向量库供语义检索。
- 获取记忆时,再将短期和长期内容合并,并确保不超过 Token 限制。
对于已有 LlamaIndex 项目,这种模型很适合作为内存管理入口,但底层数据库仍需要独立设计。
2.8 Mem0:抽取、整合、召回与实体关联
Mem0 论文强调从持续对话中动态抽取、整合和召回关键记忆,以减少全量上下文带来的延迟和 Token 成本。
Mem0 Memory Types 文档按作用域进一步区分:
- Conversation memory:单轮交互中的即时信息。
- Session memory:当前任务或频道中的短期状态。
- User memory:与用户绑定的长期知识。
- Organizational memory:多个 Agent 或团队共享的组织知识。
需要特别注意版本变化:Mem0 OSS 迁移文档显示,开源 SDK 的新算法已从外部图存储转向向量库内的 entity linking 和混合检索。因此,选型时不能只依据旧博客或旧示例。
2.9 时间图谱:处理"谁在什么时候知道什么"
Zep 论文提出用 Graphiti 构建时间感知知识图谱,将非结构化对话和结构化业务数据整合起来,同时保留历史关系。
时间图谱适合处理:
- 用户以前喜欢 A,现在改为喜欢 B。
- 某个项目负责人在不同时间段发生变化。
- 多个实体之间存在多跳关系。
- 需要回答"截至某一天,当时的事实是什么"。
向量检索擅长找"相似内容",图谱更擅长表达"实体关系、有效时间和演化历史"。两者解决的问题不同。
2.10 遗忘、衰减和强化
MemoryBank 论文引入了受遗忘曲线启发的更新机制:记忆可随时间衰减,也可因重要性和重复访问而强化。
生产系统不必机械复制心理学模型,但应实现类似能力:
- TTL:过期即删除。
- Decay:降低召回分数。
- Reinforcement:被频繁命中或被用户确认后提高权重。
- Supersede:新事实替代旧事实,但保留历史。
- Archive:低频原始证据转移到低成本对象存储。
3. 设计原则:不要按数据库分层,要按数据职责分层
常见错误是先列数据库,再想每个数据库存什么。更稳妥的方法是先定义 Agent 数据的职责和访问模式。
| 数据类别 | 典型内容 | 访问特点 | 一致性要求 |
|---|---|---|---|
| 即时上下文 | 当前问题、最近消息、当前工具结果 | 每轮必读,容量小 | 与当前推理严格一致 |
| 工作状态 | 计划、待办、游标、临时变量、锁 | 高频读写,可恢复 | 强一致或可接受的乐观并发 |
| 事件流水 | 消息、工具调用、结果、审批、错误 | 追加写、可回放 | 不可丢失,可审计 |
| 语义事实 | 用户偏好、项目知识、归纳结论 | 跨会话按需召回 | 可更新、可追溯来源 |
| 情景记忆 | 成功任务、失败案例、反思总结 | 相似任务召回 | 保留上下文与结果 |
| 程序记忆 | Prompt、技能、SOP、工具 Schema | 版本化、受控发布 | 强审计,支持回滚 |
| 关系与时间事实 | 实体、关系、有效期、变更历史 | 多跳查询、时间推理 | 保留历史版本 |
| 原始证据 | 完整对话、文件、网页、截图、日志 | 低频读取、容量大 | 不可变、低成本保存 |
4. 推荐的六层存储架构
下面是一套适合从 MVP 演进到生产环境的六层架构。
#mermaid-svg-jj7ioYTrhYh4rZQV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jj7ioYTrhYh4rZQV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jj7ioYTrhYh4rZQV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jj7ioYTrhYh4rZQV .error-icon{fill:#552222;}#mermaid-svg-jj7ioYTrhYh4rZQV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jj7ioYTrhYh4rZQV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jj7ioYTrhYh4rZQV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jj7ioYTrhYh4rZQV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jj7ioYTrhYh4rZQV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jj7ioYTrhYh4rZQV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jj7ioYTrhYh4rZQV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jj7ioYTrhYh4rZQV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jj7ioYTrhYh4rZQV .marker.cross{stroke:#333333;}#mermaid-svg-jj7ioYTrhYh4rZQV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jj7ioYTrhYh4rZQV p{margin:0;}#mermaid-svg-jj7ioYTrhYh4rZQV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jj7ioYTrhYh4rZQV .cluster-label text{fill:#333;}#mermaid-svg-jj7ioYTrhYh4rZQV .cluster-label span{color:#333;}#mermaid-svg-jj7ioYTrhYh4rZQV .cluster-label span p{background-color:transparent;}#mermaid-svg-jj7ioYTrhYh4rZQV .label text,#mermaid-svg-jj7ioYTrhYh4rZQV span{fill:#333;color:#333;}#mermaid-svg-jj7ioYTrhYh4rZQV .node rect,#mermaid-svg-jj7ioYTrhYh4rZQV .node circle,#mermaid-svg-jj7ioYTrhYh4rZQV .node ellipse,#mermaid-svg-jj7ioYTrhYh4rZQV .node polygon,#mermaid-svg-jj7ioYTrhYh4rZQV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jj7ioYTrhYh4rZQV .rough-node .label text,#mermaid-svg-jj7ioYTrhYh4rZQV .node .label text,#mermaid-svg-jj7ioYTrhYh4rZQV .image-shape .label,#mermaid-svg-jj7ioYTrhYh4rZQV .icon-shape .label{text-anchor:middle;}#mermaid-svg-jj7ioYTrhYh4rZQV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jj7ioYTrhYh4rZQV .rough-node .label,#mermaid-svg-jj7ioYTrhYh4rZQV .node .label,#mermaid-svg-jj7ioYTrhYh4rZQV .image-shape .label,#mermaid-svg-jj7ioYTrhYh4rZQV .icon-shape .label{text-align:center;}#mermaid-svg-jj7ioYTrhYh4rZQV .node.clickable{cursor:pointer;}#mermaid-svg-jj7ioYTrhYh4rZQV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jj7ioYTrhYh4rZQV .arrowheadPath{fill:#333333;}#mermaid-svg-jj7ioYTrhYh4rZQV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jj7ioYTrhYh4rZQV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jj7ioYTrhYh4rZQV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jj7ioYTrhYh4rZQV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jj7ioYTrhYh4rZQV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jj7ioYTrhYh4rZQV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jj7ioYTrhYh4rZQV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jj7ioYTrhYh4rZQV .cluster text{fill:#333;}#mermaid-svg-jj7ioYTrhYh4rZQV .cluster span{color:#333;}#mermaid-svg-jj7ioYTrhYh4rZQV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jj7ioYTrhYh4rZQV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jj7ioYTrhYh4rZQV rect.text{fill:none;stroke-width:0;}#mermaid-svg-jj7ioYTrhYh4rZQV .icon-shape,#mermaid-svg-jj7ioYTrhYh4rZQV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jj7ioYTrhYh4rZQV .icon-shape p,#mermaid-svg-jj7ioYTrhYh4rZQV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jj7ioYTrhYh4rZQV .icon-shape .label rect,#mermaid-svg-jj7ioYTrhYh4rZQV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jj7ioYTrhYh4rZQV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jj7ioYTrhYh4rZQV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jj7ioYTrhYh4rZQV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent Runtime
L0 上下文缓存
Prompt / recent messages / tool results
L1 工作状态层
session / checkpoint / locks / TTL
追加写事件流
message / tool / approval / feedback
L2 事实与情景记忆层
canonical records + vector retrieval
L3 时间关系层(按需)
entities / relations / valid time
L4 程序记忆层
skills / prompts / SOP / evaluations
L5 原始证据与冷归档
immutable objects / logs / snapshots
4.1 L0:上下文缓存层
保存内容
- 系统指令。
- 当前任务摘要。
- 最近若干轮消息。
- 当前步骤必须使用的工具结果。
- 少量始终可见的用户偏好和约束。
设计建议
- 明确 Token 预算,不允许无限追加。
- 按优先级装配上下文:系统规则 > 当前任务 > 工作状态 > 召回记忆 > 最近消息 > 可选证据。
- 对超长工具输出做结构化摘要,同时保留原始结果引用。
- 固定块应短小、稳定、可审计,避免频繁变化的大段文本常驻。
存储位置
- 主要由 Agent Runtime 在内存中装配。
- 可从 Redis 或 PostgreSQL 恢复。
4.2 L1:热状态与检查点层
保存内容
session_id、thread_id、task_id。- 当前计划、步骤状态、游标、重试次数。
- 工具调用中的临时结果引用。
- 分布式锁、租约、幂等键。
- 短期对话缓存和 TTL。
推荐中间件
- 默认:Redis。
- 必须可靠恢复的最终状态:同步或异步落入 PostgreSQL。
Redis 适合承载 TTL、缓存、锁和短期会话。Redis 官方的 Agent Memory 文档也采用了工作记忆和长期记忆两层模型,并支持在上下文变长时自动摘要旧消息。Redis Cloud Agent Memory 文档进一步支持 TTL 生命周期和异步抽取长期记忆。
边界
- Redis 不是所有业务事实的唯一真相源。
- Agent 任务完成后,关键状态必须有持久记录。
- 锁必须有过期时间,任务必须有租约和心跳。
4.3 L2:事实、事件和情景记忆层
这是系统的核心长期记忆层,建议拆成两个物理职责:
- Canonical Store:保存权威事实、事件、作用域、时间、来源和版本。
- Retrieval Index:保存 embedding、关键词索引和可过滤 metadata,用于快速召回。
推荐中间件
- Canonical Store:PostgreSQL。
- Retrieval Index:中小规模可用 PostgreSQL + pgvector ;更高检索吞吐或更复杂混合检索可使用 Qdrant。
pgvector 官方仓库支持精确与近似最近邻检索、HNSW、IVFFlat、过滤条件,以及 PostgreSQL 原有的 ACID、JOIN 和时间点恢复能力。对于 MVP 和中等规模系统,它能显著减少中间件数量。
Qdrant 官方文档提供向量检索、过滤、量化、多租户和高级搜索能力。Hybrid Queries 文档支持多阶段和混合查询,Payload 文档允许保存 JSON metadata 并在搜索时过滤。对于 LlamaIndex 项目,QdrantVectorStore 文档提供了直接集成入口。
推荐 metadata
text
memory_id
tenant_id
user_id
agent_id
session_id
task_id
memory_type # semantic / episodic / reflection / document
scope # user / agent / project / organization
content
summary
source_event_ids
source_object_uri
valid_from
valid_to
created_at
updated_at
importance
confidence
reinforcement_count
last_accessed_at
decay_policy
superseded_by
embedding_model
embedding_version
prompt_version
4.4 L3:时间关系与知识图谱层
保存内容
- 实体:用户、组织、项目、系统、文档、任务。
- 关系:负责、依赖、偏好、批准、属于、替代。
- 时间:
valid_from、valid_to、observed_at。 - 来源:由哪些事件和证据推导而来。
推荐中间件
- 默认不引入图数据库,先用 PostgreSQL 关系表建模。
- 当多跳关系和时间推理成为核心需求时,引入 Neo4j。
Neo4j Semantic Indexes 文档说明 Neo4j 同时支持全文索引和向量索引,可用于混合检索。Neo4j Vector Search 文档指出,向量搜索适合语义相似性,而精确术语、标识符和图结构需要结合其他检索信号。
什么时候值得引入图数据库
- 经常出现"谁与谁在何时有什么关系"的查询。
- 需要多跳路径推理。
- 同一事实频繁变化,必须回答历史时点问题。
- 向量召回能找到文本,但无法稳定回答关系问题。
什么时候不值得
- 主要需求只是文档问答或用户偏好召回。
- 数据量小,关系查询可以用 PostgreSQL JOIN 解决。
- 团队没有图模型治理能力。
4.5 L4:程序记忆与自我进化层
保存内容
- Prompt 模板和版本。
- Agent policy。
- 工具定义、输入输出 Schema。
- 成功技能、失败反思、SOP。
- 技能适用条件、依赖、风险等级。
- 评估集、评估结果和发布记录。
推荐中间件
- Git 仓库:适合 Markdown 技能、Prompt、SOP 和配置。
- PostgreSQL:适合保存技能索引、版本元数据、评估记录和发布状态。
- 对象存储:适合保存大体积产物和评估附件。
- 向量索引:适合按任务相似度召回技能,但不能取代版本管理。
这里必须避免一个危险误区:所谓"自我进化"不应等于 Agent 可以绕过审核直接修改生产 Prompt 或代码。更合理的闭环是:
#mermaid-svg-UnpvbU8Lpmt4wAJb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UnpvbU8Lpmt4wAJb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UnpvbU8Lpmt4wAJb .error-icon{fill:#552222;}#mermaid-svg-UnpvbU8Lpmt4wAJb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UnpvbU8Lpmt4wAJb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UnpvbU8Lpmt4wAJb .marker.cross{stroke:#333333;}#mermaid-svg-UnpvbU8Lpmt4wAJb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UnpvbU8Lpmt4wAJb p{margin:0;}#mermaid-svg-UnpvbU8Lpmt4wAJb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UnpvbU8Lpmt4wAJb .cluster-label text{fill:#333;}#mermaid-svg-UnpvbU8Lpmt4wAJb .cluster-label span{color:#333;}#mermaid-svg-UnpvbU8Lpmt4wAJb .cluster-label span p{background-color:transparent;}#mermaid-svg-UnpvbU8Lpmt4wAJb .label text,#mermaid-svg-UnpvbU8Lpmt4wAJb span{fill:#333;color:#333;}#mermaid-svg-UnpvbU8Lpmt4wAJb .node rect,#mermaid-svg-UnpvbU8Lpmt4wAJb .node circle,#mermaid-svg-UnpvbU8Lpmt4wAJb .node ellipse,#mermaid-svg-UnpvbU8Lpmt4wAJb .node polygon,#mermaid-svg-UnpvbU8Lpmt4wAJb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UnpvbU8Lpmt4wAJb .rough-node .label text,#mermaid-svg-UnpvbU8Lpmt4wAJb .node .label text,#mermaid-svg-UnpvbU8Lpmt4wAJb .image-shape .label,#mermaid-svg-UnpvbU8Lpmt4wAJb .icon-shape .label{text-anchor:middle;}#mermaid-svg-UnpvbU8Lpmt4wAJb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UnpvbU8Lpmt4wAJb .rough-node .label,#mermaid-svg-UnpvbU8Lpmt4wAJb .node .label,#mermaid-svg-UnpvbU8Lpmt4wAJb .image-shape .label,#mermaid-svg-UnpvbU8Lpmt4wAJb .icon-shape .label{text-align:center;}#mermaid-svg-UnpvbU8Lpmt4wAJb .node.clickable{cursor:pointer;}#mermaid-svg-UnpvbU8Lpmt4wAJb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UnpvbU8Lpmt4wAJb .arrowheadPath{fill:#333333;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UnpvbU8Lpmt4wAJb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UnpvbU8Lpmt4wAJb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UnpvbU8Lpmt4wAJb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UnpvbU8Lpmt4wAJb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UnpvbU8Lpmt4wAJb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UnpvbU8Lpmt4wAJb .cluster text{fill:#333;}#mermaid-svg-UnpvbU8Lpmt4wAJb .cluster span{color:#333;}#mermaid-svg-UnpvbU8Lpmt4wAJb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UnpvbU8Lpmt4wAJb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UnpvbU8Lpmt4wAJb rect.text{fill:none;stroke-width:0;}#mermaid-svg-UnpvbU8Lpmt4wAJb .icon-shape,#mermaid-svg-UnpvbU8Lpmt4wAJb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UnpvbU8Lpmt4wAJb .icon-shape p,#mermaid-svg-UnpvbU8Lpmt4wAJb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UnpvbU8Lpmt4wAJb .icon-shape .label rect,#mermaid-svg-UnpvbU8Lpmt4wAJb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UnpvbU8Lpmt4wAJb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UnpvbU8Lpmt4wAJb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UnpvbU8Lpmt4wAJb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
任务执行
收集反馈与证据
生成反思候选
抽取技能或 Prompt 修改候选
离线评估
通过阈值与审核?
保留为实验候选
版本化发布
灰度验证与回滚监控
4.6 L5:原始证据与冷归档层
保存内容
- 完整对话。
- 工具原始输出。
- 上传文件、网页快照、截图。
- Agent 生成产物。
- 事件日志快照。
- 数据导出和审计证据。
推荐中间件
- 云环境:Amazon S3。
- 自建环境:MinIO 或兼容 S3 API 的对象存储。
对象存储适合不可变大对象和低成本长期保存。AWS 官方 S3 Lifecycle 文档支持按生命周期将对象转移到 Standard-IA、Intelligent-Tiering 和 Glacier 等存储类别,以平衡访问延迟和成本。
设计建议
- 原始证据尽量追加写,不覆盖。
- 数据库中保存 URI、哈希、媒体类型、大小、权限和保留期。
- 摘要、embedding 和图谱都应能追溯到原始证据。
- 冷归档删除必须遵循租户、合规和用户撤回规则。
5. 写入链路:先保留事实,再异步提炼记忆
推荐采用"在线轻写入,异步重加工"的方式。
Memory Worker Object Storage Graph Store Qdrant PostgreSQL Redis Agent Runtime User Memory Worker Object Storage Graph Store Qdrant PostgreSQL Redis Agent Runtime User #mermaid-svg-FyDIutViu1pT7gV3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FyDIutViu1pT7gV3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FyDIutViu1pT7gV3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FyDIutViu1pT7gV3 .error-icon{fill:#552222;}#mermaid-svg-FyDIutViu1pT7gV3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FyDIutViu1pT7gV3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FyDIutViu1pT7gV3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FyDIutViu1pT7gV3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FyDIutViu1pT7gV3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FyDIutViu1pT7gV3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FyDIutViu1pT7gV3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FyDIutViu1pT7gV3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FyDIutViu1pT7gV3 .marker.cross{stroke:#333333;}#mermaid-svg-FyDIutViu1pT7gV3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FyDIutViu1pT7gV3 p{margin:0;}#mermaid-svg-FyDIutViu1pT7gV3 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-FyDIutViu1pT7gV3 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-FyDIutViu1pT7gV3 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-FyDIutViu1pT7gV3 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-FyDIutViu1pT7gV3 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-FyDIutViu1pT7gV3 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-FyDIutViu1pT7gV3 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-FyDIutViu1pT7gV3 .sequenceNumber{fill:white;}#mermaid-svg-FyDIutViu1pT7gV3 #sequencenumber{fill:#333;}#mermaid-svg-FyDIutViu1pT7gV3 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-FyDIutViu1pT7gV3 .messageText{fill:#333;stroke:none;}#mermaid-svg-FyDIutViu1pT7gV3 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-FyDIutViu1pT7gV3 .labelText,#mermaid-svg-FyDIutViu1pT7gV3 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-FyDIutViu1pT7gV3 .loopText,#mermaid-svg-FyDIutViu1pT7gV3 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-FyDIutViu1pT7gV3 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-FyDIutViu1pT7gV3 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-FyDIutViu1pT7gV3 .noteText,#mermaid-svg-FyDIutViu1pT7gV3 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-FyDIutViu1pT7gV3 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-FyDIutViu1pT7gV3 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-FyDIutViu1pT7gV3 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-FyDIutViu1pT7gV3 .actorPopupMenu{position:absolute;}#mermaid-svg-FyDIutViu1pT7gV3 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-FyDIutViu1pT7gV3 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-FyDIutViu1pT7gV3 .actor-man circle,#mermaid-svg-FyDIutViu1pT7gV3 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-FyDIutViu1pT7gV3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} opt 需要时间关系 新消息或任务 更新 session / checkpoint / TTL 追加 message_event 保存超长原始内容或附件 在线响应 触发异步记忆加工 抽取事实、情景、反思与来源 写入 embedding 与 metadata 更新实体、关系和有效时间
在线链路只做必要工作:
- 保留原始事件。
- 更新热状态。
- 保存大对象引用。
- 在预算内召回少量相关记忆。
异步 Worker 再完成:
- 事实抽取。
- 去重和合并。
- 冲突检测。
- embedding。
- 关键词索引。
- 重要度计算。
- 关系抽取。
- 旧记忆降权或归档。
这样可以避免把 LLM 抽取和复杂索引更新放进用户请求的关键路径。
6. 读取链路:混合检索比单一向量搜索更可靠
只做向量相似度搜索通常不够。生产环境建议至少组合五类信号:
- Scope filter:租户、用户、Agent、项目、会话权限。
- Semantic similarity:向量相似度。
- Lexical match:关键词、标识符、错误码、文件名。
- Recency / temporal validity:时间衰减和事实有效期。
- Importance / confidence:重要度、置信度和强化次数。
可使用如下概念评分:
text
score =
semantic_similarity * 0.40 +
lexical_relevance * 0.20 +
recency * 0.15 +
importance * 0.15 +
confidence * 0.10
实际权重应通过评估集调优。对于关系型问题,再增加图查询结果,并通过 Reciprocal Rank Fusion 或 reranker 合并结果,而不是直接比较不同检索器的原始分数。
检索结果进入上下文前还要做三件事:
- 去重:避免多个摘要重复表达同一事实。
- 冲突裁决:优先使用当前仍有效、来源可信的新事实。
- Token 压缩:只注入回答当前问题必要的内容。
7. 推荐的中间件组合
7.1 默认推荐:适合大多数团队
| 职责 | 推荐中间件 | 原因 |
|---|---|---|
| 热状态、TTL、锁、短期缓存 | Redis | 低延迟,适合短生命周期状态 |
| 权威事实、事件、版本、权限、任务状态 | PostgreSQL | ACID、JOIN、JSON、事务、成熟治理 |
| 语义检索与 metadata 过滤 | Qdrant | 专门的向量检索能力,适合 LlamaIndex 集成 |
| 原始证据和冷归档 | MinIO 或 S3 | 低成本保存大对象,支持生命周期 |
| Prompt、技能、SOP | Git + PostgreSQL 元数据 | 版本审计、评估和可回滚发布 |
| 关系与时间推理 | 初期 PostgreSQL,必要时 Neo4j | 延迟引入复杂度,按需求升级 |
| 事件总线 | 初期 PostgreSQL Outbox,必要时 Kafka | 先保证简单可靠,再扩展吞吐 |
这套组合适合已经使用 LlamaIndex 和 Qdrant 的项目:它保留现有技术栈,同时补齐热状态、权威存储和冷归档。
7.2 极简 MVP:减少运维组件
| 职责 | 推荐中间件 |
|---|---|
| 任务状态、事实、事件、权限 | PostgreSQL |
| 向量检索 | PostgreSQL + pgvector |
| 短期缓存 | 进程内缓存,必要时再加 Redis |
| 文件与原始证据 | 本地对象目录或 MinIO |
| 程序记忆 | Git |
适用于:
- 单机或小团队。
- 向量规模尚小。
- 吞吐量不高。
- 当前目标是先验证数据模型和记忆策略。
7.3 规模化版本:增加事件驱动和专用组件
| 职责 | 推荐中间件 |
|---|---|
| 热状态 | Redis Cluster |
| 权威业务数据 | PostgreSQL 高可用集群 |
| 事件总线 | Kafka |
| 向量检索 | Qdrant 集群或同级专用向量数据库 |
| 图谱 | Neo4j 或企业现有图数据库 |
| 冷归档 | S3 + Lifecycle |
| 可观测性 | OpenTelemetry + 指标、日志和 Trace 平台 |
Apache Kafka 文档将 Kafka 定位为可持久、可靠保存事件流,并支持实时和回溯处理的平台。Kafka Log Compaction 文档说明压缩日志能够为每个 key 至少保留最新状态。因此 Kafka 很适合在多 Worker、异步加工、可回放重建和跨系统同步成为核心需求时引入。
但 Kafka 不应成为早期 MVP 的默认依赖。只要 PostgreSQL Outbox + Worker 足够满足吞吐和恢复需求,先保持简单。
8. 中间件选型矩阵
8.1 向量检索层
| 方案 | 适用场景 | 优点 | 局限 |
|---|---|---|---|
| PostgreSQL + pgvector | MVP、中小规模、强事务需求 | 组件少,事实与向量可放在同一数据库,易于 JOIN 和备份 | 大规模专用检索能力和独立扩展能力较弱 |
| Qdrant | 通用生产 Agent、LlamaIndex 项目 | Payload 过滤、混合查询、多租户、专用检索能力 | 多一个需要运维的组件 |
| Redis Vector Search | 已深度使用 Redis、希望热数据和检索靠近 | 低延迟,Redis 官方已有 Agent Memory 能力 | 需要谨慎控制内存成本和持久化策略 |
| Neo4j Vector Index | 已经以图谱为中心 | 图、全文和向量检索可组合 | 不应只为了普通向量检索引入图数据库 |
8.2 图谱层
| 方案 | 适用场景 | 建议 |
|---|---|---|
| PostgreSQL 关系表 | 关系较简单、团队熟悉 SQL | 默认从这里开始 |
| Neo4j | 多跳关系、时间图谱、图可视化和图查询成为核心 | 需求明确后引入 |
| 不建图,仅 entity linking | 主要目的是增强实体命中,不需要复杂路径推理 | 可参考 Mem0 OSS 新算法思路 |
8.3 托管记忆服务
如果团队希望快速验证,也可以使用托管记忆层,例如 Mem0 Platform、Redis Agent Memory 或 Zep。它们能减少自建抽取、召回和生命周期管理的工作量。
但要先确认:
- 数据是否允许交给外部服务。
- 是否支持租户隔离、删除、导出和审计。
- 是否可以追溯到原始证据。
- 是否允许替换底层存储。
- SDK 和开源版本是否存在能力差异。
- 成本是否会随 Token、记忆数量和检索次数快速增长。
9. 建议的数据表
9.1 事件表:不可变追加写
sql
create table agent_events (
event_id uuid primary key,
tenant_id text not null,
agent_id text not null,
user_id text,
session_id text,
task_id text,
event_type text not null,
payload jsonb not null,
object_uri text,
created_at timestamptz not null default now()
);
事件类型可以包括:
text
message_received
message_sent
tool_requested
tool_completed
tool_failed
checkpoint_saved
approval_requested
approval_granted
feedback_received
memory_promoted
memory_superseded
skill_candidate_created
skill_published
9.2 长期记忆表:可演化但可追溯
sql
create table agent_memories (
memory_id uuid primary key,
tenant_id text not null,
scope_type text not null,
scope_id text not null,
memory_type text not null,
content text not null,
summary text,
importance numeric not null default 0.5,
confidence numeric not null default 0.5,
valid_from timestamptz,
valid_to timestamptz,
superseded_by uuid references agent_memories(memory_id),
source_event_ids uuid[] not null default '{}',
source_object_uri text,
metadata jsonb not null default '{}',
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
9.3 技能表:把"学到的经验"纳入发布流程
sql
create table agent_skills (
skill_id uuid primary key,
name text not null,
version text not null,
status text not null, -- candidate / evaluated / approved / published / retired
repository_path text not null,
applicability jsonb not null,
risk_level text not null,
evaluation_report_uri text,
created_from_event_ids uuid[] not null default '{}',
created_at timestamptz not null default now(),
published_at timestamptz
);
10. 多租户、安全与治理
Agent 的长期记忆天然带有隐私和越权风险。必须把治理放在数据模型中,而不是只依赖 Prompt。
10.1 作用域隔离
每次写入和检索都必须显式携带:
text
tenant_id
user_id
agent_id
project_id
session_id
检索时先做权限过滤,再做相似度召回。不能先召回再在应用层"尽量过滤"。
PostgreSQL 可用 Row-Level Security实施行级访问控制;Qdrant 可用 payload 过滤实现租户和作用域限制。Qdrant 的 LlamaIndex 多租户示例建议对大量独立用户使用单 collection,并通过 payload 分区隔离。
10.2 敏感数据
- Secret 不写入长期记忆。
- PII 在写入前做识别、脱敏和最小化。
- 用户长期偏好需要明确保留期和删除能力。
- embedding 也属于敏感派生数据,删除原文时要同步删除索引。
- 原始证据、摘要、向量、图谱和缓存需要统一执行删除流程。
10.3 可解释性
每条记忆至少应回答:
- 从哪些事件或证据提取而来?
- 由哪个 Prompt 和模型版本生成?
- 当前是否仍然有效?
- 为什么这次被召回?
- 是否被用户确认或推翻过?
11. 自我总结与进化:受控闭环
设计"会进化的 Agent"时,可以将经验升级分为四级:
| 等级 | 产物 | 是否自动生效 |
|---|---|---|
| L1 | 本次任务摘要 | 可以,用于恢复当前任务 |
| L2 | 情景记忆和失败反思 | 可以,但只作为检索上下文 |
| L3 | 技能候选和 Prompt 修改候选 | 不应直接生效,必须评估 |
| L4 | 发布后的技能、SOP、Prompt | 经过评估、审核和版本化后生效 |
11.1 推荐的总结触发器
- 上下文即将压缩。
- 任务完成。
- 工具连续失败。
- 用户明确纠正 Agent。
- 相似任务累计达到阈值。
- 定时批处理。
11.2 推荐的总结模板
text
任务类型:
目标:
关键约束:
采取的步骤:
成功证据:
失败步骤:
根因:
可复用经验:
不适用条件:
建议升级为技能:
来源事件:
11.3 发布前评估
技能或 Prompt 候选发布前至少检查:
- 在历史任务集上的成功率。
- 成本和延迟变化。
- 是否导致越权工具调用。
- 是否引入数据泄露。
- 是否能回滚。
- 是否只在明确适用范围内启用。
真正可靠的"进化"不是让 Agent 无限制修改自己,而是建立一个可追溯、可评估、可审核、可灰度、可回滚的知识发布流程。
12. 分阶段实施路线
阶段一:单机可用
目标:先跑通记忆闭环,不追求复杂组件。
- PostgreSQL 保存任务、事件和长期记忆。
- pgvector 保存 embedding。
- Git 保存 Prompt、技能和 SOP。
- 本地目录或 MinIO 保存原始证据。
- Agent Runtime 严格限制上下文 Token。
- 使用后台 Worker 做摘要、事实抽取和 embedding。
阶段二:团队生产
目标:提升在线性能、隔离和可观测性。
- 增加 Redis 保存 session、TTL、锁和热状态。
- 向量检索迁移到 Qdrant,保留 PostgreSQL 作为权威来源。
- 使用 PostgreSQL Outbox 驱动异步 Worker。
- 增加租户隔离、删除流程、审计事件和检索 Trace。
- 建立离线评估集,调优召回和上下文装配。
阶段三:规模化平台
目标:支持多 Worker、大量事件和复杂关系。
- 当 Outbox 消费成为瓶颈时,引入 Kafka。
- 当多跳关系和时间问题成为核心时,引入 Neo4j。
- S3 配置生命周期和冷归档。
- 技能候选进入自动评估、人工审核、灰度和回滚流程。
- 对每类记忆设置 TTL、衰减、强化和删除策略。
13. 常见反模式
13.1 把向量库当成唯一数据库
向量库适合召回,不适合独自承担事务状态、版本控制、审计和复杂权限。
13.2 保存所有对话,却不抽取事实
完整历史是证据,不是高质量记忆。需要异步提炼、去重、冲突检测和有效期管理。
13.3 每轮都把全部记忆塞入 Prompt
上下文越大,成本越高,噪声也越多。应先过滤、召回、重排和压缩。
13.4 一开始就引入 Kafka、图数据库和多套向量库
复杂度本身会吞噬团队精力。中间件必须由明确瓶颈驱动。
13.5 让 Agent 自动修改生产 Prompt 和代码
反思可以自动生成,生产发布必须经过评估、审核和版本控制。
13.6 忽略删除和撤回
长期记忆、embedding、缓存、图谱和对象存储中的派生数据都必须支持统一删除。
14. 最终建议
如果现在开始搭建一个通用 Agent 的分层存储,我会采用以下默认方案:
text
L0 上下文缓存:
Agent Runtime 内存装配,严格 Token 预算
L1 热状态:
Redis
L2 权威事实、任务状态、事件流水:
PostgreSQL
L2 语义检索:
Qdrant
如果仍处于 MVP,则先用 PostgreSQL + pgvector
L3 时间关系:
初期 PostgreSQL
多跳与时间推理成为核心需求后再引入 Neo4j
L4 程序记忆:
Git + PostgreSQL 元数据 + 离线评估
L5 原始证据和冷归档:
MinIO 或 S3
异步加工:
初期 PostgreSQL Outbox + Worker
吞吐量和回放需求增长后再引入 Kafka
这套架构的核心不是组件数量,而是边界清晰:
- Redis 管快而短的数据。
- PostgreSQL 管权威状态和可审计事实。
- Qdrant 管高效召回。
- Neo4j 只在复杂关系值得付出成本时加入。
- Git 管可审查、可回滚的程序记忆。
- S3 / MinIO 管大而冷的原始证据。
- Kafka 只在事件规模和异步解耦需求明确后加入。
Agent 的能力会持续演进,但存储架构必须保持一个不变原则:每一条被 Agent 使用的记忆,都应该有明确作用域、来源、生命周期、版本和删除路径。
15. 参考资料
研究论文
- MemGPT: Towards LLMs as Operating Systems
- Generative Agents: Interactive Simulacra of Human Behavior
- Reflexion: Language Agents with Verbal Reinforcement Learning
- Voyager: An Open-Ended Embodied Agent with Large Language Models
- MemoryBank: Enhancing Large Language Models with Long-Term Memory
- Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory
- Zep: A Temporal Knowledge Graph Architecture for Agent Memory
官方文档
- Letta Agent memory & architecture
- Letta Memory blocks
- Letta Archival memory
- LangGraph Persistence
- LangChain Long-term memory
- LangGraph Memory overview
- LlamaIndex Memory
- LlamaIndex QdrantVectorStore
- Mem0 Memory Types
- Mem0 OSS migration guide
- Redis Agent Memory
- pgvector
- Qdrant Documentation
- Qdrant Hybrid Queries
- Qdrant Payload
- Neo4j Semantic Indexes
- Neo4j Vector Search
- PostgreSQL Row Security Policies
- Apache Kafka Introduction
- Apache Kafka Log Compaction
- Amazon S3 Lifecycle transitions