Skip to content

feat(agent): tool output offloading — persist truncated results to disk for recovery - #2446

Merged
topcheer merged 1 commit into
mainfrom
tool-output-offload
Sep 16, 2026
Merged

topcheer merged 1 commit into
mainfrom
tool-output-offload

Conversation

@topcheer

Copy link
Copy Markdown
Owner

方向与动机

对标 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 截断,中间段被永久丢弃:

  • 一个 200KB 的构建日志在 50% fill 时截到 40KB,~160KB 内容不可恢复
  • 恢复手段只有重跑工具——对确定性工具是浪费(重复 token/时间),对一次性副作用工具(不稳定测试、部署日志)则不可能
  • 现有 truncation advisory 建议重跑时用 grep/head 缩小范围,但对无法重跑的场景无效

实施

  • 新增 internal/agent/tool_output_offload.go:截断发生时将完整原始输出写入 os.TempDir()/ggcode-spill-*/ 卸载文件
  • 截断标记后追加 spill 提示(含绝对路径 + 恢复指令 read_file offset/limitgrep),模型可直接读取被省略的中间段
  • 安全设计:惰性创建目录(无截断零开销)、并发安全、<8KB 不卸载、单文件 20MB 上限、每会话最多 20 文件(淘汰最旧)、崩溃会话残留目录 24h 后清理;I/O 失败静默回退为纯截断,绝不影响工具结果路径
  • agent.go 在 guardToolOutput 截断分支挂接,spill 提示置于 tool-specific advisory 之前

验证

  • go build -tags goolm ./... 通过
  • go test -tags goolm -count=1 -p 1 ./internal/agent/ 全部通过
  • 新增 6 个单测:小内容跳过、中间段可恢复、路径提示、超大内容封顶、容量淘汰、文件名消毒

🤖 Generated with Claude Code

Co-Authored-By: ggcode noreply@ggcode.dev

…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 topcheer left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审通过 ✅

  • 挂接点正确: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 工具执行串行下无实际争用,设计声明并发安全成立;若未来并行化再考虑缩小临界区

CI 9/9 绿。可合并(顺序 #2445#2446)。

@topcheer
topcheer merged commit 1655992 into main Sep 16, 2026
9 checks passed
@topcheer
topcheer deleted the tool-output-offload branch September 16, 2026 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant