Agent 怎么处理工具结果
工具结果跟普通对话不一样 - 单条可能就是 100KB grep 输出或者半 MB JSON。它会沿着 transcript 一路堆积,最容易爆窗口。Pi 没单独管,让它跟着文件读取限制走;OpenClaw 划了独立预算(16K / 30%),还做了"结尾重要"的启发式判断;Claude Code 干脆把超大结果写到磁盘,对话里只留 2KB 预览,并且对 prompt cache 的影响想得很周到
这是 agent 上下文管理系列的第五篇。第四篇讲了三家怎么读大文件,这一篇讲一个更棘手的问题 - 工具结果(tool result)。
工具结果跟“读文件”是两件事
刚开始读这几家源码的时候,我以为工具结果就是文件读取的延伸 - 都是“返回一段长文本给模型看”,应该用同一套机制管。读完发现这是两个相当不同的问题。
文件读取有几个隐含特性 - 总长度可知(stat() 一次就拿到字节数)、内容相对结构化(代码 / 文本 / JSON)、模型可以指定 offset/limit 自己控制读多少。所以管它相对容易,“截断 + 续读提示”就解决大半。
工具结果不一样:
总长度不可预测。
grep -r可能返回 100 行、可能返回 100 万行;HTTP 请求可能返回 200 字节、可能返回 20 MB。结构千奇百怪。bash 可能输出纯 stderr、shell 可能 ANSI 转义满天飞、JSON API 可能压成单行。
模型不能“分页”。工具一旦执行,结果是一次性返回的。模型看到的就是工具调用的全部输出,没法说“我只要前 100 行”。
会沿着 transcript 堆积。一个长会话可能跑几十次工具调用,每次几十 KB 的结果累加起来很容易上百万 token。
如果不专门管工具结果,模型会被自己产生的输出拖死。
Pi、OpenClaw、Claude Code 三家在这件事上的设计差异比文件读取大得多。
Pi:让工具结果跟着文件走
Pi 的答案最朴素 - 几乎不专门管工具结果,让它跟着工具自己的限制走。

