aaif-goose / aaif-goose/goose

Auto-compaction is only evaluated at turn boundaries, so a long tool loop reaches the context limit unchecked

Offen
#11,072 6 Kommentare 0 Reaktionen 1 zugewiesene Person Beansprucht von @filipkujawa Auf GitHub ansehen
Vorherrschende Sprache
Rust
Sterne
54.2k
Forks
6.2k
Ø Merge
3 T. 2 Std.
Gemergte PRs (30 T.)
262

Beschreibung

**Describe the bug**

Auto-compaction is only evaluated at a user-turn boundary, so tool output accumulated inside a turn is never re-examined. A turn that begins under the threshold can run all the way to the provider's context limit without a single check.

| path | site | gate |
|---|---|---|
| legacy | `crates/goose/src/agents/agent.rs:2049` | `check_if_compaction_needed` runs once, before the reply stream |
| state machine | `crates/goose/src/agents/state_machine/ops_compaction.rs:235` | `not_applicable()` unless `last_effective_role == EffectiveRole::User` |

This was noted as a secondary observation in #11049 and deferred. It is not theoretical — it is reproducible in a live session, and it survives a correct context limit.

**Observed**

A session with a correctly resolved `context_limit` of 49,152 and `GOOSE_AUTO_COMPACT_THRESHOLD=0.35` (trigger ≈ 17,203). Auto-compaction fired six times at turn boundaries and worked. Then one tool-heavy turn, from `usage_ledger`:

```
16:09:29 17,513 in is_compaction=1 -> compacted to 6,912
16:29:29 17,189 in past the 17,203 trigger, nothing fires
16:32:50 24,560 in
16:42:15 40,783 in
16:45:14 49,120 in + 32 out = 49,152 at the server's hard ceiling
```

Thirty-plus consecutive provider calls in a single turn, no compaction check in any of them. Note the last row's 32 output tokens: at that point the model has almost no room left to answer, and the next request is rejected.

**To Reproduce**

1. Configure any provider whose context limit is small enough to reach in one turn.
2. Set `GOOSE_AUTO_COMPACT_THRESHOLD` well below 1.0.
3. Ask for work that drives a long sequence of tool calls without returning to the user.
4. Watch `usage_ledger`: tokens climb past `threshold * context_limit` and keep going; `is_compaction` stays 0 until the turn ends or the provider rejects the request.

**Expected behavior**

The threshold is re-evaluated during a turn, once tool responses have landed, so a long tool loop compacts instead of walking into the context limit.

The safe point matters: compacting between a tool request and its response would hide the request from the model and orphan it. `EffectiveRole::Tool` — a user-role message carrying tool responses — is the natural boundary, and `Assistant` must stay excluded.

**Please provide the following information**
- **OS & Arch:** macOS 15 (Darwin 25.5.0) arm64
- **Interface:** Desktop (ACP) and CLI
- **Version:** 1.45.0
- **Provider & Model:** custom OpenAI-compatible (llama.cpp-derived, `--ctx 49152`)

**Additional context**

Related but distinct:
- #11048 / #11050 — classifying the resulting 400 so it is recoverable. That makes the overflow survivable; it does not stop it happening.
- #11049 — resolving the context limit correctly. Necessary, and not sufficient: the session above already had the right limit.

`AGENTS.md` requires both agent paths to change together, which is achievable in one edit per path. I have a working branch and will attach it as an RFC PR; it needs a test that exercises a mid-turn compaction end to end before it should be considered mergeable.

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.