Skip to content

fix(agent): compact at end of a final-answer turn to prevent context overflow#4079

Merged
esengine merged 1 commit into
main-v2from
fix/compact-at-end-of-final-answer-turn
Jun 12, 2026
Merged

fix(agent): compact at end of a final-answer turn to prevent context overflow#4079
esengine merged 1 commit into
main-v2from
fix/compact-at-end-of-final-answer-turn

Conversation

@esengine

Copy link
Copy Markdown
Owner

Found while stress-testing long multi-turn sessions with repeated heavy compaction.

The bug

maybeCompact runs only after a tool batch (and in the readiness/empty-final retry paths). A turn that ends with a clean final answer (no trailing tool call) returns without compacting. So when a turn ends with a large context, it carries into the next turn un-folded; across a multi-turn session the context accumulates until a request exceeds the model's hard limit and the provider returns 400 (maximum context length) — the session then breaks (every --continue re-sends the over-limit context).

Most acute for turns that add large content but call no tools (pasting big input, pure Q&A over a large context).

Repro (real provider)

6-turn session, each turn fed a ~380k-token batch, context_window 700k:

  • turn 3 reached ~766k and ended with a final answer → no compaction
  • turn 4 then sent ~1.16M tokens → 400: maximum context length is 1048565 tokens, requested 1158757 → session dead

After the fix, the same session runs to completion (9 folds, no 400).

The fix

Call maybeCompact on the final-answer path too. It's a no-op below the trigger (normal turns keep their warm cache); it folds only when the context is already over the threshold — exactly when the next turn would otherwise overflow.

Test

TestRunCompactsAfterFinalAnswer: a final-answer turn over the trigger must compact. Verified it fails without the one-line change and passes with it. Full internal/agent suite green.

…overflow

A turn that ends with a final answer (no trailing tool batch) skipped
compaction entirely — maybeCompact ran only after tool batches and in the
retry paths. So a large context carried into the next turn un-folded, and
across a multi-turn session it accumulated until the next request exceeded the
model's hard context limit and the provider returned 400, breaking the session.

Compact at the end of the final-answer path too. It is a no-op below the
trigger, so normal turns keep their warm cache; it folds only when the context
is already over the threshold — exactly when the next turn would risk overflow.
@esengine esengine requested a review from SivanCola as a code owner June 12, 2026 00:42
@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development agent Core agent loop (internal/agent, internal/control) and removed v2 Go rewrite (1.x) — main-v2 branch, active development labels Jun 12, 2026
@esengine esengine merged commit 922f7b1 into main-v2 Jun 12, 2026
14 checks passed
@esengine esengine deleted the fix/compact-at-end-of-final-answer-turn branch June 12, 2026 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant