跳到主要内容

dexter — 本课题摘录

读了哪几篇: 01-agent-loop(核心主循环)、02-tools-and-permissions(工具层)、03-context-engineering(上下文工程)。 其余三篇(记忆系统、子 agent 与技能、无人值守与多渠道)本轮没读。

这一家是"长任务里上下文怎么管"最系统的一份,而且它自己说这是全书工程含量最高的一章。

它对本课题回答了什么

决定一:先把问题定义清楚

"上下文工程 = 在固定大小的窗口里,决定什么留、什么压、什么扔,让 agent 能一直研究下去而不崩、也不失忆。"

它点出了两种失败,不只一种:

失败表现
塞不下直接报错,这一步作废
塞太满就算没报错,模型也会"注意力稀释",在一堆旧数据里找不到重点

(依据:Agent 库 · Dexter · 上下文工程:让上下文有界又不丢信息(全书精华) —— 上下文有两种失败——塞不下会直接报 overflow 错误,塞太满则即使没报错模型也会注意力稀释、在一堆旧数据里找不到重点)

第二种失败很容易被忽略。 我们讨论压缩时通常只想着"别超限", 但"没超限但塞太满"同样会让 agent 变笨,而且不会报错。

它还点出了自己场景的特殊难点:工具结果里的数字恰恰是最终答案要用的,不能随便扔——所以不能简单"删旧的",得在压缩的同时保住数字。

决定一的核心心智模型:窗口是内存,暂存文件是磁盘

把上下文窗口当内存,把一个只追加的暂存文件当磁盘。 内存(喂给模型的那串消息)必须精简、有界;但所有工具结果的完整原文都先落磁盘,一份不丢。 需要压缩时,是"从磁盘重新组织一份精简视图喂进内存",而不是"把内存里的东西删掉就没了"。

(依据:Agent 库 · Dexter · 上下文工程:让上下文有界又不丢信息(全书精华) —— 心智模型是「窗口当内存、append-only scratchpad 当磁盘」——所有工具结果完整原文先落磁盘一份不丢,压缩是从磁盘重新组织一份精简视图喂进内存而非删掉内存里的东西)

这句话是本课题"历史怎么压"这一支最好的一句概括。 deepseek-harness 的"日志 + 投影"、deepagents 的"不改历史只投影"、headroom 的"可逆压缩"—— 全都可以用这一句话统一表述。

决定一:四道防线,按代价从轻到重

① 单结果治理 ② 微压缩 ③ 全量压缩 ④ 硬截断
单个结果太大? 旧的读类结果太多? 窗口快满?让模型把 还超?直接删
→ 落盘 + 留预览 → 换成「已清除」标记 所有结果摘成结构化 最旧的几轮
每轮总量超预算 保留最近 4 条 摘要(保数字) (信息真丢)
→ 大的先落盘
──────────── ──────────── ───────────── ──────────
进消息前先做 每轮前跑一次 过阈值才跑 压缩失败或
(便宜、无损) (便宜、不花模型钱) 失败 3 次就不再试 溢出时兜底

(依据:Agent 库 · Dexter · 上下文工程:让上下文有界又不丢信息(全书精华) —— 四道防线依次是单结果治理(落盘+留预览、每轮总量预算)、微压缩(旧的可清除工具消息换成占位符、保留最近 N 条、不花 LLM)、全量压缩(过阈值才跑、用快模型摘成结构化 summary、失败 3 次就不再试)、硬截断(删最旧轮次,信息真丢))

四道防线的四个属性对比,是这份材料最实用的部分:

防线花不花模型钱有没有损什么时候跑
单结果治理不花无损(原文落盘)进消息之前
微压缩不花半损(能从磁盘找回)每轮前
全量压缩花(用便宜的快模型)有损但保数字过阈值
硬截断不花真丢兜底

"微压缩不花模型钱"这一档是别家少见的。 opencode 的"裁剪"、deepagents 的"工具参数截断"是同一档,但dexter 把它明确排在"全量摘要"之前—— 先用不花钱的办法,不够再花钱。

"失败 3 次就不再试"是一条重要的护栏:压缩本身也会失败,不能无限重试。

决定一补充:两种预算 —— 单个结果 vs 每轮总量

它区分了两件事:

  • 单个结果太大 → 落盘 + 在消息里留一段预览;
  • 一个轮次内工具结果的总量超预算大的先落盘。

(依据:Agent 库 · Dexter · 上下文工程:让上下文有界又不丢信息(全书精华) —— 单结果治理分两种——单个结果太大则落盘并注入预览,一个 turn 内工具结果总量超预算则大的先落盘)

"每轮总量"这个维度很多实现没有。 五个工具各返回一份不大不小的结果,单看都没超,加起来就爆了。 这条要抄。

决定三:连续只读的调用批成并行,写操作串行过闸门

它的并发规则是按"读/写"分的:连续的只读调用批成并行,写操作串行、并且要过权限闸门。 (依据:Agent 库 · Dexter · 工具层:元工具路由、并发批处理与权限闸门 —— 执行器把连续只读调用批成并行、把写操作串行并过权限闸门;权限引擎对 bash 采用 fail-closed 的解析-分类-匹配三步)

权限引擎对跑命令这类工具采用"默认拒绝"的解析-分类-匹配三步。

这是并发问题的第四种答案(前三种:按动作类型硬分、按读写集合自动推、工具自己声明只读)。 dexter 这一种最简单:连续只读的凑一批,遇到写就断批。

决定四:主循环

一个异步生成器反复"喂消息给模型 → 看有没有工具调用 → 有就执行并把结果塞回消息数组 → 没有就是终答",全程用事件流对外播报。 (依据:Agent 库 · Dexter · 核心主循环:一次 query 如何端到端跑完 —— 核心主循环是一个 async generator 反复「喂消息给模型 → 看有没有工具调用 → 有就执行并把结果塞回消息数组 → 没有就是终答」,全程用事件流对外播报)

它没回答什么

  • 不用原生工具调用怎么办——它假设模型支持。
  • 停止条件的护栏——这三篇没讲轮数上限、连错熔断。
  • 循环状态怎么存下来续跑——暂存文件保住了工具结果,但不是"整个运行可恢复"。

坑与代价

  • 四道防线的阈值和条数(保留最近 4 条、失败 3 次、每轮预算)都是经验值。 换场景要重调。
  • "落盘 + 留预览"要求模型知道"想看全的怎么取回"。 如果没有配套的取回工具,预览就是纯粹的信息损失。

    判断(无锚): 这一点上 headroom 的"带 hash 的取货单"更完整。dexter 落盘但这三篇没讲取回路径。 如果错,会错在: 如果模型基本不需要回看细节(结果只用来做一次判断),那不给取回路径反而更简单。

  • 它是金融深度研究场景,一次查询能连打几十个工具、抓回几百 KB。 我们的最小原型远没有这个量级—— 但它的四道防线是一个可以照着长的路线图:第一版只做第 ①、④ 两道就够。