智猩猩AI整理
编辑:林夕
DeepSeek Harness开源之后,社区开始出现一种很有意思的现象。
大家已经不满足于看它能不能跑Agent了,而是开始顺着Harness内部的每一个组件往下拆:
工具怎么调用、Context怎么压缩、结果怎么保存,以及当Agent看不到一部分信息之后,它还能不能把这部分信息找回来。
最近,GitHub上的一个Pi社区PR,就把这个问题直接摆到了台面上。
Pi开发者adamteale在PR 中提交了一套tool-result pruner+spill extension。
![]()
设计说明里明确表示,这套方案参考了DeepSeek Harness的compaction-tool-result-pruner和spill-policy。
但他进一步提出了一个问题:如果工具结果被裁剪后,模型未来又需要中间那部分信息怎么办?
在PR的设计说明中,他将DSH pruner描述为:
dsh pruner permanently drops the middle of pruned results with no recovery path.
这里的关键并不是信息被永久删除,而是被pruner移出模型当前Context之后,模型是否拥有一条直接的回溯路径。
于是,他给出的方案是:Context可以裁,但完整信息要留下。
01
一个写死的8192,
Agent正在主动失忆
为了控制上下文占用,DSH内置了工具结果裁剪。
DSH官方默认配置是这样,工具返回结果超过8192个字符,保留头部4096个字符和尾部1024个字符,中间的部分替换成一行省略标记。
![]()
对于超过8192 Unicode code points的工具结果,DSH会在模型侧只保留头部和尾部;完整原始事件仍保存在Session Log中,但模型当前上下文不会直接携带中间内容。
也就是说:
[ 前4096 ][ 省略 ][ 后1024 ]从Context管理角度看,这非常合理。问题是,Agent当下不知道未来需要什么。
今天被认为不重要的中间几千行,可能正是十几轮之后定位Bug所需要的信息。
这位开发者在实际测试中,仅一个下午就遇到了七次截断。每次截断都迫使模型从头开始重新生成整个插件源码,且试图填入一个更大的窗口,效率极低。
![]()
举个例子。你让Agent排查一个服务故障,它grep出一段21,800字符的日志,错误堆栈在第7000个字符附近。
按默认规则,这段日志被砍成4096加1024,错误堆栈正好落在被替换掉的中间区段。
Agent只能看到完整的开头、完整的结尾,和一行省略标记,然后基于看不到错误在哪的残缺信息继续推理,大概率给出一个错误结论。
这并不是DSH独有的问题。
GitHub上一个高讨论度Issue #45770,就暴露了同样的问题:
Claude Code的工具结果存在约25K token的硬上限,一个300KB的 Confluence页面因此无法完成“读取、修改、回传”的完整工作流。
![]()
另外,#14888也可以作为旁证,它专门讨论了Claude Code固定25K token文件读取上限与模型实际Context 能力不匹配的问题。
![]()
02
Context可以裁,但信息别丢,
Pi给Agent留了一条后路
既然问题不是结果太长,而是长结果被移出Context之后,模型缺少直接的回溯入口,那能不能换一种处理方式?
Pi开发者的答案是:可以。
它没有取消裁剪,而是在裁剪之前多做了一步:把完整结果复制到spill file。
超过阈值的结果,模型上下文里仍然只保留头部、尾部和省略标记;与此同时,完整结果被写入磁盘,并通过一个文件定位信息告诉模型去哪里找。
再配合read_tool_result,模型需要中间某段内容时,可以指定path、offset和length,把对应区段重新读回来。
也就是说,Pi并没有试图让Context装下更多东西,而是让暂时看不见和永远找不到变成两回事。
Pi的扩展API提供pi.on()事件钩子和pi.registerTool()注册接口。其中tool_result事件在工具结果写入上下文之前触发,允许拦截和改写,这正是做这件事的完美位置。
插件的逻辑分三步。拦截,结果长度超过阈值就进入处理。落盘,完整结果写入 artifacts 目录,一个字节都不丢,路径、总字符数、落盘时间全部记录。改写返回,上下文里放头部4096字符、尾部1024字符,再加一把钥匙,告诉模型完整结果在哪、怎么取回。
对照一下两种方案对同一份21,800字符结果的处理。
DSH的方案,模型拿到4096加1024和一行省略标记,中间内容从当前模型上下文中移除;完整原始事件仍保留在Session Log中,但模型没有一个直接的按区段读取入口。
Pi插件的方案,模型拿到同样的首尾加一把钥匙,中间内容完整躺在磁盘上,任何时刻都可以按需取回。
两套方案真正的区别,不是保存还是丢弃,而是保存之后,模型能不能主动取回来。
DSH解决的是如何把超长结果压缩成模型当前需要看的信息;Pi这个插件则进一步给这些被移出Context的内容增加了一条按需回溯的路径。
这也暴露出一个更有意思的区别:Session Log可以保存完整历史,但系统保存了并不等于模型能够按需访问。
Pi自己对截断的态度也能看出渊源。
Pi在v0.13.2版本中,已经将工具输出截断统一为2000行或50KB的限制,并针对不同工具提供继续读取的路径。
到v0.37.5,干脆把truncateHead、truncateTail这些工具函数直接导出给扩展用。
思路是一脉相承的,截断可以有,但截断必须透明,透明之后还得给模型留一条回去的路。
03
一次PR,
重新思考Agent的Context管理
看到这里,其实会发现,Pi开发者和DSH的思路并不是简单的谁的截断算法更好,两边真正的分歧,是对Context之外的信息到底应该怎么处理。
DSH的思路更像是:Context有限 → 超长结果裁剪 → 当前不需要的信息先移出去。
而Pi这个插件进一步追问了一步:如果Agent之后突然需要那部分信息呢?
答案不是把Context做得更大,而是给被裁掉的信息留下一个可检索的外部存储层。
这其实比单纯扩大Context窗口更值得关注,因为对于Agent来说,真正重要的从来不是我现在能看到多少信息,而是:
“我现在看不到的信息,需要的时候还能不能找到?”
这也是为什么这个Pi插件有意思,它并没有否定DSH的pruner,甚至沿用了相同的头尾保留策略,只是给Context之外的信息增加了一条回溯路径。
回到这份PR本身,这个方案最终并没有直接进入Pi核心。
PR按earendil-works/pi的CONTRIBUTING.md流程被自动关闭了,新贡献者的PR默认如此。
adamteale随即在issue 请求维护者批准重开。插件是14个文件的自包含示例,不改核心代码,不引入额外依赖,只使用Pi现有的extension API。
![]()
两个链接都是公开的,任何人都可以打开查看完整的benchmark数据和设计决策。
所以,8192这个看似简单的阈值,也因此不再只是一个Context预算问题,真正引出的其实并不是一个阈值到底应该设多少的问题。
而是当信息被移出模型视野之后,Agent还能不能把它找回来?
Context可以压缩,信息可以暂时离开视野,但一个真正成熟的Agent,应该知道去哪里把它找回来。
关注+星标,获取AI前沿进展与开源一线动态
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.