# Infinity 低内存架构深度调研与本地化方案

**研究日期：** 2026-10-30

**Infinity 仓库版本：** `1abc6fcff1f186124f924b56aa92c3a3684c90c5`

**Hermes Agent 上游核对版本：** `d4865574e47497e9a9cd1d21333b8c008a9e8a34`（2026-10-30 查询到的官方 `main`）

**研究范围：** 长期会话的驻留内存、执行器生命周期、队列和持久化边界；不评估 Agent 能力清单，也不把本地模型权重计入 runtime 内存。

## 1. 执行摘要

### 直接结论

1. **Infinity 的低内存优势是真实的，但它不是“全部会话历史不占内存”。** 关键是空闲线程的 driver future、局部执行状态及关联 worker 入口会在空闲时销毁；对话历史是否留在 RAM，则取决于 `ConversationStore`。仓库的低内存基准使用 `InMemoryConversationStore`，所以 80,000 个空闲 Agent 的完整合成历史仍留在进程内存里。
2. **Infinity 并不要求全部云化。** 它把执行逻辑、存储和输入投递抽象为接口；AWS Lambda/SQS/DSQL 是一种 embedding。相同的 step 模型可以运行在单机进程中，把 SQLite/本地队列放在本机磁盘上。需要“离开执行器 RAM”的是权威状态，不是必须离开用户的机器。
3. **当前仓库的本地 daemon 持久化包装还不等于有界内存存储。** JSON 文件按需加载进核心内存 store，且加载后没有找到卸载/淘汰路径。持久化解决重启恢复，不自动解决长期进程的 RAM 上界。
4. **要托管海量会话，设计目标应是“总会话数与进程 RSS 解耦”。** 持久化消息和状态放在本地/远端数据库，等待中的工具调用变为持久化事件，空闲 Agent 不保留 driver；运行时只保留受并发数约束的活跃切片和受字节预算约束的热缓存。若仍把全历史装入无界 map、无界队列或每个 session 常驻对象，换成云数据库也不能保证应用进程低内存。

### 一句话回答“是否必须云化”

**不必须。** “执行时重建、执行完释放”是生命周期架构；“状态放在哪里”是部署选择。一个单机版完全可以由本地持久化数据库、磁盘 inbox/outbox 和有限 worker 构成。云化只是在多机、高可用、托管运维或弹性扩缩容方面的选项，不是 Infinity 低内存机制的必要条件。

### 需要先划清的三个边界

| 边界 | 含义 | RAM 是否随所有历史会话数增长 |
|---|---|---|
| 权威状态 | 原始消息、线程关系、去重 ID、工具调用状态、压缩摘要 | 应存于持久化层；如果持久化层又全量镜像进进程内存，仍会增长 |
| 执行态 | 当前切片的 prompt、模型请求/响应缓冲、活跃工具派发及局部状态 | 应只随同时执行数增长，并受 worker 上限约束 |
| 热缓存与队列 | 最近会话、重建后的上下文、待处理消息 | 必须有显式条目上限、字节上限和背压；仅设 TTL 不等于字节有界 |

这里的“极低内存”指 **Agent runtime 的控制面与会话状态**。如果模型在本机运行，模型权重、KV cache、推理批次缓冲通常另有显著资源成本；Infinity 的脚本基准没有测这些资源。

## 2. Infinity 的架构到底节省了什么

### 2.1 Step：把等待变成消息边界

Infinity 将用户输入、工具结果、订阅事件、子线程报告和定时唤醒统一成 `InputMessage`。一个执行切片加载会话和去重状态，处理输入并调用模型；遇到异步工具时派发调用并结束切片，工具完成后把结果作为新输入重新入队。下一片执行再从 store 恢复上下文。执行器不必在“等待工具几分钟/几小时”期间一直持有一个运行中的 Agent 对象。

这套语义有两个关键收益：

- **空闲时间不占一个线程级执行器。** 只要 Agent 没有正在运行的切片，就无需保留它的 future、栈/局部变量和活动连接。
- **故障恢复基于持久化输入和状态。** 至少一次投递可以通过稳定 dedup ID 吸收重放；同一 thread 的顺序由输入传输层保证。

这不是“每个会话的历史消失”。如果消息 store 本身是内存实现，历史依然由 store 长期持有。

### 2.2 Local router：空闲 driver 释放，不是所有 session 状态释放

`crates/infinity-agent-core/src/system/local/router.rs` 的注释说明：router 自己拥有 `FuturesUnordered` 中的 driver futures，而不是为每条 thread 永久 `spawn` 一个 task；driver 结束后，其 future 和 worker entry 可以被释放。路由器收到下一条该 thread 的消息时再生成 driver。消息按 thread ID 路由，活着的同一 thread driver 被复用；不同 thread 的 driver 可以并行。

因此，Infinity 有两层不同的“常驻”概念：

- **执行器驻留：** 空闲时可为零；这是 local router 明确优化的对象。
- **会话数据驻留：** 由 store 决定。空闲 driver 消失后，历史、线程元数据、压缩摘要和去重 ID 仍可留在 HashMap 中。

### 2.3 存储抽象让本地方案成为可能

核心接口 `ConversationStore`、`StateStore` 和 `InputSender` 将历史/状态读取、写入和消息投递从执行引擎中分离。Lambda 实现将它们绑定到 DSQL、DynamoDB 和 SQS；这只是一个部署适配器。单机服务可实现相同契约，将这些接口绑定到本地 SQL 数据库和磁盘队列。

但要注意：接口可替换不代表当前已经附带了所需的本地 SQL 实现。具体的有界读取、事务、持久化 inbox/outbox、worker 配额和内存回收仍需实现。

## 3. 仓库实证：目前哪些东西仍在 RAM

### 3.1 In-memory store 会保留全部对话

`crates/infinity-agent-core/src/stores.rs` 的 `InMemoryConversationStore` 使用：

- `HashMap<ThreadId, Vec<(InfinityMessage, String)>>` 存消息；
- `HashMap<ThreadId, ThreadInfo>` 存线程树元数据；
- `HashMap<ThreadId, Vec<CompactionSummary>>` 存摘要。

`load_history_up_to(..., None)` 会克隆所请求范围的全部消息到 `Vec`；`append_messages` 会把消息追加到 map 内的向量。`InMemoryStateStore` 另以 HashMap/HashSet 保存已处理消息 ID、metadata、订阅和待选项。它很适合示例、测试和短生命周期进程，但不构成按 session 数量有界的存储。

需要特别注意：历史摘要/compaction 能减少后续 prompt 看到的消息范围，但并不自动代表 backing store 已删除原始历史。若底层仍是该内存 map，原消息仍可能留在向量中。

### 3.2 daemon 的 JSON 持久化仍是“内存 store + 文件镜像”

`crates/infinity-daemon/src/memory_store.rs` 的 `PersistentConversationStore` 将 JSON 文件作为恢复来源，但核心语义委托给 `InMemoryConversationStore`：

1. 首次触达某个线程时，`ensure_thread_loaded` 从 `{thread_id}.json` 反序列化整份 `ThreadSnapshot`，导入内存 store。
2. `loaded` / `metadata_loaded` 集合记录已加载线程；代码中没有看到相应的 unload、LRU 或按字节淘汰流程。
3. `append_messages` 先更新内存 store，再调用 `save_thread`。后者从核心 store 拿整份线程快照、序列化完整 JSON 并写回文件。小批量反复追加时会重复处理整个会话快照，写放大随历史长度上升。
4. JSON 写入调用将错误转为 `.ok()`，即持久化写失败不会通过 `ConversationStore` 的 `Result` 反馈给上层。这意味着这段 wrapper 不能仅凭“落盘了”就视为满足可靠队列/数据库的耐久性契约。

`PersistentStateStore` 同样把每个 thread 的 JSON state 导入 `InMemoryStateStore`，并维护 loaded 集合；其 state 写入也存在忽略 `std::fs::write` 错误的代码路径。因此它是当前 daemon 的轻量恢复机制，不是面向无限 session 的 RAM 有界 SQL backend。

### 3.3 Local 队列和活跃 driver 也未设服务级上限

`crates/infinity-agent-core/src/system/local/sender.rs` 的主输入 sender 是 Tokio `UnboundedSender`。router 创建 per-thread worker 输入/订阅 channel 时也使用 unbounded channel；driver 数放入 `FuturesUnordered`，未发现全局并发 semaphore/最大活跃 thread 配置。

空闲线程可回收并不意味着爆发流量时有硬上界。若生产者持续快于消费者，无界输入队列会把等待工作转成 RAM；若大量不同 thread 同时到达，活跃 driver 也可随输入规模增大。生产环境需要持久化待处理消息、worker 配额及入口背压。

### 3.4 上下文 API 仍允许全量读取

`ConversationStore::load_history_up_to` 的 `start_from` / `up_to` 按消息数量截断，但 `None` 表示无界；`load_history_with_ancestors` 会拼接 thread 与祖先历史并返回完整 `Vec<InfinityMessage>`。要把会话归档放在磁盘而又不把长历史整体装回内存，需要新增按页/字节/Token 限制的 prompt-context 接口，或在 SQL 查询层实现“摘要 + 最近消息 + 有针对性的检索”。只把底层换成 SQLite，但每次读取仍 `SELECT *` 并构建完整 Vec，RAM 仍随单个长会话增长。

## 4. 低内存基准：它证明了什么、没有证明什么

### 4.1 仓库中当前的实测数据

数据在 `docs/src/components/MemoryChart.tsx`，测试驱动在 `crates/infinity-agent-core/examples/agent_scale.rs`。图表注释给出的测量环境和方法是：AMD EPYC 9R14 单线程、本地内存 stores、进程内 scripted model、`AGENTS=80000 TURNS=20 WAVE=4000`。每个合成 turn 有两轮 completion 与一次异步工具回环。每一波 agent 完成 20 轮后，等待 idle driver 退出、清理生命周期通知，再采样 RSS。

| Agent 数 | 实测 RSS（十进制） | 说明 |
|---:|---:|---|
| 0 | 5,304,320 B | 基线 |
| 4,000 | 692,879,360 B | 第一波完成后采样 |
| 8,000 | 1,101,406,208 B | 两波累计 |
| 12,000 | 1,507,291,136 B | 三波累计 |
| 40,000 | 4,348,772,352 B | 逐波累计 |
| 80,000 | 8,406,446,080 B | 图表终点 |

从 0 到 80,000 的端点平均增量是 `(8,406,446,080 - 5,304,320) / 80,000 = 105,014 B/agent`，约 **102.55 KiB/agent**。如果仅按这个全区间平均值作粗略线性估算，10,000 个会话约增加 1.05 GB；但图表早期不是严格直线，8,000 和 12,000 两点之间的线性插值约为 1.30 GB。因此不要把 102.55 KiB 当成固定的单会话保证，实际部署应按自己的历史分布复测。

### 4.2 正确解读

该基准最有价值的证据是：**大量 Agent 完成工作并变为空闲后，driver/task 生命周期开销可以被释放；剩余 RAM 主要体现 store 中的对话和元数据。** 它不是 80,000 个同时调用真实 LLM 的压测，也不是“8 GB 设备承载 80,000 个任意长度会话”的证明。

它没有覆盖：真实模型客户端及流缓冲、网络连接、真实工具的大型输出、同时执行上限、长达数月的消息历史、真实 SQL 索引/页缓存、重试积压、多个租户、OOM 恢复，也没有测本地模型权重与 KV cache。示例将模型 context window 设为 0 以关闭自动 compaction，使历史增长确定；每轮模型文本形状固定，只有合成工具调用。

所以，基准可以支持“每个空闲 Agent 不必保留完整运行时对象”和“内容很小的 80k 空闲历史在这次环境中占约 8.4 GB RSS”，但不能支持生产容量承诺。完整消息文本本身仍会占空间；若每个会话历史或工具输出增大十倍，RAM-backed store 通常也会近似按字节增长。

## 5. Hermes Agent 现状给出的参照

截至本报告核对的 Hermes 官方版本（commit `d4865574e47497e9a9cd1d21333b8c008a9e8a34`），官方文档把两件事分开：

- **持久事实来源：** Session Storage 使用 SQLite 保存规范会话消息，并通过 FTS5 支持历史检索；Gateway 是权威写入者，其他客户端通过 Gateway 协作访问。数据库还包含 per-session durable FIFO admissions 和 delivery outbox 等状态表。
- **小型路由索引：** Gateway 的 `SessionStore` 仍维护内存 `_entries` 字典并持久化到 `sessions.json`，保存 session key 到 ID 的映射和标志/时间戳等 metadata。它意味着一些内存仍可能随 session 数增长，但这些元数据与把完整 transcript、工具输出和 agent 对象全量常驻 RAM 是不同量级的问题。
- **热会话对象：** Gateway 为近期 session 缓存运行中的 `AIAgent`，用以复用模型上下文/prompt 前缀。文档描述该对象会保留完整 transcript（包括工具输出），在历史变长时可达几十 MB；新请求可从 SQLite 重新构建已淘汰的对象。
- **回收控制：** Gateway Agent Cache 文档列出默认缓存规模 128、默认 idle TTL 1 小时、LRU，以及基于 `memory_high_mb` 的动态内存压力回收；默认每轮最多回收 16 个 entry，并保护最近使用的 8 个 session。压力回收还会跳过进行中的 turn 和尚未可靠持久化的 transcript。它是越过匿名内存预算后的反应式回收策略，不是瞬时 RSS 硬上限；若可回收项都受保护，内存可能继续高于目标。

这修正了“市面上 Agent 一律把所有历史会话常驻内存”的概括：Hermes 的规范历史并非只存在 RAM，但最近/活跃 Agent 对象仍有内存缓存。它也说明 **entry-count/TTL 与 byte budget 是两回事**：128 个 session 的上限不直接限制单个大 session 的体积；活跃会话不能安全回收时，压力策略可能需要等待安全边界。

此对比不应被读成 Infinity 与 Hermes 的 per-session 直接性能排名。二者基准、每个 session 的消息量、工具输出、模型和驻留状态口径均不同。可借鉴的是状态分层：**SQLite/其他持久层做规范状态，内存只作可以重建的热缓存，并在对象回收前确保规范状态已经提交。**

## 6. 推荐目标架构：本地优先、状态持久、执行无状态

### 6.1 组件图

```text
本地 HTTP / CLI / RAP 入口
        │ 鉴权、限流、生成稳定 dedup_id
        ▼
本机持久化 inbox / session DB / outbox  ◄── 磁盘上的消息、状态、租约、工具任务
        │ 只领取有配额的 ready 工作
        ▼
有限 worker pool（并发 C；同一 thread 单飞）
        │ load bounded prompt context
        ▼
AgentSystem::step + Infinity tools/model adapter
        │ transaction: append result + state + tool outbox
        ├──────────► 本地工具进程或本机 RAP 服务
        │                    │ 完成回调/定时任务作为新 inbox event
        └────────────────────┘
```

运行期内存应近似满足：

```text
RSS ≈ 固定运行时基线
    + 活跃切片数 C × 每个活跃切片工作集 W
    + 受字节上限约束的热缓存 B
    + 受大小/背压约束的临时网络与结果缓冲
```

会话总数 `S` 和历史总量应主要影响磁盘/数据库容量、索引大小和备份量，而不应让一个长期存活的 Rust HashMap 永远持有所有会话正文。该式是容量规划模型，不是对 RSS 的数学硬保证；allocator、数据库页缓存、网络层仍须实测并设置进程/容器安全余量。

### 6.2 关键数据与事务边界

单机首版可以把 SQLite 作为权威状态库，表按实际查询设计：`sessions/threads`、`messages`、`processed_inputs`、`tool_invocations`、`inbox`、`outbox`、`leases`。核心规则：

1. 入口将输入以稳定 dedup key 写入 inbox；唯一约束让重复投递可安全识别。不要先把消息只放进进程无界 channel，再假设它已耐久。
2. scheduler 按 thread key 领取任务。DB 里用租约/过期时间支持 worker 崩溃后的重试；同一 thread 保证 FIFO/单飞，不同 thread 在并发配额内运行。
3. 执行器仅加载该次切片需要的历史视图。执行结果、追加消息、processed ID 和待派发工具记录在同一个 DB 事务中提交，避免“对话已写入但工具没入队”或“工具已发出但会话状态未落盘”的窗口。
4. 独立 outbox dispatcher 执行外部工具/HTTP 调用；结果回调再次写入 inbox。跨进程/外部工具的 exactly-once 通常无法仅靠本地事务实现，因此使用幂等调用 ID、可重试协议、超时后的状态核对和人工可审计的未知结果状态。
5. 持久化错误必须向调用者返回或可靠报警；不能把写失败变成成功响应。崩溃恢复和磁盘满是正常故障模式，不是仅在开发环境处理的边缘情况。

这套模式允许把当前 Infinity `InputSender` 实现为本地 durable queue adapter；执行 engine 继续使用 `ConversationStore` 和 `StateStore` 契约。若 step 批次可能包含很多 thread，入口也应先限批，再由 scheduler 做限并发，不能把整个待处理 backlog 一次性 `Vec` 到内存。

### 6.3 上下文构建必须有预算

持久化完整历史不等于每次模型调用都应加载完整历史。建议将“规范归档”与“模型可见上下文”分开：

- 规范层保存完整、有序、可审计的原始消息和工具结果；工具输出过大时可把原文转成本地文件/blob，并在消息中保留权限受控的引用与摘要。
- 执行层按 token/字节预算构造 prompt：系统提示、最新对话窗口、最近 compaction summary、未完成工具调用闭合信息，以及按需检索的历史片段。
- `ConversationStore` 新增有界读取/分页/`load_prompt_context` 能力；不要将长历史的全量 `Vec` 作为唯一可用 API。页边界要保留 assistant tool call 与对应 tool result 等协议完整性。
- 旧消息检索是一次性短任务，完成后丢弃结果；检索索引和 embedding 需按需加载或由单独服务管理，并同样纳入资源预算。

如产品要求完整 transcript replay，可从数据库分页流式传给 UI；不要为了 replay 把所有 thread 的所有历史常驻进单个进程。

### 6.4 worker、缓存和流量的硬预算

- worker pool 设置全局 `C`、模型供应商并发、每租户配额和工具并发额度。达到上限时保留任务在 durable inbox，入口等待或返回明确的过载信号。
- 每 thread 只允许一个正在处理的 turn；不同 thread 并行。定义用户消息在正在运行的工具/模型调用期间是排队、打断还是合并，避免无意积累无界 per-thread channel。
- 热缓存同时设 `max_entries`、`max_bytes`、单 session 最大驻留字节和 TTL。以“总字节”做硬约束，entry 数和 TTL 只作辅助策略；缓存只能加速，不可成为唯一状态来源。
- 限制 prompt 输入、模型输出、工具 stdout/stderr、图片/附件大小；大对象流式落盘。RSS 高水位时先停领新任务，再回收可重建缓存，不能等到 OS OOM killer 处理。
- 对话存储与 state 索引分别设置保留/压缩/归档策略。去重 ID 也会随 lifetime message 数增长：需要定义去重保留窗口、持久化唯一键或可证明安全的过期策略，而不是无限 HashSet。

## 7. 本地、私有部署和云部署的选择

| 形态 | 典型构成 | 是否云化 | 适用和主要边界 |
|---|---|---|---|
| 单机本地优先 | 一个 Infinity worker 服务 + 本机 SSD/SQLite + SQLite WAL + DB 驱动的 inbox/outbox + 本地工具 | 否 | 单机、数据留本地、离线/低运维；需要备份、磁盘监控和同机故障恢复设计。数据库写并发需压测。 |
| 自托管多进程/多机房 | Infinity worker + 自管 PostgreSQL/队列，部署在自有服务器/内网 | 不一定 | 需要横向扩容或更高写并发，但数据和运维仍由团队控制；需定义主从、故障转移和网络分区策略。 |
| 云托管/Serverless | Infinity step handler + SQS 等队列 + 云数据库 + 托管模型/工具 | 是 | 低运维和弹性扩缩容；引入网络/供应商依赖、费用、数据驻留与权限边界。 |

SQLite 官方说明 WAL 支持读写并行，但仍只有一个 writer；它适合作为同机存储，不是多主写入数据库，也不应把 WAL 数据库放到不支持其共享内存/锁语义的网络文件系统上。因此本地方案不应把“SQLite”当成无限吞吐承诺；若写并发和 HA 超出单机边界，可迁移到本地/自管 PostgreSQL 或云数据库。无论哪种 DB，执行器仍要限并发和限制上下文大小。

另一个容易混淆的“外置”是模型推理：可使用远端模型 API，同时将会话数据库和 Agent worker 留在本机；也可运行本地模型，但需另算模型权重和推理显存/RAM。**模型在哪里、存储在哪里、worker 部署在哪里，是三个可分别选择的维度。**

## 8. 建议实施路线

### P0：先用可复现负载建立真实预算

- 保留现有 80k 脚本基准，增加不同消息体积、长工具输出、图片引用、不同历史轮次和活跃率场景。
- 输出 RSS、进程 heap、活跃/空闲 driver 数、队列深度/字节、缓存字节、读取历史条数/字节、p50/p95 切片耗时、DB/WAL 大小。
- 按 `S=1k/10k/100k`、活跃比例和历史分布建矩阵；重点看“session 数加倍但活跃数和 cache budget 固定时，RSS 是否近似稳定”。

### P1：打通单机持久化与可靠队列

- 新增可替换的 SQL `ConversationStore` / `StateStore` 实现，测试进程重启后的消息、线程树、compaction cutoff、去重、待用户选择和工具状态恢复。
- 将输入 inbox、工具 outbox 与状态变更做事务化；实现 lease、重试、幂等和 dead-letter/人工恢复路径。
- 先支持单机 SQLite WAL；错误必须可见、可监控，测试磁盘满、损坏、锁竞争、进程被杀和 WAL checkpoint。

### P2：把执行并发、缓存和上下文都变成有界

- 选择 step handler 或改造 local router 为受限 scheduler；加入 worker semaphore、per-thread single-flight、入口背压和本地 durable backlog。
- 设计 bytes-aware session cache；默认不把所有历史会话恢复到 RAM。只缓存可丢弃的 prompt view/热 metadata。
- 增加 token/字节约束的上下文加载 API；对过大工具响应使用磁盘/blob 引用与摘要。

### P3：完成规模与故障验收，再决定是否多机

- 在相同机器和固定样本上对比内存 store、当前 JSON wrapper、新 SQL store 的 RSS、写放大、恢复时间和切片延迟。
- 故障测试包括：重复投递、相同 thread 并发、模型超时、工具已执行但回执丢失、worker 被杀、数据库满、重启后队列恢复、缓存压力回收。
- 只有当本地 DB 写入/磁盘容量/单机可用性实际成为瓶颈，再拆成多个服务或迁移到集群/云。不要先云化，再把同一套无界内存对象搬过去。

### 建议验收标准

1. 当历史 session 数增加一个数量级、但活跃 worker 数和缓存字节预算不变时，进程 RSS 不随历史正文线性增加；由归档数据引起的 RAM 上界有明确预算。
2. worker 活跃数、在内存排队消息字节和单 thread prompt bytes 均有硬上限；上限触发后任务保留在持久层并出现可观测的背压。
3. 任意位置 kill/restart 后，输入不静默丢失；重复消息不重复改变状态；不确定结果可审计、可重试/补偿。
4. 同 thread 的顺序及工具调用/结果配对在分页、压缩、缓存淘汰和重启后保持正确。
5. RSS、p95 延迟、队列等待、数据库错误、磁盘/WAL 水位、cache hit/eviction、OOM/过载拒绝都有指标和告警。

## 9. 最终判断

Infinity 最值得借鉴的不是某个数据库或 AWS 组件，而是 **把 Agent 视作可重建的执行切片，等待中的工作用消息表达，单 thread 状态持久化，空闲时销毁执行器**。这能够把大量“并不活跃”的会话从执行资源里剥离出来。

但 Infinity 当前工作区里的 in-memory store 与 daemon JSON wrapper 都还会将被触达的历史/状态累积在进程内存；local 输入队列和活跃 worker 也没有生产级的服务配额。因此，结论不是“直接开箱就能用 10 万会话低内存托管”，而是：**架构方向适合，仓库已有良好扩展接口和执行生命周期基础；要兑现有界内存，需要补本地/远端事务型持久化、durable queue、有限 scheduler、按字节有界缓存和有界 prompt 构建。**

这些补齐可以全部部署在同一台自有机器上。云化是部署和运维选择，不是低内存的前提。

## 10. 资料与证据

### Infinity 仓库（本地源码，版本见报告首页）

- `crates/infinity-agent-core/src/system/local/router.rs:1`、`:254-396`：driver future 所有权、按 thread 路由、idle 生命周期、worker/channel 创建。
- `crates/infinity-agent-core/src/system/local/sender.rs:21-53`：local 输入队列为 unbounded channel。
- `crates/infinity-agent-core/src/stores.rs:65-73`、`:226-255`、`:420-427`：in-memory history、thread 和 state map 的实现。
- `crates/infinity-agent-core/src/traits.rs:25-65`、`:220-320`：ConversationStore/StateStore/InputSender 抽象与 history API。
- `crates/infinity-daemon/src/memory_store.rs:349-374`、`:420-451`、`:762-807`、`:970-1079`：JSON 快照持久化、懒加载进 core store、state store 装载/写回。
- `crates/infinity-agent-core/examples/agent_scale.rs:1-20`、`:235-319` 与 `docs/src/components/MemoryChart.tsx:1-42`：基准 workload、运行方式和当前图表数据。
- `docs/docs/infinity-runtime/architecture.md`、`docs/docs/infinity-runtime/agent-systems/step-mode.md`、`docs/docs/infinity-runtime/serverless/architecture.mdx`：step 语义、消息回环、AWS Lambda/SQS embedding。

### 官方外部资料（于 2026-10-30 核对）

- [H1] Hermes Agent 官方文档：[Session Storage](https://hermes-agent.nousresearch.com/docs/developer-guide/session-storage)（SQLite 规范历史、Gateway 写入模型），研究时对应上述 Hermes commit。
- [H2] Hermes Agent 官方文档：[Gateway Session Lifecycle](https://hermes-agent.nousresearch.com/docs/zh-Hans/developer-guide/gateway-session-lifecycle)（路由 metadata、Agent cache、session 重建和生命周期），研究时对应上述 Hermes commit。
- [H3] Hermes Agent 官方源码：[Gateway Agent Cache 默认配置](https://github.com/NousResearch/hermes-agent/blob/d4865574e47497e9a9cd1d21333b8c008a9e8a34/hermes_cli/config_defaults.py)（默认容量、idle TTL、每轮回收数和近期 session 保护值），固定到上述 Hermes commit。
- [S1] SQLite 官方文档：[Write-Ahead Logging](https://www.sqlite.org/wal.html)（WAL 的并发与文件系统边界）。
- [S2] SQLite 官方文档：[Appropriate Uses For SQLite](https://www.sqlite.org/whentouse.html)（嵌入式/本地数据库与 client-server 场景的选择边界）。

> 本报告中的 Infinity 结论以指定工作区源码为准；Hermes 与 SQLite 用于架构对照，不是 Infinity 已实现能力的证据。容量数字只对应报告所述脚本和采样方式，应以目标 workload 的压测结果替代。
