用 OpenClaw 跑长任务的人,迟早会遇到这个场景:

agent 刚启动的时候反应很快,跑了两三个小时之后开始变慢,六七个小时之后每次回复要等十几秒,Telegram 消息偶尔直接超时。

你以为是模型变笨了,或者 API 限速了,或者服务器扛不住了。

都不是。

是你的 session 太胖了。

胖在哪

OpenClaw 的 session 会累积所有的对话历史、工具调用结果、文件读写记录。每次 agent 要回复你,它得先把整个 session 装配进上下文窗口。

一个跑了 8 小时的 session 是什么样的?

内容类型 占比 特点
你说的话 5% 有用
agent 的回复 15% 部分有用
工具调用输出(bash、文件读写、搜索结果) 60% 大部分过期
系统提示词 + skills 10% 每次都要加载
重复的上下文恢复 10% 纯浪费

60% 的 token 花在了已经过期的工具输出上。你两小时前让 agent 读的那个文件,内容还挂在 session 里,每次回复都要重新装配一遍。你三小时前跑的那段 bash 输出,200 行日志,还在那占着位置。

这就是"session 肥胖症"。

为什么 /compact 不够用

OpenClaw 自带 /compact 命令,会让 agent 把长历史压缩成一段摘要。

问题是:摘要是自然语言写的。

自然语言摘要有三个毛病:

第一,密度低。agent 写的摘要经常是"我们讨论了 X,然后做了 Y,接着解决了 Z 的问题"这种句子。看着像有信息量,实际上恢复现场的时候什么都找不到。文件路径没了,决策原因没了,下一步动作模糊了。

第二,每次不一样。同样的 session,让 agent 压两次,出来的摘要结构完全不同。下一个 agent 接手的时候,不知道该信哪个版本。

第三,该删的没删,该留的没留。闲聊保留了,文件路径丢了。过程保留了,结论丢了。

换一种压法:结构化索引

我们在生产环境里试了一种不同的压缩方式。不写自然语言摘要,写结构化索引。

格式长这样:

::SESSION_INDEX{
  ::META{
    session_key:bounty-hunter-2026-05-08
    date:2026-05-08
    topic:操盘手特训营全书重塑
    status:active
  }
  ::GOAL{
    primary:完成全书 PDF 输出
  }
  ::DECISIONS{
    ::ITEM{id:D1|desc:用 weasyprint 不用 wkhtmltopdf}
    ::ITEM{id:D2|desc:中文字体用 Noto Sans CJK}
  }
  ::STATE{
    ::ITEM{key:主稿|value:已完成|conf:high}
    ::ITEM{key:PDF输出|value:被 elevated 权限阻塞|conf:high}
  }
  ::ARTIFACTS{
    ::FILE{path:/root/workspace/特训营.md|role:主稿|status:final}
    ::FILE{path:/root/workspace/特训营.print.html|role:印刷版|status:ready}
  }
  ::TODO{
    ::ITEM{prio:P0|task:开通 elevated 权限后安装 PDF 工具链}
    ::ITEM{prio:P1|task:生成 PDF 并验证中文显示}
  }
  ::RISKS{
    ::ITEM{level:high|desc:Telegram provider 下 elevated 未生效}
  }
  ::ANCHORS{
    ::ITEM{ref:/root/workspace/特训营.md|note:全书终版在这}
  }
  ::SUMMARY{
    one_line:主稿和HTML都好了,卡在elevated权限出不了PDF
  }
}

对比一下两种压缩方式:

自然语言摘要 结构化索引
信息密度 低,散文体 高,每行一个事实
一致性 每次压出来不一样 格式固定,机器可解析
文件路径 经常丢 强制保留
决策记录 混在段落里 独立字段
下一步动作 "我们接下来可以考虑..." P0/P1/P2 优先级
恢复速度 要读完整段再理解 扫一眼就知道现场
token 成本 200-500 tokens 80-150 tokens

同样的信息量,结构化索引的 token 成本大约是自然语言摘要的 1/3。

什么时候压

不是等 session 卡死了才压。我们定了八个触发条件:

  1. 会话超过 30 条有效消息
  2. 出现大文件操作(PDF、长文档、批量编辑)
  3. 一个任务形成了稳定结论
  4. heartbeat 到来且 session 明显变肥
  5. 即将 /new
  6. 发现装配成本在上升(回复变慢)
  7. 完成一个阶段性交付物
  8. 出现重复上下文或重复解释

关键的思维转变:heartbeat 不只是报平安,还要承担瘦身职责。agent 收到 heartbeat 的时候,先检查 session 是不是肥了,肥了就先压再回复。

恢复怎么做

压完之后,agent 恢复现场的顺序也要倒过来:

  1. 先读 PROJECT_INDEX(项目级)
  2. 再读 SESSION_INDEX(会话级)
  3. 再读相关文件
  4. 只有索引不够时,才回看原始长历史

大部分 OpenClaw agent 的默认行为是反过来的:先扫全量 trajectory,装配整段历史,然后在一堆过期信息里找有用的。这就是慢的根源。

两层压缩

短期任务只需要 SESSION_INDEX。

长期项目需要两层:SESSION_INDEX 记录"这次会话做到哪了",PROJECT_INDEX 记录"这个项目长期做到哪了"。

::PROJECT_INDEX{
  ::META{name:操盘手特训营|updated:2026-05-08}
  ::GOAL{primary:完成全书出版级 PDF}
  ::FACTS{
    ::ITEM{key:总字数|value:85000}
    ::ITEM{key:章节数|value:12}
  }
  ::DECISIONS{
    ::ITEM{id:PD1|desc:排版用 CSS print media 不用 LaTeX}
  }
  ::ARTIFACTS{
    ::FILE{path:特训营.md|role:主稿|status:final}
  }
  ::NEXT{
    ::ITEM{prio:P0|task:PDF 输出}
  }
}

项目跨了十几个 session,换了三个 agent,中间重启过两次 gateway。只要 PROJECT_INDEX 在,任何一个新 agent 读一遍就能接手。不需要回放十几个 session 的完整历史。

实测效果

在我们的生产环境里(OpenClaw + Telegram,每天 100+ 消息),用这套协议跑了一周:

指标 压缩前 压缩后
平均回复延迟(8小时 session) 12-15秒 3-5秒
单次装配 token 消耗 8000-12000 2000-4000
Telegram 超时率 每天 3-5 次 基本消失
/new 后恢复时间 30-60秒 5-10秒
agent 接手准确率 看情况 读索引就能干活

最明显的变化是 heartbeat 不再卡了。之前 heartbeat 经常因为 session 太重,光装配上下文就超时。现在 heartbeat 到了先压一下,session 保持在合理体重,后续每次回复都快。

完整协议

完整的 Session Compression Index Protocol v1.0 已经开源,包含十四个章节:总原则、触发条件、压缩目标、输出位置、索引格式、项目级压缩、写作规则、恢复策略、heartbeat 规则、/new 规则、主会话纪律、禁止事项、铁律、最终目标。

GitHub 地址:(评论区问我要)

索引格式用的是 I-Lang 的声明语法(::ENTITY{field:value} 结构),如果你用过 I-Lang 的 SOUL 或 GENE 定义,这个格式会很熟悉。不了解也没关系,上面的例子照着抄就能用。

一句话

你的 agent 不是变笨了,是被自己的历史压垮了。给它一个索引层,让它靠索引活,不靠长聊天活。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐