开源 Agents 调研

开源 Agent 实现调研

本文围绕 Hermes Agent、Prime Agent、Letta Code 和 OpenClaw,分析它们如何积累经验、管理长上下文、保存长期记忆,以及组织 Agent 的运行循环。调研基于 2026-09-06 获取的官方文档和源码快照,结论对应文中列出的具体版本;本次未运行项目,也未进行学习效果、召回率、延迟或成本测试。

Overview

四个项目都支持经验积累和长时间运行,但各自侧重不同。下面先比较核心机制,再分别展开实现细节。表格反映的是能力如何实现,不代表性能或效果排名。

项目 自主学习 长上下文管理 持久 Memory Agent loop 编排
Hermes Agent · 详解 执行中可主动记忆,回合结束后按条件复盘,将经验写成笔记和技能。 将过长工具输出存到文件,压缩旧对话,保留近期消息,并按需检索历史。 短小的常驻记忆文件、技能目录和 FTS5 历史检索;可接入外部记忆服务。 Python 主循环按条件调用工具;工具分段并发,支持子任务和定时任务。
Prime Agent · 详解 自动检查或手动触发 /refine,更新四类框架状态,支持回滚;默认限于当前会话。 持久 Python REPL 保存工作数据,结合对话摘要、原始日志和独立子会话。 会话级与全局 JSON 记忆;摘要进入提示,详情通过 Python API 读取。 后台服务托管会话;目标、质量检查和调度策略决定是否继续运行。
Letta Code · 详解 主动编辑记忆,回合结束后按条件反思;在独立 Git 工作树中整理经验并合并。 后端维护上下文,摘要与完整历史分开保存;本地模式的压缩逻辑已开源。 Git 管理的 MemFS;核心内容进入提示,其余按需读取,同一 Agent 跨会话复用。 客户端与后端交替推进;客户端负责本地工具审批、执行和结果回传。
OpenClaw · 详解 Dreaming 分阶段巩固记忆,Skill Workshop 维护技能;两者默认均支持自动运行。 旧工具结果裁减、对话压缩和压缩前记忆写入相互配合;具体策略取决于运行时。 Markdown 保存内容,SQLite 保存索引与状态;支持关键词及向量混合检索。 网关与队列控制会话执行,支持多种运行时、后台子任务和异步结果交付。

阅读时需要区分四件事:

  1. 学习的对象是什么。 四个项目主要通过修改提示、记忆和技能来复用经验。本次核查未发现这些常规运行路径会更新模型权重;自动记录经验能否提高任务成功率,仍需实测。
  2. 当前窗口与长期记忆分别解决什么问题。 上下文管理通过限制输入、压缩旧消息、检索历史和拆分子任务,让当前工作继续推进;长期记忆则保存以后仍值得使用的知识。两者相互配合。
  3. 记忆在哪个范围内复用。 Prime 默认将经验保存在当前会话中,新会话需要通过全局记忆才能复用;Letta 主要按 Agent 共享记忆;Hermes 通常按配置档案(profile)共享;OpenClaw 还考虑会话类型和私聊隔离设置。
  4. 一次运行何时算结束。 模型完成一轮回复、Agent 结束一次运行、目标被标记完成,以及调度器不再唤醒任务,是不同层次的状态。理解这些区别,才能判断后台运行和恢复机制究竟保留了什么。

版本基准

本次分析固定在以下主分支提交上,它们可能与已安装的发布版本不同。源码引用均指向具体提交,便于后续复核;持续更新的官方网页作为补充资料。

项目 固定 commit 提交时间(Asia/Shanghai)
Hermes Agent 245e48008fa8 2026-09-06 08:00:18
Prime Agent 9c54a35dac3a 2026-09-06 03:12:41
Letta Code 701f2a536782 2026-09-06 09:02:04
OpenClaw 047fdfe90fef 2026-09-06 11:06:22

术语说明

文中的 harness(运行框架) 指模型之外负责工具执行、会话状态、上下文管理和调度的代码。Agent loop(运行循环) 是其中反复执行“模型推理—工具调用—结果回传”的过程。涉及触发频率时,本文保留各项目的计数口径,避免将模型回复轮次与用户消息条数混为一谈。

概念 本文含义 容易混淆的边界
自主学习 从执行过程、用户纠正和任务结果中提炼经验,保存后供后续任务使用。 需要同时考察触发、写入、检索和效果验证。
工作上下文(working context) 当前模型请求携带的系统提示、消息、工具定义和结果。 内容必须进入模型请求,才会占用当前上下文窗口。
压缩摘要(compaction summary) 为继续当前工作而生成的对话摘要。 压缩会丢失部分细节,摘要也可能随任务推进而变化。
事件历史(episodic history) 原始对话、工具调用和执行事件。 用于恢复、检索和追溯,通常不会全部放入模型请求。
事实记忆与程序性记忆 前者保存事实、偏好和决策,后者保存可复用的步骤与技能。 文件、数据库和向量检索是不同实现方式。
参数学习 通过训练更新模型权重。 应与提示、记忆和技能的更新分别讨论。

下图概括四个项目共有的工作方式。各项目的具体调用链在后文展开。

运行时流程图可直接跳转至:Hermes、Prime、Letta Code、OpenClaw。图中实线表示主要控制流,虚线表示按需读取、后台触发或后续复用。为突出关键步骤,图中省略了部分模型服务适配和失败清理分支;压缩、复盘与调度均按各项目的配置和触发条件执行。

flowchart LR
    A[用户输入或调度唤醒] --> B[组装本轮上下文]
    M[持久记忆与技能] -->|核心注入或按需加载| B
    B --> C[模型与工具循环]
    C --> H[原始历史与执行产物]
    C --> D{窗口压力}
    D -->|压缩与外置| S[摘要及保留尾部]
    S --> B
    H -->|检索旧细节| B
    C -->|满足触发条件| R[经验复盘]
    R --> V[写入校验与可选评估]
    V --> M
    C --> E[本次运行结束]
    E -->|目标或调度策略继续| A

Hermes Agent

1. 自主学习:将交互经验整理为记忆和技能

Hermes 提供两条经验积累路径。执行任务时,主 Agent 可以主动调用 memory 和 skill_manage;回合结束后,系统也会按条件启动后台复盘。默认情况下,记忆复盘每累计 10 个用户回合触发,技能复盘则在累计 10 次工具迭代后检查。后台任务要求本轮已生成最终回复、未被中断,且没有设置 skip_background_review。自动复盘可以关闭,也可以通过 /refine 手动发起。H1

后台复盘以刚完成的对话为材料:使用同一模型时读取对话快照,使用另行配置的模型时读取摘要历史。它重点寻找用户纠正、有效的解决步骤,以及缺失或过时的技能。更新顺序是先修订本次用过的相关技能,再考虑其他已有技能及其辅助文件,最后才创建新技能。

复盘任务只能使用记忆、技能管理和相关读取工具。修改现有技能前必须重新读取内容,而且后台只能修改由整理器管理的技能;用户自有、固定、内置及从 Hub 安装的技能受到保护。H2

复盘结果会写入 $HERMES_HOME/skills/.../SKILL.md、技能的参考资料、脚本和模板,或 memories 目录下的记忆文件。之后执行任务时,模型先根据系统提示中的技能名称和描述判断是否需要使用,再通过 skill_view 加载正文及关联文件。短记忆则直接进入系统提示,从而形成“整理经验—保存—再次使用”的过程。H3

技能写入会检查元数据和文件大小,并提供格式检查(lint)及修改前读取保护;对 Agent 创建技能的安全扫描属于可选项,默认关闭。这些检查约束的是文件质量与修改过程。经验本身是否正确,仍主要由模型判断。本次未发现常规复盘路径会强制运行新旧技能的对照测试,再按得分决定是否采用更新。H2、H3

Hermes 还提供技能整理器(curator),默认每 7 天、且空闲至少 2 小时时检查一次。默认只按规则处理长期未用的技能:30 天后标为过时,90 天后归档;由 LLM 合并和整理技能的功能默认关闭。run_curator_review 会先备份,再更新技能状态,并按配置启动整理任务、记录报告。H4

2. 长上下文:压缩对话,保留可检索的原始材料

Hermes 默认使用内置 ContextCompressor,也可以通过配置替换为插件。压缩阈值会随模型窗口和输出预留量调整:基础比例为 50%,窗口小于 512,000 tokens 时至少提高到 75%,部分 Codex 路由还会提高到 85%。这个比例作用于扣除输出预留后的有效输入预算,并受最小阈值和绝对上限约束。token 用量优先采用 API 返回值,缺失时再估算;Gateway 在回合开始前另有一层 85% 的会话容量检查。H5

压缩先从成本较低的清理开始,例如裁减旧工具结果和空白行,再把对话分为开头、需要概括的中段和近期消息。辅助模型负责总结中段,系统随后修复工具调用与结果的配对关系。默认 lean 模式为近期消息分配窗口的 2.5%,限制在 10K–25K tokens 之间,同时保护最近 20 条消息和至少一条真实用户消息;这些保护规则可能使实际保留量超过软预算。

摘要还会附上程序提取的标识符索引、预算允许范围内的用户原始请求,以及通过 session_search 找回细节的提示。过大的摘要输入需要采样,因此这仍是有损压缩。需要保留更多近期消息时,可以选择 legacy 模式。H6

默认的原地压缩保留会话 ID,并将旧消息标记为 active=0, compacted=1。它们退出当前上下文后,仍可在 SQLite 中检索;旧式会话轮换也是可选方案。这样,摘要负责让当前任务继续,原始历史负责补回细节,整理后的记忆负责跨会话复用。自动压缩失败后会按 60、300、900 秒冷却,持续无效时暂停自动尝试;手动 /compress 和上下文溢出后的恢复路径仍可在限制内重试。H5、H6

过长的工具结果会单独存到文件中。默认上限是普通结果 100K 字符、MCP 结果 50K 字符、每轮合计 200K 字符,小窗口会进一步缩小这些限额。超限正文保存在 $HERMES_HOME/cache/spillover,上下文只留下约 1,500 字符的预览和文件路径。read_file 不受这项规则影响,以便读回已保存的内容;多模态结果另行处理。若保存失败,系统会明确标记结果已被截断。H7

子 Agent 使用独立的消息上下文,父 Agent 传入目标和必要背景,而不是默认复制全部历史。子任务返回摘要时,还会根据父窗口的剩余容量限制长度,减少中间材料对主任务的占用。H11

3. 持久记忆:短笔记、技能与历史库各司其职

内置记忆保存在 $HERMES_HOME 下,默认目录通常是 ~/.hermes。其中 memories/MEMORY.md 记录环境和经验,memories/USER.md 记录用户信息,默认容量分别为 2,200 和 1,375 字符,条目之间用 \n§\n 分隔。每个 AIAgent 持有自己的 MemoryStore 实例,写入时会加文件锁、重新读取最新内容,再原子保存。

记忆工具支持添加、替换、删除,以及按最终容量检查的原子批量操作,修改目标通过唯一子串定位。超出容量时,工具返回错误,由模型合并或删减条目;每回合的失败次数也有限制。H8

这两份短记忆不做向量检索,而是整体构成系统提示中的记忆快照。任务执行中的记忆修改会先写入文件,不会每次都刷新提示前缀;上下文压缩后,invalidate_system_prompt 会重新从磁盘加载记忆并重建提示。主 Agent、后台复盘任务和用户都可以更新记忆文件,相关入口权限与写入审批可以另行配置。H8、H9

原始对话保存在当前 profile 的 state.db 中。session_search 使用 SQLite FTS5,支持查找会话、浏览内容,以及围绕某条消息继续读取。默认返回 3 个结果,并按需调整详细程度,检索本身不需要调用 LLM。当前源码对发现结果中的每条消息设有 4,000 字符的返回上限;需要完整细节时,可以继续滚动或读取原消息。这比官方页面“不截断”的概括更具体。H10

记忆默认按 profile 或主目录共享,同一 profile 下的多个会话使用同一份记忆。删除记忆条目不会自动删除原始历史。session_search(profile=...) 支持只读访问其他 profile,按会话 ID 也能定位相应数据库,因此 profile 更接近状态组织方式,而不是对同一系统用户的严格权限隔离。

此外,memory.provider 可以接入与内置记忆共存的外部服务。Honcho、向量或图检索等能力需要分别看所选服务,本文未逐一验证这些插件的检索和删除行为。H8、H10、H12

4. 运行循环:模型调用、工具执行与任务调度

运行时流程图

下图展示 Hermes 自有运行循环。可选的 codex_app_server 模式会将整个回合交给另一运行时处理,图中未展开。常规路径中的后台复盘在回复交付后启动,与前台工具执行分开进行。H1、H5、H11、H12

flowchart TB
    HIn["CLI / Gateway 用户输入"] --> HBuild["AIAgent.run_conversation<br/>build_turn_context:消息与系统提示"]
    HCron["Cron 到期:创建独立 AIAgent<br/>加载 memory,关闭后台复盘"] --> HBuild
    HMem[("MEMORY.md / USER.md<br/>技能目录")] -. "初始化或提示刷新时加载" .-> HBuild
    HBuild --> HCheck{"准备下一次模型调用<br/>中断或预算耗尽?"}
    HCheck -->|是| HStop["结束运行并记录状态"]
    HCheck -->|否| HCtx["检查上下文预算<br/>按需压缩,保留近期尾部"]
    HCtx --> HModel["组装请求与 preflight<br/>模型 API 调用"]
    HModel --> HResult{"模型调用结果"}
    HResult -->|可恢复错误| HRetry["分类恢复与有界重试<br/>溢出时尝试压缩"]
    HRetry --> HCheck
    HResult -->|不可恢复错误| HStop
    HResult -->|工具调用| HTools["run_tool_round<br/>可并发工具分段执行,串行屏障"]
    HTools -. "delegate_task" .-> HChild["独立子 Agent 上下文<br/>父中断传播"]
    HChild -. "结果或任务状态" .-> HOut["工具结果回填<br/>超限正文卸载,保留预览与路径"]
    HTools --> HOut
    HTools -. "memory / skill_manage" .-> HMem
    HOut --> HCheck
    HResult -->|最终文本| HFinal["finish_text_response / finalize_turn<br/>交付回复并持久化"]
    HFinal --> HStop
    HOut -. "执行轨迹" .-> HHistory[("SQLite 原始历史<br/>spillover 工具正文")]
    HFinal -. "保存对话" .-> HHistory
    HHistory -. "session_search 或按路径读回" .-> HTools
    HFinal -. "达到复盘间隔且未中断" .-> HReview["后台 fork 复盘<br/>受限工具与技能保护规则"]
    HReview --> HMem

    classDef runtime fill:#e8f1ff,stroke:#5278b8,color:#152a46;
    classDef memory fill:#e8f5eb,stroke:#528763,color:#173e24;
    classDef background fill:#f1eaff,stroke:#8764aa,color:#38204e;
    class HBuild,HCtx,HModel,HTools,HOut,HFinal runtime;
    class HMem,HHistory memory;
    class HCron,HChild,HReview background;

AIAgent 将任务交给 agent.conversation_loop.run_conversation。它先通过 build_turn_context 准备上下文,再进入由 begin_iteration 和 prepare_iteration 驱动的循环:组装请求、执行请求前检查、调用模型,然后规范化返回结果。有工具调用时进入 run_tool_round,获得最终文本时进入 finish_text_response,最后由 finalize_turn 保存状态并按条件启动复盘。整个过程由显式 Python 状态循环控制。H12

运行时通过 max_iterations 和共享的 iteration_budget 控制迭代次数,也可另设时间预算。构造器默认使用 sys.maxsize,相当于没有实用的迭代上限。最终回复、预算耗尽、中断,以及无法恢复的 API 或持久化错误都可能结束运行。API 外层默认最多尝试 3 次,但具体处理取决于错误类型;上下文溢出还有单独的压缩次数限制。硬中断和运行中追加指令(steer)也有各自的状态处理路径。H12

_plan_tool_batch_segments 按模型给出的顺序将工具调用分段。允许并行的只读操作、目标文件互不冲突的操作,以及显式允许并发的 MCP 调用可以放在同一段;其他工具作为串行边界。底层分别提供顺序、线程池和分段执行器,并支持超时及中断。H11

delegate_task 通过新建 AIAgent 执行子任务,设置 skip_memory=True,并禁用子任务的记忆、定时任务和用户询问工具。默认最多并发 10 个子任务,委派深度为 1,深度可配置,父任务的中断会传递给子任务。文件系统隔离需要另外配置,例如使用独立 Git 工作树。

定时任务则沿 tick → run_one_job → run_job → _construct_cron_agent → run_conversation 执行,独立保存并投递结果。它支持并行运行,也支持不调用 LLM 的纯脚本任务。当前版本的定时 Agent 会加载记忆(skip_memory=False),但关闭后台复盘(skip_background_review=True)。H11、H12

源码导航

H1 复盘触发及默认值:记忆复盘的回合计数;后台复盘触发条件;默认间隔。

H2 复盘材料、更新策略与后台执行:技能纠错与保护规则;工具白名单与复盘入口;自动启用。

H3 技能读写及验证边界:技能索引与正文读取;写入位置与可选扫描;格式校验;格式检查的提示性质。

H4 技能整理器实现:默认周期与规则式清理;完整整理流程;官方触发说明。

H5 压缩默认与例外:压缩引擎、双阈值与冷却说明;75% 下限实现;配置和可选剪枝。

H6 有损压缩与恢复:压缩主流程;lean 模式的近期消息预算;程序提取的恢复信息;阈值和熔断。

H7 过长工具结果的文件存储:预算、豁免和窗口比例;正文保存与失败时截断;调用链。

H8 内置记忆存储与修改:格式、默认容量、快照、原子操作;profile 路径与批量操作;增删替换。

H9 压缩后刷新记忆快照:invalidate_system_prompt;系统提示注入。

H10 历史检索及隔离边界:发现结果截断、FTS 查询;4,000 字符限制与查询实现;跨 profile 只读访问;默认参数。

H11 工具并发和子任务:分段调度入口;子 Agent 构造;子任务工具限制;默认并发数与委派深度;按父窗口限制结果长度。

H12 主循环、外部记忆与定时任务:主循环与运行时分支;默认迭代上限;API 默认重试配置;可选外部记忆服务;定时 Agent 的记忆与复盘开关;定时任务的 Agent 执行入口。

Prime Agent

实现定位

Prime 的设计分为两层。RLM 执行环境提供持久 Python REPL,让模型用代码处理数据、调用工具和委派子任务;Continual Harness 保存可编辑的提示补充、事实记忆、技能调用说明和子 Agent 规范。TypeScript AgentSession 负责模型请求、调度、压缩和持久化。正常交互由后台服务托管,关闭终端只会断开客户端连接,执行进程可以继续工作。架构

1. 自主学习:检查经验,更新可复用的框架状态

  • 触发检查。 用户可以执行 /refine,模型也可以通过 refine.run 请求更新。自动检查 autoRefine 默认开启,每累计 25 个 assistant turns(模型回复轮次)检查一次,压缩后也可触发,默认冷却时间为 20 分钟。只有具备持久 harness 目录的根会话才启用这条自动路径;是否写入,还要看后续判断。默认配置、根会话限制
  • 提炼经验。 自动路径先由 LLM 判断 shouldRefine。通过后,系统结合现有状态、历史更新记录和执行轨迹,生成 JSON 格式的新增、修改或删除提案。轨迹输入取序列化会话的最后 80,000 字符。提案可以修改 prompt / memory / skill / subagent 四类条目,基础系统提示保持固定。经验检查调度、提案生成
  • 保存并复用。 应用提案前,系统校验字段,并检查相关条目是否在生成提案期间被其他操作修改。更新保留版本及修改前后内容,便于回滚;应用后重建系统提示,供后续轮次使用。默认写入当前会话的状态库(session-local),只有显式选择 global 时,经验才进入跨会话共享的状态库。应用与冲突检查、落盘及重新注入

需要区分状态更新与效果验证。expectedOutcome 记录的是预期收益,字段校验和冲突检查只能确认提案是否可以应用。技能条目保存 Python 能力的调用契约;/refine 不会仅凭一段描述就自动构建、测试并安装一个新 Python 包,可执行技能另有创建流程。本次未在这条路径中发现参数训练。经验更新约束、技能机制

2. 长上下文:用持久 REPL 保存数据,用摘要管理对话

  1. 把工作数据留在执行环境中。 默认内置模型工具是 ipython。文件内容、解析结果和函数可以保存在 Python 环境里,需要时再读取或打印;rlm(...) 则为子任务建立独立会话。这样每次请求只需携带当前推理所需的信息,实际打印到对话中的内容仍会占用窗口。RLM 接口
  2. 压缩增长中的对话。 自动压缩默认开启,条件为 contextTokens > contextWindow - reserveTokens。默认预留 16,384 tokens,并尝试保留最近约 20,000 tokens 的消息。LLM 为旧内容生成摘要,JSONL 则继续保留原始条目和压缩记录;后续模型请求使用“摘要、保留消息和新增消息”重建上下文。预算及触发、上下文重建
  3. 按能力范围恢复执行状态。 Python 内核通常在压缩后继续保留,系统会把剩余变量名告知模型,同时清理超过单变量快照限制的变量。进程重启后,通过 dill 尽可能恢复可序列化对象,默认快照总量上限为 256 MiB,单变量上限为 16 MiB;无法序列化的对象会被跳过。较大的数据因此更适合显式保存为文件。压缩后变量处理、快照限制

3. 持久记忆:区分会话状态与全局经验

层 存储与使用方式
会话经验 保存于 <session artifact dir>/harness/harness_state.json。默认更新写入这里,恢复同一会话时继续使用。
跨会话经验 默认保存于 ~/.prime/agent/harness/harness_state.json,需要显式选择 global 写入;另有 refinements.jsonl 记录更新历史。
注入与访问 合并会话级和全局状态后,默认每类最多展示 6 条,每条内容摘要为 180 字符。详情通过 Python API 的 list/get 等接口读取,这条路径不使用向量相似检索。
操作与纠错 支持 create/update/delete/upsert,记录版本、来源和作用域,更新可以回滚。删除当前条目后,历史审计记录仍然保留。

依据:路径与原子保存、摘要选择规则、Python harness API。

4. 运行循环:会话执行与持续运行策略分层

运行时流程图

下图分别展示模型与工具的内循环、负责会话状态的宿主,以及决定是否继续工作的外层策略。rlm() 返回任务接纳句柄,子任务通过消息或文件交付结果。经验更新可以在后台生成提案,再等待合适的执行边界应用;压缩和更新的具体时机会随交互模式与 headless 模式调整。宿主架构、经验更新应用时机

flowchart TB
    PIn["TUI / headless 输入"] --> PSup["Daemon supervisor<br/>路由到 session worker"]
    PSchedule["Heartbeat / schedule / Agent 消息"] --> PSup
    PSup --> PQueue["AgentSession 输入队列"]
    PQueue --> PContext["构建模型上下文<br/>harness 摘要与当前消息"]
    PMem[("Local / global harness JSON")] -. "提示注入与按需读取" .-> PContext
    PContext --> PModel["模型调用"]
    PModel --> PResult{"回复类型"}
    PResult -->|工具调用| PKernel["ipython 顺序执行<br/>持久 Python kernel"]
    PKernel --> PExec["Python 数据处理 / 工具<br/>typed host request"]
    PExec --> PReturn["工具结果进入上下文"]
    PKernel -. "rlm:返回接纳句柄" .-> PChild["独立子 AgentSession"]
    PChild -. "显式消息交付结果" .-> PQueue
    PChild -. "文件交付结果" .-> PExec
    PReturn --> PBoundary["宿主检查点<br/>按需压缩,处理 steering 与预算"]
    PResult -->|文本回复| PBoundary
    PBoundary --> PNext{"还有工具后续或待处理输入?"}
    PNext -->|有| PContext
    PNext -->|无| PPolicy{"Goal / autonomous 策略<br/>是否需要继续?"}
    PPolicy -->|目标未完或 gate 失败且预算允许| PQueue
    PPolicy -->|无需继续或达到限制| PIdle["当前 run 结束或等待输入<br/>UI detach 不等于 worker 停止"]
    PResult -->|错误或取消| PRecovery["分类恢复 / 有界重试<br/>或记录失败、取消状态"]
    PRecovery -->|允许重试| PContext
    PRecovery -->|终止| PIdle
    PBoundary -. "记录压缩与状态" .-> PStore[("Session JSONL 与 artifacts<br/>kernel 尽力快照")]
    PReturn -. "记录工具轨迹" .-> PStore
    PStore -. "恢复同一 session" .-> PQueue
    PBoundary -. "满足自动条件或显式 refine" .-> PReview["Review / refinement 提案<br/>校验、冲突检查、应用与审计"]
    PReview --> PMem

    classDef runtime fill:#e8f1ff,stroke:#5278b8,color:#152a46;
    classDef memory fill:#e8f5eb,stroke:#528763,color:#173e24;
    classDef background fill:#f1eaff,stroke:#8764aa,color:#38204e;
    class PSup,PQueue,PContext,PModel,PKernel,PExec,PReturn,PBoundary runtime;
    class PMem,PStore memory;
    class PSchedule,PChild,PReview background;

底层 runLoop 在内层反复执行模型请求和工具调用,在外层处理后续消息与继续执行的请求。每轮还会检查中断、工具终止信号和宿主的停止策略。通用工具调度支持并行,但 ipython 明确标记为 sequential,以保护共享 Python 内核。需要并行时,可以在 Python 中编排,或使用独立子会话;子任务的答案通过显式消息或文件返回。运行循环、工具模式、ipython 顺序执行

持续运行由三类机制共同控制:goal 保存目标和进度;autonomous mode 根据轮次、token、时间和继续执行次数的预算,以及可选的命令质量检查,决定是否继续;heartbeat 和 schedule 则在未来重新将任务放入队列。达到限制会停止运行,但不会自动证明目标已经完成。终端断开、上下文压缩和进程恢复也分别处理连接、对话和执行状态。长期执行策略

Letta Code

实现定位与版本范围

当前 Letta Code 仓库同时包含交互终端、headless 运行框架、本地运行时、App Server 和消息渠道。旧的 letta-ai/letta 主分支已改为项目入口,V1 服务端停止维护,源码保留在 archive 分支。本文因此以当前 Letta Code 为分析对象,旧 Python 服务端的 core、archival、recall 架构只作为历史背景。L1

未显式指定后端时,Letta Code 默认使用 api,地址为 https://api.letta.com。通过 --backend local 可以切换到进程内的本地运行时,App Server 也支持这种模式。API 模式由云端保存 Agent 身份、会话、消息和记忆仓库,客户端在当前机器执行本地工具;local 模式则将这些状态保存在本机。虽然本地模式的部分环境开关仍带有 experimental 名称,官方已经提供自托管说明。L2

1. 自主学习:编辑记忆,并在后台反思经验

Letta Code 主要通过修改记忆文件、可复用技能和环境配置来积累经验。默认提示要求模型记录用户纠正、偏好和反复出现的错误,并通过 Git 保存变更。用户也可以使用 /remember 明确要求记住信息,或用 /init 初始化项目记忆。哪些内容值得长期保留,仍由模型根据交互判断。L3

后台反思(dreaming/reflection)默认按 step-count 触发:累计 25 步后,在回合结束时检查,合并模式默认为 auto。maybeLaunchPostTurnReflection 会先等待本轮新增对话记录保存,再检查累计步数;也可改为压缩事件触发,或直接关闭。它依赖 MemFS,计数单位并非用户消息条数。若云端返回 cutover=true,自动反思由云端接管,客户端不再重复启动;本次未核查云端调度器的内部实现。L4

反思子 Agent 读取近期对话片段和父 Agent 的记忆快照,在独立 Git 工作树中整理纠正、偏好、事实和重复流程。提示要求它合并重复项、替换过时事实、排除一次性任务状态,必要时最多更新一项技能。生成提交后,由运行框架合并;也可以配置主 Agent 在另一后台会话中先审阅和修订。

只有成功完成并整合结果后,系统才推进反思游标;失败或冲突时,待处理的对话材料仍会留待后续使用。这些检查确认的是反思任务与合并过程是否成功。/doctor 则检查记忆布局、重复内容和提示的 token 占用,本次未发现默认运行独立能力基准、量化奖励或模型权重更新的流程。L5

2. 长上下文:由后端维护窗口,原始历史独立保存

API 模式下,sendMessageStream 只发送本次消息或工具审批结果,以及客户端工具和技能信息;完整对话历史由后端持有。请求会开启压缩事件返回,客户端也提供主动压缩接口和相应的事件处理。开源代码可以说明双方如何协作,但云端具体采用什么压缩算法、预算阈值和数据库实现,仍需要服务端证据。L6

local 模式的上下文管理已开源。它优先根据最近一次模型用量统计计算预算,再估算后续新增消息;没有可信统计时,则根据提示、消息和工具定义估算,文本按字符数除以 4,图片使用固定估值。输出预留量为 min(16384, max(1, floor(window×0.2))),当前用量超过窗口减预留量时提前压缩,模型服务报溢出时也有恢复路径。

默认使用滑动窗口策略,保留预算比例为 0.3,也支持 all 策略。摘要生成后,系统用“摘要和近期消息”更新当前有效消息集合,并向完整历史追加压缩记录,原始内容仍然保留。若压缩失败或压后仍超窗,可以尝试全量摘要;但如果系统提示和工具定义本身就超窗,仅压缩历史无法解决。L7

压缩让任务可以持续推进,但精确细节仍需从原始消息或记忆文件中找回。本地模式主要对完整对话做文本匹配,云端消息搜索接口支持全文、向量和混合检索。搜索结果经过工具读取后,才会进入模型的当前上下文。L8

3. 持久记忆:用 Git MemFS 管理内容与版本

MemFS 将 Agent 的 Git 记忆仓库检出为本地目录。API 模式通常使用 ~/.letta/agents/<agent-id>/memory,本地后端使用其存储根目录下的 memfs/<agent-id>/memory。memory 和 memory_apply_patch 工具修改内容后会自动提交;直接编辑文件则需要显式提交,远端更新在后续同步时完成。

本地提示编译器通过 git ls-tree HEAD 和 git show HEAD:<path> 读取已提交版本,因此未提交的文件修改不会直接进入核心提示。L9

MemFS 目前存在两种目录布局。v1 和 local 模式把 system/*.md 作为核心记忆,其他文件主要以目录索引形式展示,正文按需读取。云端 v2 则通过根目录的 MEMORY.md 识别布局:根目录下的 Markdown 文件属于核心记忆,子目录需要自己的 MEMORY.md 索引,技能单独处理。

当前客户端已包含 v2 的格式检测、读写校验和提示模板,但本次未核查云端提示编译器。官方 MemFS 页面仍主要介绍 v1,涉及目录行为时应以对应版本的代码为准。L10

MemFS 默认按文件组织和查找记忆,不建立向量索引。模型可以通过 Read、Grep 和文件搜索,根据路径、描述或 Markdown 链接读取内容。官方另有 memfs-search 扩展,其可选语义和混合检索依赖 QMD;这与云端对话消息的向量搜索属于不同功能。

当前创建 Agent 时,代码关闭 include_base_tools,默认只挂载服务端 web_search 和 fetch_webpage,本地工具在运行时传入。因此,旧 V1 的 archival memory 向量存储并不是当前 Agent 默认记忆路径。L8、L11

MemFS 按 Agent 复用:同一 Agent 的不同 conversation 共享记忆,但各自维护上下文窗口。本地目录以 Agent ID 区分;共享记忆需要显式附加共享仓库,实际访问范围仍取决于权限配置。技能加载优先级依次是项目技能、Agent 的 MemFS 技能、全局技能和内置技能。发现阶段只提供名称与描述,正文按需加载;Agent 自有技能可以随云端记忆迁移到其他机器。L9、L11

4. 运行循环:客户端执行工具,后端推进会话

运行时流程图

下图展示客户端如何与 API 或 local 后端协作。两种模式共用消息和审批接口,但后端实现不同:图中展开了已核查的本地压缩流程,云端推理与压缩则保留为整体模块。后台反思是否由客户端启动,还取决于云端是否已接管。L4、L6、L7、L12

flowchart TB
    LIn["交互终端 / headless 输入"] --> LSend["sendMessageStream<br/>发送本次消息或 approval 结果"]
    LSend --> LMode{"Backend 模式"}
    LMode -->|默认 API| LCloud["Letta API conversation stream<br/>云端持有会话与窗口"]
    LMode -->|local| LLocal["Local runtime<br/>编译已提交 MemFS 与 active messages"]
    LLocal --> LBudget["检查窗口预算<br/>按需摘要并切换 active message IDs"]
    LBudget --> LModel["Local provider executor<br/>模型与后端工具执行"]
    LCloud --> LEvents["客户端接收后端事件流"]
    LModel --> LEvents
    LEvents --> LKind{"事件 / 停止原因"}
    LKind -->|文本或中间事件| LUI["更新 UI、usage 与 transcript delta"]
    LUI --> LEvents
    LKind -->|requires_approval| LApprove{"客户端权限判定<br/>自动允许 / 用户决定 / 拒绝"}
    LApprove -->|允许| LTools["executeApprovalBatch<br/>只读并发,同资源写入串行"]
    LApprove -->|拒绝| LDeny["构造拒绝结果"]
    LTools --> LSend
    LDeny --> LSend
    LTools -. "memory 工具修改并提交" .-> LMem[("Agent Git MemFS<br/>核心记忆、其它文件、skills")]
    LMem -. "读取 HEAD 的核心内容" .-> LLocal
    LMem -. "API 模式同步已提交变更" .-> LCloud
    LKind -->|正常终止| LDone["完成本轮<br/>追加 transcript delta 与反思计数"]
    LKind -->|错误或取消| LRecovery["共享恢复策略<br/>续接 stream / 重试 / 终止"]
    LRecovery -->|可恢复| LSend
    LRecovery -->|取消或不可恢复| LStop["记录终态并结束"]
    LDone --> LStop
    LDone -. "MemFS 开启且满足触发条件" .-> LOwner{"Cloud 已接管自动反思?"}
    LOwner -->|是| LCloudReview["交由 Cloud 管理<br/>客户端不重复启动"]
    LOwner -->|否| LReview["Reflection 子代理<br/>独立 Git worktree 整理经验"]
    LReview --> LMerge["提交与合并<br/>成功才推进反思游标"]
    LMerge --> LMem

    classDef runtime fill:#e8f1ff,stroke:#5278b8,color:#152a46;
    classDef memory fill:#e8f5eb,stroke:#528763,color:#173e24;
    classDef background fill:#f1eaff,stroke:#8764aa,color:#38204e;
    class LSend,LCloud,LLocal,LBudget,LModel,LEvents,LTools,LDone runtime;
    class LMem memory;
    class LCloudReview,LReview,LMerge background;

交互模式从 use-conversation-loop.processConversation 进入,headless 模式则使用自己的迭代循环。两者都通过 sendMessageStream 请求后端,再持续接收文本、工具、审批和停止事件。API 后端可以自行执行服务端工具并继续推理;遇到本地工具时,返回 requires_approval,由客户端判定自动允许、拒绝或等待用户决定。允许执行后,executeApprovalBatch 调用工具管理器,并将结果作为下一次请求发回后端。

当前云端的内部多步调度只能从协议观察;本地后端的模型执行器则与客户端代码位于同一仓库,可以直接审阅。L6、L12

本地工具按资源安排并发。可并发的只读工具和 Task 可以同时执行;写操作按目标资源分组,同一资源内依次执行,不同资源之间可以并行。结果最终按原始调用顺序返回。executeApprovalBatch

运行循环分别处理正常结束、取消、错误和 max_steps 限制。headless 模式会避免在回传工具审批结果前因步数上限直接退出,以免后端一直等待结果。SDK 默认关闭自动重试,恢复由外层统一控制:429、5xx 和网络故障在预算内延迟重试,繁忙状态尝试续接已有流,审批 ID 不匹配时重新读取后端状态;鉴权或额度错误则按对应原因结束。

子 Agent 通过独立 headless 进程运行,可以新建上下文、继承父上下文,或调用已有 Agent。反思任务是其中一种受限于记忆范围的专用子 Agent。独立上下文提供了单独的推理预算,但工作目录是否隔离需要另看配置。L12

从实现上看,Letta Code 的特点是把长期身份、可提交的记忆、后台反思和按需读取组织在一起。经验因此能够跨会话保留并再次使用;实际收益则取决于记忆质量、检索命中率和具体任务表现。

源码导航

L1 当前与历史版本:Letta 当前仓库说明。

L2 后端默认配置与部署:后端选择逻辑、默认设置、官方自托管说明。

L3 经验记录与触发:MemFS 主提示、官方记忆与反思说明。

L4 反思开关与触发:回合结束后的反思入口、云端接管处理;默认值见 L2。

L5 反思、写入与结果整合:reflection-v2 提示、工作树结果整合、成功后的进度更新。

L6 API 消息接口:请求构造与 SDK 重试设置、后端代理接口、官方压缩接口。

L7 本地上下文压缩:预算与触发阈值、默认策略、摘要应用与历史追加、失败恢复策略。

L8 检索方式与范围:官方 MemFS 检索说明、云端消息搜索接口、本地历史搜索。

L9 持久化与已提交内容加载:记忆工具自动提交、本地编译器读取已提交内容、记忆路径与作用域。

L10 MemFS 两代布局:检测规则、本地核心记忆编译。

L11 默认工具与技能:创建工具集、关闭默认基础工具集、技能来源优先级。

L12 运行循环、恢复与子 Agent:交互循环、headless 工具审批、执行与回传、步数限制与审批回传顺序、重试分类、子 Agent 启动。

OpenClaw

1. 自主学习:分别巩固长期记忆与维护技能

OpenClaw 当前有两条默认开启的自动学习路径。第一条是 memory-core 的 Dreaming,默认每天 03:00 由托管定时任务运行。它依次经过 light、REM 和 deep 三个阶段,完成候选内容去重、主题反思和长期记忆巩固。

进入长期记忆前,候选内容必须同时达到评分、召回次数和不同查询数量的门槛。不可信来源和系统来源会被排除,从会话提取的候选也只接受交互会话。模型在这些规则内选择新增、合并或替换内容,系统随后检查来源、旧条目保留比例和提示容量。改写前保留原内容并检查哈希,失败时回退到追加方式。DREAMS.md 记录可供人工审阅的结果,不再被当作新的学习材料。O1O2

第二条是 Skill Workshop,负责从任务经验中维护技能。skills.workshop.autonomous.mode 和 approvalPolicy 默认均为 auto,包括使用过程中的技能修复、任务结束后的后台经验复盘,以及每周的技能集合整理。

后台经验复盘有明确条件:单轮至少经历 10 次模型迭代,前台任务已完成或被中断,但没有模型服务或提示错误;运行时还必须报告所用模型,并确认 skill_workshop 可用。之后要等待至少 30 秒空闲,且系统没有活动 Agent。定时任务、心跳、记忆维护、溢出恢复、钩子、子任务和复盘任务不会再次触发这条路径,已经发生压缩的回合也被排除。

复盘只读取截至本轮结束位置的材料,最多产生一次技能变更,且只能修改当前 Agent 的 workshop-skills。变更依次经过提案生成、哈希绑定、扫描和应用,也可能保留为待处理或隔离状态。新会话会使用更新后的技能,正在运行的会话继续使用已有快照。将模式改为 propose 时只生成提案,改为 off 则关闭自动捕获。O3

这两条路径分别更新事实记忆和程序性技能。压缩前的 memory flush 只负责把尚未保存的内容写入日记,后续整理交给 Dreaming;heartbeat 和 cron 负责唤醒工作,默认心跳本身不维护记忆。Workshop 也提供评估插件接口,但没有内置一套持续执行“评估、反复修订、判断何时停止”的通用优化控制器。O4

2. 长上下文:裁减工具结果、压缩对话、提前保存记忆

Pruning 用于裁减旧工具结果。 它不概括普通对话,也不改写原始结果,而是维护一份供模型读取的精简视图。当前版本会通过隐藏的 openclaw.cache-ttl 标记保存这份视图,使其能够在 Gateway 重启后恢复。

非 Anthropic 路径默认关闭 pruning,Anthropic 路径则可能根据认证方式采用预设配置。直接使用 Anthropic API key 时,旧工具结果由服务端清理;其他符合条件的路径在缓存 TTL 到期后进行本地裁减:上下文占用约 30% 时缩短旧结果,达到约 50% 且可清理内容足够时进一步清空。最近 3 轮和初始用户消息之前的内容受到保护。O5

Compaction 用于压缩对话。 它默认开启,在接近窗口预算或模型服务报告溢出时生成旧对话摘要,保留近期消息,并维护工具调用与结果的配对。新配置默认使用 safeguard 模式,会检查摘要质量并允许有限次数的修正,未通过检查的摘要不会写入。

Memory flush 在压缩前保存值得保留的信息。 压缩阈值以窗口减预留量计算,flush 再提前一个 softThreshold 触发。系统优先使用最新 token 统计,必要时读取历史估算。默认 flush 要求工作区可写,只向 memory/YYYY-MM-DD.md 追加内容,不修改 MEMORY.md、DREAMS.md、SOUL.md 和 AGENTS.md;没有内容需要保存时可以返回 NO_REPLY。O6O7

这些步骤失败时,系统优先保留已有状态。flush 重试耗尽不会重置会话,必要压缩失败则保留原历史并返回错误。摘要模型未被显式指定时,可以尝试配置中的备用模型;取消和摘要质量检查失败不会触发模型切换。溢出压缩成功后可以重试原请求,并清理流缓冲以避免重复输出。用户停止任务后,后续恢复与重试也会停止,但已完成的压缩不会回滚。

上述细节对应内置运行时,原生 Codex 等其他运行时使用各自的压缩策略。子 Agent 通常有独立的上下文和 token 预算,也支持通过 context: fork 显式继承父历史。O7O11

3. 持久记忆:Markdown 保存内容,SQLite 支持检索与恢复

memory-core 默认索引 MEMORY.md、已有的 USER.md 和 memory/*.md。长期事实放在 MEMORY.md,用户偏好和指令放在 USER.md,日记保留详细过程,DREAMS.md 用于审阅整理结果。用户可以直接读写这些文件;SQLite 则保存文本分块、向量、全文索引、来源信息和运行状态。

每个 Agent 的主数据库位于 ~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite,会话及完整对话记录也已迁入其中。JSONL 和 sessions.json 主要用于旧数据迁移或归档,不再是当前运行时默认持续写入的存储。O8

内置检索结合 FTS5/BM25 关键词搜索和向量搜索。默认按 400 tokens 分块,相邻块重叠 80 tokens,文件变更后会合并短时间内的更新再重建索引。结果综合相关性、时间和重要性排序,最后通过 MMR 减少重复内容;这里没有使用学习式重排模型。

默认向量服务为 OpenAI,有可用凭证时才启用,否则使用关键词搜索。也可配置 Gemini、Voyage、Mistral、Ollama 等服务;运行本地 GGUF 模型需要官方 llama.cpp 提供程序,sqlite-vec 则用于可选加速。O8

本次版本已移除内置 QMD 后端,doctor 会迁移旧配置,同时保留附加路径和原始记忆。当前内置引擎不包含原 QMD 的 HyDE 和交叉编码器重排能力。外部记忆插件仍可使用:官方资料列出了 Honcho 和需要另行安装的 memory-lancedb,后者通过 plugins.slots.memory 选择。memory-wiki 则是补充知识层,与替换 memory-core 的插件用途不同。O9

记忆从工作日记、flush 写入内容和合格的交互历史开始,先建立带来源的索引,再由 Dreaming 整理为长期记忆,最后在预算内加入初始提示并逐轮刷新。系统还可以按触发短语进行词法或向量匹配,最多补入 3 条可信记忆。

Active Memory 默认采用 escalate 策略:当用户明确要求回忆,而常规检索没有强匹配时,再启动检索子 Agent,等待结果后继续。跨会话记忆在个人安装中默认开启,配置私聊隔离后默认关闭;检索范围限于同一 Agent 已识别的私聊,不包含群聊、其他 Agent 或元数据不足的会话,也不会扩大 sessions_* 工具的权限。虽然 sources 默认只有 memory,开启 rememberAcrossConversations 后仍会加入 sessions。O10

4. 运行循环:队列管理会话,运行时执行任务

运行时流程图

下图从 Gateway 托管会话的入口展开自有运行时,其他运行框架在对应模块内执行。上下文准备节点汇总了模型请求前和错误恢复时的检查,具体是否裁减、保存记忆或压缩,取决于当时的条件。Dreaming 与 Workshop 单独在后台运行。O1、O3、O5、O6、O11、O12

flowchart TB
    OIn["用户消息 / Gateway agent RPC"] --> OGateway["Gateway:校验与 session 解析<br/>接纳请求并返回 runId"]
    OGateway --> OQueue["Session lane → Global lane<br/>同 session 串行,全局并发受限"]
    OSchedule["调度器:Cron / Heartbeat 输入"] --> OQueue
    OQueue --> ORuntime{"选择 model runtime / harness"}
    ORuntime -->|自有 runtime| OPrepare["准备 session 与上下文<br/>按条件 pruning / flush / compaction"]
    ORuntime -->|其它 harness| OOther["对应运行时执行<br/>使用自身工具与压缩策略"]
    OMem[("Markdown 记忆与技能<br/>SQLite 索引、来源与运行状态")] -. "预算内注入或按需检索" .-> OPrepare
    OPrepare -. "flush:先追加工作日记" .-> OMem
    OPrepare --> OModel["agent-core 模型调用"]
    OModel --> OResult{"模型结果"}
    OResult -->|工具调用| OTools["工具批次执行<br/>默认可并发,遵守 sequential 标记"]
    OTools --> OPrepare
    OTools -. "创建子任务" .-> OChild["后台子 Agent session<br/>独立上下文或显式 fork"]
    OChild -. "完成后幂等 handoff" .-> OHandoff["父 run 活跃时尝试 steer<br/>否则进入父 session lane"]
    OHandoff --> OQueue
    OResult -->|文本完成| OPending{"仍有 steering / follow-up?"}
    OPending -->|有| OPrepare
    OPending -->|无| OEnd["发布终态<br/>结束本次 run"]
    OOther --> OEnd
    OResult -->|错误 / 溢出 / 取消| ORecovery["分类恢复<br/>有界压缩、重试或失败"]
    ORecovery -->|允许重试| OPrepare
    ORecovery -->|失败或取消| OEnd
    OModel -. "流事件" .-> OStore[("SQLite session / transcript<br/>writer fence 防止过期写入")]
    OTools -. "工具事件" .-> OStore
    OEnd -. "记录终态" .-> OStore
    OEnd -. "合格长回合结束后静默 30 秒" .-> OWorkshop["Workshop experience review<br/>提案、hash 校验、扫描与应用"]
    OWorkshop --> OMem
    ODreamTick["Dreaming 托管 Cron<br/>默认每日 03:00"] --> ODream["Light → REM → Deep<br/>候选去重、反思、门槛校验与巩固"]
    OStore -. "仅合格 interactive 轨迹" .-> ODream
    OMem -. "记忆候选与召回信号" .-> ODream
    ODream --> OMem

    classDef runtime fill:#e8f1ff,stroke:#5278b8,color:#152a46;
    classDef memory fill:#e8f5eb,stroke:#528763,color:#173e24;
    classDef background fill:#f1eaff,stroke:#8764aa,color:#38204e;
    class OGateway,OQueue,OPrepare,OModel,OTools,OOther,OEnd runtime;
    class OMem,OStore memory;
    class OSchedule,OChild,OHandoff,OWorkshop,ODreamTick,ODream background;

Gateway 收到 Agent RPC 后,先校验请求、解析会话并返回 runId,随后通过 agentCommand 和 runEmbeddedAgent 安排执行。任务先进入会话队列,再进入全局队列,然后选择模型运行时,准备会话和提示,推进模型与工具循环,并持续发送事件和保存状态。

run-orchestrator 中的 enqueueSession 包裹 enqueueGlobal,符合条件的 CLI 路径也在入队后分发。同一会话依次执行,不同会话可以并发;SQLite 通过 activeWriterRunId 检查当前写入者,防止已被替代的运行实例写入过期对话。O11

当前执行内核位于项目自己的 packages/agent-core 和 @openclaw/ai。部分代码改编自 Pi/pi-mono,终端界面仍使用 pi-tui,但运行循环已经由项目自身维护。此外,系统还支持 Codex、Copilot 等嵌入式运行框架和独立 CLI 后端。模型服务、具体模型与执行运行时属于不同配置层。

内核的工具执行默认允许并发;显式设置 sequential,或批次中某个工具要求顺序执行时,该批次会串行处理。因此,会话队列的顺序执行与会话内部的工具并发是两层机制。O12

当没有待处理的工具调用、运行中追加指令或后续消息时,循环结束;错误、中断和预算超时也可以终止运行。agent.wait 超时只表示调用方停止等待,后台任务仍可能继续。输入队列支持运行中追加、回合后跟进、合并收集和中断等模式,当前默认是 steer。

子 Agent 使用独立会话在后台运行,完成后通过带幂等标识的交接流程向父任务投递结果:父任务仍在运行时先尝试追加消息,否则进入父会话队列。计算完成与投递成功分别记录,投递重试有次数上限。定时任务的独立回合则由调度器管理预算和清理。O11O12

源码导航

以下链接均固定到本次核查的提交。官方资料出现分歧时,本文采用更具体的实现或专题说明,并在下一节注明差异。

O1 Dreaming 默认开关与执行时间;三阶段及巩固验证。

O2 候选来源与交互会话过滤;托管定时任务实现。

O3 Workshop 默认自动模式;复盘阈值与触发条件;完整学习流程。

O4 外部评估与优化接口;默认心跳与记忆维护的分工。

O5 工具结果裁减、精简视图保存与触发阈值。

O6 压缩前记忆保存的目标与规则;默认启用与预算;提前触发阈值与过期用量处理。

O7 对话压缩、摘要检查与失败恢复。

O8 内置检索与 SQLite 索引;SQLite 会话存储与旧日志迁移。

O9 QMD 移除后的能力变化;外部 LanceDB 插件。

O10 记忆来源分级与检索路径;跨会话默认与隔离;检索来源与权限范围。

O11 入队与运行时准备;RPC 到运行循环及写入者检查;子 Agent 隔离、上下文继承与异步交付。

O12 自有内核循环及终止;工具串并行决策;默认并发配置;Pi 代码来源说明;队列。

官方文档冲突与核查边界

  1. 本次核查确认了写入流程、来源过滤和哈希校验等机制,尚未测试它们对记忆准确率和任务表现的实际影响。
  2. 关于每周技能集合整理,同一版本的两份文档描述不同。self-learning 说明提到整体备份和自动回滚,Workshop 恢复说明则说明新流程采用普通 Agent 文件编辑方式,不提供集合级事务,也不再创建整体备份。本文采用后者;单个技能提案保存的回滚元数据属于另一套机制。
  3. 关于工具结果裁减,compaction.md 的对照表仍写作“仅在内存中生效”,但 pruning 专页说明精简视图可以持久保存。本文据此区分两层内容:原始工具结果保持不变,供模型读取的视图可以在重启后恢复。
  4. 文档用“无隐藏状态”强调记忆内容可直接读取;实现上,SQLite 仍会保存来源、索引和 Dreaming 的运行状态。

横向比较与实现参考

如果希望借鉴这些项目,可以先根据要解决的问题选择阅读入口。下面的建议基于实现特点,效果仍需结合自己的任务和部署条件验证。

希望解决的问题 值得先读的实现 原因与边界
保存个人偏好、环境事实和可复用步骤 Hermes 的 MemoryStore、后台复盘和技能工具 文件结构简单、容量明确,适合梳理从经验整理到再次使用的完整过程;更大的知识库需要结合技能、历史或外部记忆服务。
处理大量材料,并用代码组织多个 Agent Prime 的 REPL、宿主接口、runLoop 和 AgentSession 可以分别观察工作数据、子会话与调度状态如何管理,重点留意变量恢复、预算和异步结果交付。
维护跨会话身份,并对记忆进行版本管理 Letta 的 MemFS、反思工作树和本地提示编译器 能追踪记忆修改、Git 提交和提示加载过程;阅读时需要确认后端模式与 MemFS 版本。
构建长期在线、支持多个消息入口的助理 OpenClaw 的 memory-core、Dreaming、Workshop 和会话队列 可参考来源过滤、分阶段整理和异步投递机制;需要同时掌握所用运行时、插件和相关配置。

从实现机制到实际学习效果

环节 已看到的代表实现 仍需验证的效果
提取经验 Hermes 后台复盘、Prime 经验更新、Letta 反思、OpenClaw 记忆与技能整理。 能否识别稳定规律和用户纠正,避免把偶然成功或已经召回的内容误当作新知识。
控制写入 文件容量限制、技能保护、字段校验、版本冲突检查、Git 合并,以及来源和安全扫描。 除了成功保存,内容是否正确,遇到反例后能否及时修正。
后续复用 常驻短记忆、框架状态摘要、MemFS 核心内容与目录索引,以及混合检索。 需要时能否找到,不相关时是否造成干扰,知识规模增长后是否仍然有效。
效果反馈 用户纠正、后续任务结果、回滚和可配置的质量检查、评估接口。 是否能通过独立任务集比较更新前后的表现,再据此决定保留或撤销经验。

后续可以怎样验证

可以从以下五类任务开始验证。它们分别检查记忆更新、经验复用、上下文恢复、进程恢复和隔离行为,本次尚未执行。

场景 测试方式 记录指标
偏好与事实更新 在 A 会话提供事实,在 B 会话要求使用;再明确修改该事实,在 C 会话检查是否采用新版本。分别测试 Prime 的会话级与全局范围,以及 Letta 的同一 Agent 与不同 Agent。 写入位置、版本、检索来源、新事实采用率和旧事实残留情况。
程序性学习 先完成一次需要纠错的任务,再给出同类但参数不同的任务;使用相同初始状态,对比启用和关闭复盘时的表现。 技能是否生成并被调用、错误是否重复、成功率、token 用量和耗时。
压缩后恢复精确信息 在早期对话中提供精确 ID、失败原因和禁止操作,触发多次压缩后继续任务。 摘要保留程度、历史补检成功率,以及未检索就猜测的比例。
跨进程恢复 分别关闭界面、重启执行进程或 Gateway,再恢复会话,检查目标、工具状态、子任务和保存的数据。 状态丢失、操作重复执行,以及子任务结果丢失或重复投递。
记忆纠错与隔离 先写入错误结论并保留来源,再明确纠正;检查私聊、群聊、不同 Agent 或 profile,以及删除后的可见性。 当前记忆与原始历史是否分别处理,访问范围是否符合配置。

阅读旧资料时需要注意的版本变化

  • Letta:旧 V1 服务端已归档。当前以 Letta Code 的 API 与本地后端为准,MemFS 的默认路径应与旧版 archival/recall 架构分开理解。当前仓库说明
  • OpenClaw:当前版本已加入默认 Dreaming 和自动 Workshop,移除内置 QMD,并使用自有执行内核和 SQLite 会话存储。相关实现见 O1–O12。
  • Hermes:压缩阈值随模型窗口调整,记忆快照会在压缩后重新加载,搜索结果也有返回长度限制。相关实现见 H5、H9、H10。
  • Prime:自动经验更新只对满足条件的根会话启用,默认保存在当前会话;REPL 恢复还受序列化能力和快照大小限制。相关实现见 Prime Agent。

本文将可从源码或官方说明确认的机制,与基于这些机制作出的工程判断分开记录。后续若要比较四个项目的实际表现,应在固定模型、任务集和初始记忆的条件下测试,并保留检索与更新过程,才能解释效果差异。

本文作者: Uyouii
文章链接: https://uyouii.cool/posts/3f0ed6b/
版权声明: 本博客文章除特别声明外, 均采用署名4.0国际(CC BY 4.0)国际许可协议进行授权, 转载请注明出处


开源 Agents 调研
https://uyouii.cool/posts/3f0ed6b/
作者
Uyouii
发布于
2026年9月6日上午11点27分
许可协议