feat(agent): tool output offloading — persist truncated results to disk for recovery - #2446
Merged
Merged
Conversation
…sk for recovery Implements the 2026 "Tool Output Offloading" harness-engineering pattern (LangChain "Anatomy of an Agent Harness"; practiced by Claude Code and Manus): when guardToolOutput truncates a large tool result under context pressure, the FULL original output is now persisted to a spill file under the OS temp dir, and the truncation notice carries the absolute path with recovery instructions (read_file offset/limit or grep), so the agent can inspect the omitted middle section instead of losing it forever or re-running the tool (wasteful for deterministic tools, impossible for one-shot side effects like flaky test runs or deploy logs). Details: - internal/agent/tool_output_offload.go: lazy, concurrency-safe offloader; spills <8KB skipped (head-tail already suffices); 20MB per-file cap; max 20 files per session (oldest pruned); stale spill dirs from crashed sessions pruned after 24h; best-effort — I/O failure falls back to plain truncation and never fails the tool result path. - agent.go: spill hook in the guardToolOutput truncation branch; spill notice appended before the tool-specific truncation advisory, so the model sees the recovery path adjacent to the truncation marker. Research basis: LangChain "The Anatomy of an Agent Harness" (2026), Anthropic "Effective Harnesses for Long-Running Agents" — context management strategy #3 "Tool Output Offloading: storing large tool results to the filesystem rather than injecting them directly into context. Reduces noise while keeping the data accessible." Co-Authored-By: ggcode <noreply@ggcode.dev> Co-Authored-By: ggcode <noreply@ggcode.dev>
topcheer
commented
Sep 16, 2026
topcheer
left a comment
Owner
Author
There was a problem hiding this comment.
复审通过 ✅
- 挂接点正确:guardToolOutput 截断分支内、advisory 包装前——spill 的是完整原始 content(截断前),恢复指针随 advisory 进上下文;失败静默回退纯截断(工具结果路径零影响)✓
- 安全面核销:全 mu 锁内(含 dir 重建分支);文件名双重防护(regex 清洗+filepath.Base);0600 权限;用户仓库零污染(os.TempDir 隔离)✓
- 资源边界完整:8KB 门槛(与 advisory 抑制阈值对齐)/20MB 单文件+中段标记(rune 边界 snap)/20 文件淘汰最旧/24h 崩溃残留 once 清理(ModTime 窗口足够长,不会误删活跃会话)✓
- 测试 6 项覆盖全关键面(门槛/全量写/notice/cap/淘汰/清洗)
- 一个非阻塞观察:mu.Lock 内做 I/O(WriteFile+prune ReadDir)——agent 工具执行串行下无实际争用,设计声明并发安全成立;若未来并行化再考虑缩小临界区
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
方向与动机
对标 2026 harness engineering 前沿实践(在线研究:LangChain《The Anatomy of an Agent Harness》、Anthropic《Effective Harnesses for Long-Running Agents》、zylos.ai harness design patterns 综述)。其中 Context Management 六策略之一的 Tool Output Offloading(工具结果卸载)在 ggcode 中缺失。
Gap 分析
guardToolOutput(context-fill-aware 截断)在上下文压力大时对大工具结果做 head+tail 截断,中间段被永久丢弃:实施
internal/agent/tool_output_offload.go:截断发生时将完整原始输出写入os.TempDir()/ggcode-spill-*/卸载文件read_file offset/limit或grep),模型可直接读取被省略的中间段agent.go在 guardToolOutput 截断分支挂接,spill 提示置于 tool-specific advisory 之前验证
go build -tags goolm ./...通过go test -tags goolm -count=1 -p 1 ./internal/agent/全部通过🤖 Generated with Claude Code
Co-Authored-By: ggcode noreply@ggcode.dev