ARTICLE · 1146688
DeepAgents(六): 大结果卸载
《代码的江湖》
工具返回 24 万字符,历史里只剩 1274 字符。窗口装不下的结果被搬进文件,模型那一轮只看得到路径和预览,这是虚拟文件系统最实用的一手。
省了多少好量,搬走之后的事不好猜:东西落在哪、能活多久、要用的时候取回一次付多少。
卸载省下的是上下文窗口;被搬走的内容存在哪、能活多久,取决于你装的是哪个 backend。
下面这笔账来自一次真跑。8 轮任务,工具累计返回 87 万字符,我逐轮记下模型真正收到多少,再把 4 种 backend 各装一遍看产物落到哪。全程不用 API key,读完约 6 分钟。
一、先把 3 个结论摆出来
后面按这 3 条逐条给证据。
二、省了多少:一次 8 轮任务的账
先看任务长什么样。8 轮工具调用,其中 5 次返回 3 万字符、3 次返回 24 万字符。卸载线是 tool_token_limit_before_evict = 20000,配上 NUM_CHARS_PER_TOKEN = 4,也就是 8 万字符。
逐轮记下模型每次调用收到的历史字符数:
表里「模型这一轮收到」是它这次调用时看到的历史,「本轮工具返回」是这次调用之后拿到的东西,两者错开一轮。
规律很干净:一条 3 万字符的结果,下一轮原样带上,多 30000;一条 24 万字符的,下一轮只多 1274。
收尾时整张表算下来:
3 条 24 万的结果,历史里各剩 1274 字符。其余部分全在文件里,一个字没少。
要确认卸载的功劳,得把它关掉
「占了 17%」这个数字单独看说明不了什么,得知道不省会怎样。建 agent 时传一个同名的 FilesystemMiddleware,把它的 tool_token_limit_before_evict 设成 None,装配环节会按 .name 原地替换掉默认那个。替换后栈里仍然只有 1 个 FilesystemMiddleware,阈值从 20000 变成 None。
同一个任务跑 3 遍:
第二行值得停一下。把卸载关掉,历史也没长到 87 万,因为后面还有一道线接着,模型逐轮实收的峰值也跟着从 15 万涨到 60 万。
第二道线是摘要
同一批装配里,摘要在历史涨到 68 万字符左右时动手,把旧消息压成摘要,还往 /conversation_history/session_xxx.md 写了 33 万字符。所以关掉卸载只到 840013。
2 道线都关才能看到 100%,此时收尾是 87 万字符,约 21.8 万 token。
顺带解释一条容易踩的坑:摘要的触发线分 2 档。
max_input_tokens | |
假模型没有 profile,走的是第二档。用真模型时若 profile 里没写窗口大小,退到的就是这条固定线,跟窗口实际多大无关。

三、卸下来的东西落在哪
省下来的是窗口,那内容去哪了。同一份 24 万字符的结果,装 4 种 backend 各跑一次:
files 字段,键是 /large_tool_results/call_1 | ||
<root>/large_tool_results/call_1 | ||
/large_tool_results/call_1 | ||
<root>/call_1 |
最后一行有个细节:路由之后前缀被剥掉了,磁盘上的真实路径少一层 large_tool_results。这段不算问题,用原来的虚拟路径仍然读得回来,实测 read_file('/large_tool_results/call_1') 成功,读到 6436 字符。
默认那一行才是重点:默认 backend 把卸载产物装在图 state 里。它跟普通文件一个待遇,不会因为「是框架自动写进去的」就多一层落盘。
四、它能活多久
接着上面的结论往下问:装在图 state 里的东西活多久。同一个卸载任务跑 3 遍,每遍换个方式再读一次产物:
第一行要注意:默认装配下没有 checkpointer,同一个会话里再跑一轮,产物就没了。第二行加上 InMemorySaver 能留住,但换一个 thread_id 等于换一个会话,还是取不回来。
要真落盘就换 FilesystemBackend,指定一个 root_dir,写下去就是真文件,重开 agent 还能读。
FilesystemBackend(
root_dir=root,
)
五、取回一份要读几次
产物没丢,那取回贵不贵。一份 24 万字符、3886 行的产物,read_file 默认一次读 100 行:
42 次是整份读完的下限。这个数按日志文本算,一行约 62 字符,换成别的语料,行宽不一样,次数跟着变。
真实任务里通常只要其中一小段,这也正是卸载能省上下文的前提:模型先看那 1274 字符的引用,判断要不要取、取哪一段。
再验一件事,搬走的过程有没有截断:
搬走的是完整的,只有历史里那条变短了。

六、所以这笔账怎么算
3 条收口。
卸载省的是窗口,换不来留存。 省下的上下文是真的,但产物落在哪个 backend 里,就受那个 backend 的寿命管。默认装配下换一个会话,东西跟着一起走。
要留住就得换存的位置。 卸载产物和普通文件一个待遇,没有额外通道。想跨会话留住,用 FilesystemBackend 写磁盘,或者 StoreBackend 交给 store。
取回成本要算进预算。 一条 24 万字符的结果全读一遍约 60004 token,比不卸载还贵。卸载的价值建立在「只取要用的那一段」上。
选之前先想清楚这 2 件事:产物要活多久,你打算怎么取回它。
— 代码的江湖 —