Agent 架构文档 · Markdown
上下文工程在 10 家 Agent 框架的深度对比
版本:2026 04 25 配套:本文是 5 个主题对比之一,专讲 System prompt 组装、context window 管理、压缩、prompt cache、按需召回、工具结果压缩、多 turn 稳定性、checkpoint 持久化 ;长期记忆架构(PG/Milvus/Neo4j/向量库/用户画像)属于另一篇《记忆系统》主题,本文只在交集处指明边
版本:2026-04-25 配套:本文是 5 个主题对比之一,专讲 System prompt 组装、context window 管理、压缩、prompt cache、按需召回、工具结果压缩、多 turn 稳定性、checkpoint 持久化;长期记忆架构(PG/Milvus/Neo4j/向量库/用户画像)属于另一篇《记忆系统》主题,本文只在交集处指明边界。
#目录
- 零、为什么单独写"上下文工程"
- 一、10 家速览大表
- 二、System prompt 组装的 8 种哲学
- 三、上下文压缩的 5 种算法对照
- 四、Prompt cache 完整性的取舍光谱
- 五、按需召回机制对照
- 六、工具结果压缩对照
- 七、长会话稳定性 / state 持久化对照
- 八、最值得抄走的 5 个设计创新
- 九、趋势观察 + 一句话各家总结
- 附:源文档章节对照
#零、为什么单独写"上下文工程"
LLM 调用唯一的输入是一段 token 序列。Agent 框架的全部"工程"都是在决定这段序列长什么样:
- 每轮 system prompt 拼几段、按什么顺序
- context window 接近上限时是丢、是压、还是分叉
- 哪些段必须保住才能命中 prompt cache
- 哪些资料是"启动就在",哪些是"用到才查"
- tool 输出是原文塞回,还是落盘只塞 path
- 长会话怎么不让 system prompt 自己漂移
这 7 件事合起来叫"上下文工程"。它不是记忆系统(那是"长期记什么"),也不是工具系统(那是"能干什么"),而是每一轮真正喂给 LLM 的那段 token 是怎么生成的。十家答案差异巨大,从"写死禁止改"(Hermes)到"四档动态召回"(Cursor),跨度比记忆系统还大——值得专门写一篇。
#一、10 家速览大表
一行装得下一家的"上下文取向"——剩下的章节都是这张表的展开。
| 项目 | 默认模型 ctx | 压缩策略 | Cache 哲学 | 召回方式 | System prompt 段数 | session 持久化 |
|---|---|---|---|---|---|---|
| OpenClaw | 200K(取决 model) | command:new/reset 触发 session-memory flush → session:compact:before/after 包住模型驱动 compact |
取决 model provider(仓库无内置"prompt cache 压缩点对齐") | Active Memory 子代理 + memory_search 工具 | SOUL + AGENTS + TOOLS + IDENTITY + MEMORY + active_memory_plugin(6 段) | session.jsonl append-only |
| Hermes | 模型自选(4 系最高 256K) | ContextCompressor v2,token-budget tail + Iterative summary | 写死禁止 mid-conversation 改 prompt / tools / memory | memory_manager.prefetch() 预取 + Honcho 注入 |
Personality + MEMORY + SKILL + ctx files + tool guidance + tools + model-specific(7 段) | SQLite + FTS5 + session lineage |
| Claude Code | 200K / 1M(按模型) | auto-compact 三阶(drop tool out → summarize → 报错) | 压缩后 project root CLAUDE.md re-inject,skill 按 25K 预算 re-attach | CLAUDE.md 沿目录树 + auto memory + skill description always-on | system + CLAUDE.md 链 + MEMORY.md + skill desc + subagent memory(5 层) | session JSONL + agent-memory/ |
| OpenAI Codex | 取决于 gpt-5-codex | /compact 显式 + Responses API server-side encrypted_content |
encrypted_content 由 OpenAI 后端管,CLI 持引用 | AGENTS.md 多层级合并 + /init 骨架,无自动 memory |
system + product + merged AGENTS.md(嵌套)+ profile + subagent dev_instructions(5 段) | 本地 SQLite + codex resume / fork / /side |
| Cursor | 长 ctx MoE(Composer) | 官方未公开(待核实) | 官方未公开(待核实) | 4 档触发:Always / Auto-Attached / Agent-Requested / Manual | mode prompt + rules(按召回)+ Memories + AGENTS.md + @ 引用展开 | 服务端 chat + Codebase Index Merkle |
| Cline | 200K(一般) | /smol(同 task 自压缩)+ /newtask(切 task) |
不主动管理 | @file/@folder/@problems/@terminal/@git/@url 六种 @ 引用,token 暴力 |
内置 prompt + .clinerules 合并 + 文件树 + mode 标记(4 段) | ~/.cline/data/taskHistory.json + 影子 git checkpoint |
| OpenHands | 取决于 model | Condenser 协议:NoOp / Recent / LLMSummarizing / ObservationMasking / AmortizedForgetting / Rolling | 摘要本身也 emit 成 SummaryEvent | Microagents triggers 关键词触发 + RecallAction → RecallObservation | agent prompt + repo.md(永久) + microagent 触发注入 | EventStream(确定性可重放) |
| AutoGen | 取决于 model | ChatCompletionContext 4 种策略:Unbounded / Buffered(N) / HeadAndTail / TokenLimited |
用户自决 | Memory protocol → update_context push |
system_message + Memory.update_context 注入(2 段) | team.save_state() / load_state() |
| LangGraph | 取决于 model | pre_model_hook + trim_messages(用户写) |
用户自决,可 reducer 控 | Store API(namespace tuple)+ ToolNode 注入 | 完全用户决定,没框架级"system 段"概念 | Pregel Checkpointer(Memory/SQLite/Postgres/Redis) |
两个抽象坐标:
- 横轴:System prompt 是动态还是静态? 左边是 Hermes(写死禁止改)、AutoGen / LangGraph(用户决定);右边是 Cursor(4 档动态召回)、Claude Code(auto-compact 后 re-inject)、OpenHands(Microagent 触发性注入)。
- 纵轴:Compaction 是框架默认还是用户责任? 顶端是 OpenHands(一等公民 Condenser)、Claude Code(auto-compact)、Codex(server-side encrypted_content);底端是 LangGraph / AutoGen(用户自己写 trim node)。
#二、System prompt 组装的 8 种哲学
"system prompt 是 agent 的身份证。怎么拼出来这张证,决定了 agent 是谁。"
#2.1 八种拼装模式
① 数据库 driven ② 文件目录 driven
apc_skill_dir_list 从 S3 拉 + 工具 schema 注入 SOUL + AGENTS + TOOLS + IDENTITY 4 个 md 拼
③ "三件套写死" ④ "工程文件沿目录树"
Hermes Claude Code
Personality + MEMORY + SKILL + ctx + tools CLAUDE.md 沿 cwd 向上递归 +
prompt_builder.py 一次性渲染 auto memory MEMORY.md + skill description
⑤ "四层级合并" ⑥ "模式 + Rules + 召回"
Codex Cursor
~/.codex/AGENTS.override.md → ~/.codex/AGENTS.md mode prompt + rules(4 档触发)+
→ <git_root>/AGENTS.md → <cwd>/AGENTS.md Memories + AGENTS.md + @ 引用
⑦ "目录拼起来" ⑧ "完全交给用户"
Cline AutoGen / LangGraph
.clinerules/*.md 合并 + 内置 prompt + system_message 自由字段,
文件树 + plan/act mode 标记 没有"框架级 system 段"约定
#2.2 几个跨家共识
- AGENTS.md 已成事实标准:Codex / Cursor / OpenClaw 原生识别这个文件名;OpenClaw 兼容
CLAUDE.md软链。Claude Code 自己用CLAUDE.md,官方建议在 CLAUDE.md 里写@AGENTS.md引入(不直接读取)。Cline 用.clinerules/目录(同一逻辑、不同命名)。这是 2025-2026 行业最重要的一次开放胜利。 - 嵌套合并 = developer-native:Codex 是嵌套层级最严密的(
~/.codex/AGENTS.override.md→~/.codex/AGENTS.md→ 沿 git root 一路向 cwd 走),上限 32 KiB(project_doc_max_bytes,见codex-agent-architecture.md §1.4 / §5.2)。Claude Code 用 4 个 scope(managed > project > user > local)+ 沿 cwd 向上递归(见claude-code-agent-architecture.md §5.2)。 - "frontmatter 是 schema 的最后一站":Cursor
.mdc、Claude Code subagent.md、OpenHands microagent、Hermes SKILL.md,全部约定 YAML frontmatter 表达 metadata(name / description / triggers / globs / tools),主体走 markdown。这是行业里少见的"自然形成 schema"。
#2.3 最复杂的一份:Hermes prompt_builder
按 hermes-agent-architecture.md §1.4 的明确顺序:
[1] Personality(今天扮谁,~/.hermes/personalities/<name>.md)
[2] MEMORY.md ← agent 长期记忆摘要
[3] 已加载的 SKILL.md ← 程序性记忆
[4] 上下文文件 / context files
[5] Tool-use guidance(针对当前模型)
[6] <tools>...</tools>(function schema)
[7] Model-specific instructions(Hermes 4 → 是否启用 <think>)
7 段都进 system prompt,且整个会话内不变——这是 Hermes 把 prompt cache 完整性当成顶级硬约束的直接结果(见第四章)。
#2.4 最少的一份:AutoGen / LangGraph
AutoGen 的 AssistantAgent 只有一个 system_message: str 字段;LangGraph 没有"system 段"的概念,用户自己在 node 函数里拼 messages。框架不替你拼。这是"开放协议派"的写法——好处是想干啥都行,代价是新人写 agent 要从零搭框架。
#三、上下文压缩的 5 种算法对照
"context window 一定会爆——区别只在框架是把它当默认问题,还是当 plugin 问题。"
#3.1 五种主流算法
- 触发:messages.token_count() > 150K
- 步骤:fold_messages 把早期 N 轮合并成 [FOLD] 占位 → LLM summarize → Message.system 替代
- 关键:折叠点对齐 prompt cache point(见 4.1)
② ContextCompressor v2(Hermes)
- 触发:token usage 比例 + structured budget 联合判断(v0.2 的固定 50% 阈值已废弃)
- 步骤:tail 保护按 token-budget(非固定条数)→ 中段 LLM summarize → 替换;旧摘要不被新摘要覆盖
(Iterative summary 跨多次 compaction 累加)
- 关键参数:SUMMARY_RATIO=0.20、_MIN_SUMMARY_TOKENS=2000、_SUMMARY_TOKENS_CEILING=12000
- 关键:只压不归档(原文在 SQLite + FTS5 随时检索);summary 模板显式区分
Resolved / Pending / Remaining Work,并带 preamble 防止被 LLM 误读成系统指令
- 出处:hermes-agent-architecture.md §5.2
③ Auto-compact 三阶(Claude Code)
- Step 1: 清掉旧 tool outputs(尤其大 file reads)
- Step 2: 总结对话,保留你的请求 + 关键代码 + 每个已 invoke skill 前 5K(总 25K 预算)
- Step 3: 报错 thrashing,停下来等用户介入
- 关键:project root CLAUDE.md re-inject;skill 按预算 re-attach;嵌套 CLAUDE.md 不 re-inject
- 出处:claude-code-agent-architecture.md §5.4
④ Server-side encrypted_content(Codex)
- 触发:用户显式 `/compact`
- 步骤:当前可见对话 → 替换成 type=compaction 的 input item,里面是 encrypted_content
- 关键:server-side stateful,CLI 只持有引用;保留模型潜在理解状态而非简单总结
- 代价:不能导出/迁移到别家 provider
- 出处:codex-agent-architecture.md §5.4
⑤ Condenser 协议(OpenHands)
- 这是一个抽象基类,不是单一算法
- 实现:NoOp / RecentEvents / LLMSummarizing(前 K + 摘要 + 后 M)/ ObservationMasking
/ AmortizedForgetting / Rolling
- 关键:摘要本身 emit 成 SummaryEvent,进 EventStream,能审计能回放
- 实测:长 session cost 从二次方增长变线性增长
- 出处:openhands-agent-architecture.md §5.3 + §8.5
#3.2 三种"用户自管"派
OpenClaw:bundled hook `session-memory` 在 compact 之前 flush,把要长期记的事写到
`MEMORY.md` / `memory/YYYY-MM-DD-HHMM-<slug>.md`(slug 由 LLM 现场生成),
再让 `session:compact:before` → 模型驱动 compact → `session:compact:after` 跑完。
当前 flush 挂在 `command:new` / `command:reset`(用户主动 `/new` 或 `/reset` 时触发),
外加 `session.idle` / `session.maxAge` 兜底——无固定 daily 时间。
→ 关键创新:"压缩前先抢救一次"——issue #56072 daily reset 丢上下文事故的修复。
出处:openclaw-agent-architecture.md §5.2-5.4
Cline:双路径 ——
/smol:同 task 内 LLM 自压缩(180K → 10K summary + 20K 最近原文)
/newtask:阶段切换,把 plan + 已完成 + 关键文件 + 下一步 打包成新 task 的初始 user message
出处:cline-agent-architecture.md §5.4
AutoGen:ChatCompletionContext 4 种策略组件 ——
UnboundedChatCompletionContext / BufferedChatCompletionContext(buffer_size=N)
/ HeadAndTailChatCompletionContext(head=k, tail=m) / TokenLimitedChatCompletionContext
出处:autogen-agent-architecture.md §5.1
LangGraph:pre_model_hook + langchain_core.messages.utils.trim_messages,全部用户在 node 里写
出处:langgraph-agent-architecture.md §5.1
Cursor:官方未公开长会话 summarization / pruning 机制(待核实)。社区可观测现象是
"对话拉长后老 ctx 会被有损压缩",但具体阈值和算法未披露。
出处:cursor-agent-architecture.md §5.4 标注官方未披露
#3.3 "保前 K + 保后 N + LLM 总结中段" 是公约数
不论哪家,凡是做了主动压缩的,公式高度相似:
keep_first_n (系统消息 + 最初任务描述,开场上下文丢不得)
+
LLM(summarize(middle)) (中段交给便宜模型生成摘要)
+
keep_last_n (最近 N 条 / 最后 ≥20 条,必须完整)
具体参数:
| 项目 | keep_first | keep_last | summarize 模型 |
|---|---|---|---|
| Hermes(v2) | token-budget(非固定条数) | token-budget tail | 辅助模型(用户配) |
| OpenHands LLMSummarizingCondenser | k 轮(系统 + 初始 user) | M 条(最近详细历史) | LLM client |
| Claude Code | 隐式(CLAUDE.md re-inject + 用户请求) | 隐式(最近一段 + 已 invoke skill 前 5K) | Anthropic 内部 |
唯一不走这套的是 Codex 的 encrypted_content——那不是"保 K 段 + 摘要",而是把模型的 KV 状态以加密形式存在 OpenAI 后端,本质上是模型 server 的能力,不是 framework 的能力。
#四、Prompt cache 完整性的取舍光谱
"你想用 prompt cache,那 cache invalidation 就成了头等事——这件事每家答案都不一样。"
#4.1 光谱:从"写死禁止"到"动态注入"
最严格(cache 完整性 = 顶级约束) 最自由(cache 让位于动态性)
←──────────────────────────────────────────────────────────────────────────→
AGENTS.md 写死 压缩点固定在 auto-compact 后 摘要也是 event Memories + 4 档 rules
"do NOT alter past turn 边界 + project CLAUDE.md push 到 stream, 动态召回不同 rules
context cache point re-inject, microagent 触发 每次 prompt 不一样
mid-conversation" 设在压缩点之后 skill 按 25K 会破坏 cache cache hit 率较低
re-attach (见 §4.6) 但灵活度最高
#4.2 Hermes 的"硬约束"(业内最严,值得抄)
AGENTS.md 里有一条原文(见 hermes-agent-architecture.md §1.4 / §8.6):
"Do NOT implement changes that would alter past context mid-conversation, change toolsets mid-conversation, [or] reload memories or rebuild system prompts mid-conversation."
直接后果:
- system prompt 7 段在整个会话内不变
- 任何破坏 cache 的 slash command(如
/skills加新技能)默认 deferred 到下一会话生效,想立即生效必须显式--now - "记忆 reload" 只发生在会话开始;中途不重建
启发:用 prompt cache 后,默认行为应该是"不破坏 cache",破坏要用户显式选。
# 压缩点固定在 turn 边界
fold_turn_id = calculate_fold_point(messages)
memory.messages = [
Message.system(summary), # 摘要替代早期对话
*messages[fold_turn_id:], # 最近的对话原样保留
]
self._set_cache_at_position(fold_turn_id) # 关键:cache point 设在压缩点之后
核心思路:变化集中在末尾(最近几轮 + 用户新消息),cache 边界画在变化点之前,这样 cache hit 比例最大化。
#4.4 Claude Code 的"压缩后 re-inject"
claude-code-agent-architecture.md §5.4 列举的"幸存优先级":
- ✅ project root CLAUDE.md:会被 re-inject(重新从盘上读)
- ❌ 嵌套 CLAUDE.md:等下次 Claude 读那子目录文件时才会回来
- ✅ 已 invoke 的 skill:按 25K 总预算 re-attach(可能丢老的)
- ❌ 对话里口头说的临时规则:会丢 → 所以官方建议持久规则放 CLAUDE.md
启发:压缩后哪些段必须回来,哪些段可以丢——这是设计 compaction 时的核心决策,不能"全压全丢",也不能"全保全留"。
#4.5 Codex 的"cache 不归你管"
Codex 走 Responses API,encrypted_content 由 OpenAI 后端持有。框架本身不操心 cache invalidation——这是把 cache 设计权外包给 model server。代价:换 provider 的话这部分上下文带不走。
#4.6 Cursor / OpenHands 的"动态优先"
- Cursor:4 档 rules 召回意味着每次 prompt 注入的 rules 不同,cache hit 率天然受限。换来的是"硬盘有 50+ rules,进 prompt 的远少于 50"的容量优势。
- OpenHands:Microagent 触发性注入意味着每次匹配关键词的不同,注入的 microagent body 也不同,影响 cache hit。但 EventStream 把摘要本身做成 event,理论上能审计每一次 prompt 变化。
#五、按需召回机制对照
"硬盘上能塞 100 份资料,prompt 里只能装 5 份——决定哪 5 份的机制叫召回。"
#5.1 四种触发模式
① Always-on ② Glob / Path 触发 ③ Agent-decides ④ Manual / @-mention
每次都注入 文件路径相关时注入 description 给 agent 用户主动调
它自己决定要不要拉
Cursor: alwaysApply:true Cursor: globs:[...] Cursor: description+ Cursor: 空 frontmatter
Claude Code: project Cline: paths frontmatter alwaysApply:false + @rule-name
CLAUDE.md OpenHands: triggers:[...] Cline: @file/@folder/
Hermes: 启动加载的 OpenClaw: subagent (关键词) @problems/@terminal/
skill queryMode: recent/full @git-changes/@url
工具集
OpenHands: repo.md
#5.2 Cursor 是 4 档最完整的(值得抄)
cursor-agent-architecture.md §1.2:
| 模式 | frontmatter 关键字段 | 何时塞进 system prompt |
|---|---|---|
| Always | alwaysApply: true |
每次 agent 调用都注入 |
| Auto Attached | 非空 globs |
对话里出现匹配该 glob 的文件时自动注入 |
| Agent Requested | 非空 description,alwaysApply: false |
把 description 给 agent,由 agent 自己决定要不要拉 |
| Manual | 空 frontmatter | 用户写 @rule-name 才加载 |
为什么是 4 档?因为 .cursor/rules/ 能塞 50+ 文件,硬塞会爆 ctx。实际进 prompt 的 rules 远少于硬盘上的 rules——这是"按需召回"最好的注脚。
preload = "Agent 的本能" 每次推理都看得到
project_plan / memory_graph /
content_verify / capability_advisor
on-demand = "Agent 通过 find_assets 学到的新技能"
浏览器 / dev / pdf_processor / visual_processor / ...
发现 → skill() 工具加载
find_assets 是元工具——它的存在让 LLM 知道"还有别的能力但不知道详细 schema"。要用了才查。这跟 OpenAI 的 ToolSearch 模式同源。
#5.4 OpenClaw 的"子代理抢跑"(独特)
openclaw-agent-architecture.md §5.3:
用户消息: "那个项目今天怎么样了?"
│
▼
active memory sub-agent (blocking, 只有 memory_search / memory_get 工具)
│ memory_search("项目状态 最近")
│ memory_get("MEMORY.md")
▼
返回 summary: "用户提到的项目应该是 'XX',上周决定走 A 方案,今天 deploy 计划在 16:00"
│
▼
这段 summary 作为 hidden <active_memory_plugin> 块拼到主 LLM 的 system 段
│
▼
主 agent 这才正式 infer
代价:多一次 LLM 开销 + "agent 不知道自己看到的 context 来自哪里"的不可解释性。 好处:用户感受不到延迟(与主调用串行但短)+ 主 agent 不用自己写记忆查询代码。
#5.5 OpenHands Microagent 的"关键词触发"
openhands-agent-architecture.md §5.4:
user: "我想加个 useEffect 管下副作用"
│ event_stream.add_event(MessageAction)
↓
agent.step:
├ 检查 user message keywords → 命中 "useEffect"
├ emit RecallAction(query="useEffect")
↓
Memory.recall (openhands/memory/memory.py)
├ 扫已注册的 knowledge microagents triggers
├ 命中 react-best-practices.md
└ emit RecallObservation(content=microagent_text)
↓
event_stream 收到 RecallObservation
↓ 下一轮 step
ConversationMemory 把 RecallObservation 转成 system 区注入
LLM 看到 React 最佳实践 → 输出更准
frontmatter 长这样:
---
name: react-best-practices
type: knowledge
triggers: [react, hooks, useState]
---
#5.6 Cline 的"@ 引用"是用户控的最纯粹版
cline-agent-architecture.md §5.2,6 类引用:
| 引用 | 注入什么 |
|---|---|
@/path/to/file |
完整文件内容(带 import 上下文) |
@/path/to/folder/ |
整个目录树 + 每个文件全文 |
@problems |
VSCode Problems 面板里的 errors/warnings |
@terminal |
最近终端输出(保留格式) |
@git-changes 或 @<commit-hash> |
uncommitted diff 或某个 commit 的 diff |
@https://example.com |
webfetch 抓回该页面 markdown |
注意:`@ 引用展开后直接拼进 user message,不经过任何 retriever / 向量召回,纯 token 暴力。这是"不做语义召回"的极端选择——把召回完全外包给用户。
#六、工具结果压缩对照
"一个 grep 输出 50K 行,全塞回 LLM 就废了——怎么处理 tool 结果是 context 工程的"暗工程"。"
#6.1 几家做了的
| 项目 | 做法 | 出处 |
|---|---|---|
| OpenHands | 单个 observation 内容超过 max_message_chars(默认 30k)尾部截断 + "... [N chars truncated] ..." 提示 |
openhands-agent-architecture.md §5.2 |
| Claude Code | auto-compact 时优先清掉旧 tool outputs(尤其大 file reads);这是 Step 1 | claude-code-agent-architecture.md §5.4 |
| Cursor | 工具结果落成 file reference + preview;详细机制未公开(待核实) | — |
#6.2 没主动做的
- Hermes / Cline / Codex / AutoGen / LangGraph:没有框架级"工具结果自动压缩"机制。Cline 的
@file是用户控的全文塞,不带截断。Codex 的 shell 工具输出走 sandbox,默认会被 truncate 但 sandbox 层做的(不是 framework)。
#6.3 一个被低估的设计:OpenHands 的"observation 也是 event"
OpenHands 的 EventStream 抽象让"观察一个大输出 + 截断 + 提示用户"这件事变成 event 操作:
- L1(EventStream history)保留完整 observation 内容(甚至 30k 之外)
- L2(ConversationMemory)翻译给 LLM 时才截断
- 后续如果用户回头看 audit log,完整原文还在 L1
#6.4 一个常见但少有人写的反模式
反模式:"tool 返回大字符串,agent 每轮都把它全塞给 LLM。"
正确做法(业内共识,但只有 OpenHands / Claude Code 在 framework 层做):
工具执行 → 大输出
│
├─→ 完整原文落盘(path / file_id / db row)
└─→ 给 LLM 的:preview 前 N 行 + "完整内容见 path X,可用 read_file 拉"
#七、长会话稳定性 / state 持久化对照
"会话内是不是允许动态改 system prompt / 工具集 / memory?这是个深得能撕裂哲学派系的问题。"
#7.1 静态派 vs 动态派
静态派("会话内 system prompt 不变") 动态派("按需注入新内容")
Hermes AGENTS.md 写死禁止 Cursor 4 档 rules 召回
用 find_assets 但不动 system 嵌套目录读到才 inject
Codex AGENTS.md 启动拼一次,会话内 OpenHands Microagent triggers 关键词触发
不再动 OpenClaw Active Memory 子代理每轮抢跑
适合:长会话 + 高 cache hit 适合:项目大 + 资料多
代价:临时规则得手动改 代价:cache hit 率低、debug 难
#7.2 Session / checkpoint 持久化对照
| 项目 | 持久层 | 关键能力 |
|---|---|---|
| OpenClaw | session.jsonl append-only |
人类可读、可 git、可 cat |
| Hermes | SQLite + FTS5 + session lineage | 单进程、本地优先、跨 session 沿 lineage 检索;short timeout(1s) + retry(20-150ms × 15) + WAL checkpoints every 50 writes |
| Claude Code | session JSONL + agent-memory/ | 多 surface 共享同一 session |
| Codex | 本地 SQLite(sqlite_home / CODEX_SQLITE_HOME) |
codex resume 续 / codex fork 分叉 / /new 同进程开新对话 / /side 临时小窗口(fresh ctx 不污染主线) |
| Cursor | 服务端 chat history + Codebase Index Merkle tree | 跨设备复用(账号绑定);plaintext 永不上服务端 |
| Cline | ~/.cline/data/taskHistory.json + 影子 git |
task 级 messages + cost;影子 git per-step commit 让 YOLO 模式有底气 |
| OpenHands | EventStream(核心抽象) | deterministic replay:从任意 event_id 起跑、可分叉、可审计 |
| AutoGen | team.save_state() / load_state()(v0.4 新) |
dict → json.dump;包含每个 agent 的 model_context、memory、speaker pointer、termination 累积 |
| LangGraph | Pregel Checkpointer(Memory/SQLite/Postgres/Redis) | Time Travel:从历史 checkpoint 重放、可改 state 再跑;Pregel 通道版本号决定 next superstep 哪些节点要跑 |
#7.3 三条最值得提的设计
(1) OpenHands EventStream = state 是 derived value
openhands-agent-architecture.md §5.1:把 conversation = ordered event log 当作核心抽象,state 不是存起来的,是从 event log 重算出来的。这给了三个超能力:完全可重放、可审计、可分叉。
代价:副作用必须 emit 成 event 才"算数",agent 不能在 step 内偷偷改外部状态而不留 event。这对工程纪律要求很高。
(2) LangGraph Time Travel
langgraph-agent-architecture.md §5.3:
history = list(app.get_state_history(config))
old_cp = history[3]
new_config = {"configurable": {"thread_id": "...", "checkpoint_id": old_cp.config["configurable"]["checkpoint_id"]}}
app.invoke(None, new_config) # 从老 checkpoint 接着跑
app.update_state(new_config, {"plan": "...new..."}) # 改 state 再跑
这是 Pregel 模型的副产品——每个 superstep 都能重放,能改 state 再走。比 print + 复现快十倍,是调试 agent 的杀手锏。
(3) Codex /side 临时 fresh context
codex-agent-architecture.md §5.3:在同一个 CLI 进程内开一个独立"小窗口"问个简短问题(fresh context),不污染主线 thread。这是个少有人提的小创新——承认 "agent 主线 ctx 不应该被任何 ad-hoc 问题污染"。
#八、最值得抄走的 5 个设计创新
"看了 10 家设计,挑 5 个 '这家做了别家没做' 的事,给设计自家上下文工程时直接套。"
#8.1 Hermes:把 cache 完整性写进 AGENTS.md 当顶级硬约束
把 "do NOT alter past context mid-conversation" 写成项目文档的硬约束——这件事看起来微小,但它把 prompt cache 从"性能优化"提升到"架构约束"。所有破坏 cache 的操作(slash command 改 skills / memory reload / system prompt rebuild)默认 deferred 到下一会话,用户要立即生效必须 --now。
启发:当一个性能优化的不命中代价 = 整轮重算 token,那它就该被当成架构约束写进规范,而不是"如果命中了不错,没命中也没事"。
#8.2 OpenHands:Condenser 是一等公民 + 摘要也是 event
把上下文压缩从"用户 plugin"提到"框架核心抽象",加上"摘要本身也是 event 进 stream",让长 session cost 从二次方变线性、且摘要可审计可回放。
启发:任何会改变 LLM 输入的操作都应该 emit 成 typed event 而不是隐藏在框架内部。这让你可以审计任何一次 prompt 变化的来源。
#8.3 Cursor:4 档 rules 触发模式
Always / Auto-Attached / Agent-Requested / Manual 四档解决了"硬盘 50 份 rules、prompt 只能装 5 份"的问题。每档由 frontmatter 的不同字段触发,零代码就能让用户决定召回模式。
启发:召回机制不应该只有"全塞" or "完全靠语义检索"两档。在两端之间至少有 4 个有用的中间档(确定性 + 模糊 + agent 自决 + 用户手动)。
把"什么时候压缩"和"cache point 设在哪"绑成同一个决策——压缩点固定在 turn 边界,cache 边界画在压缩点之后。这样:
- 变化集中在末尾(最近几轮 + 用户新消息),cache hit 比例最大化
- 压缩之后 cache 重建的成本可预测
- 调试时能清晰看出 "这轮命没命中 cache"
启发:性能边界(cache point)应该跟语义边界(turn / 压缩点)对齐,而不是各拍各的。
#8.5 Codex:嵌套 AGENTS.md + override 机制
合并顺序设计:
1. ~/.codex/AGENTS.override.md ← 个人最高优先级
2. ~/.codex/AGENTS.md ← 个人默认
3. <git_root>/AGENTS.override.md ← 项目最高优先级(不进 git?或进)
4. <git_root>/AGENTS.md ← 项目默认
5. <git_root>/<sub_dir>/AGENTS.md ← 子目录细化
...
N. <cwd>/AGENTS.md ← cwd 最具体
每层都有 .override.md + AGENTS.md 两个文件,外层覆盖内层。32 KiB 上限强制不能堆超大文件。这把"工程文件作为系统提示"做到了最完整的层级表达。
启发:当一个配置文件可能被多 scope 覆盖时,提供 .override.md + 默认 + 嵌套 三件套,而不是单一文件。这是 git workflow 直接套到 prompt engineering。
#九、趋势观察 + 一句话各家总结
#9.1 三个跨家共识
(1) AGENTS.md 已成事实标准。 Codex / Cursor / OpenClaw 原生识别这个文件名;OpenClaw 还兼容 CLAUDE.md 软链。Claude Code 自家用 CLAUDE.md,官方建议在 CLAUDE.md 里写 @AGENTS.md 引入而非直接读取(见 claude-code-agent-architecture.md §5.2)。Cline 用 .clinerules/ 目录,与 AGENTS.md 同一逻辑(每次失败 → 一条永久规则)但文件命名不同。这是 2025-2026 行业最重要的一次"开放协议吃下私有后台"——之前各家想做"自家 memory 后台 + 仪表盘",最后市场给的答案是"放回 git 里"。
(3) 工具结果压缩仍是个 framework 层的空白。 OpenHands / Claude Code 做了一点(observation 截断、auto-compact 优先丢 tool output),但没有任何一家有"tool 返回大输出自动落盘 + 给 LLM preview"的框架级约定。每个工具自己 truncate,agent 看不到"这个工具会输出多大",这是后续可以做的事。
#9.2 一句话各家总结
| 项目 | 一句话 |
|---|---|
| OpenClaw | 全 markdown + session:compact:before 配合 session-memory hook,"压缩前先抢救一次";Active Memory 子代理预跑 |
| Hermes | AGENTS.md 写死"会话内禁止改 prompt/tools/memory",cache 完整性顶级硬约束 |
| Claude Code | 5 层记忆 + auto-compact 三阶 + project CLAUDE.md re-inject + skill 25K 预算 re-attach |
| OpenAI Codex | AGENTS.md 嵌套 + override;compaction 走 Responses API encrypted_content(server-side stateful) |
| Cursor | 4 档 rules 召回(Always / Auto / Agent-Requested / Manual),动态注入派天花板 |
| Cline | 用户全控派:6 类 @ 引用 + /smol + /newtask 双路径,影子 git 兜底 |
| OpenHands | Condenser 是一等公民;EventStream 让摘要也是 event,state = derived value |
| AutoGen | ChatCompletionContext 4 种策略 + Memory protocol,没有"框架级 system 段"约定 |
| LangGraph | 完全交给用户:state 字段 + reducer + checkpointer,Time Travel 是免费副产品 |
#附:源文档章节对照(供深读)
| 主题 | 主要出处 |
|---|---|
| 工具结果压缩 | openhands §5.2 / claude-code §5.4 |
| Session/checkpoint | hermes §5.3 + §5.6 / codex §5.3 / openhands §5.1 / langgraph §5.2-5.3 / autogen §5.4 / cline §5.3 + §5.5 |
| 8 大对比综述 | agent-architectures-comparison.md §6 |