aaif-goose / aaif-goose/goose

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

Ouverte
#11,072 6 commentaires 0 réactions 1 personne assignée Réclamée par @filipkujawa Voir sur GitHub
Langage dominant
Rust
Étoiles
54.2k
Forks
6.2k
Merge moyen
3 j 4 h
PR mergées (30 j)
240

Description

**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.

Guide de contribution

Ouvrir le guide de contribution

Piste de recherche

The bug is in two files: `crates/goose/src/agents/agent.rs:2049` and `crates/goose/src/agents/state_machine/ops_compaction.rs:235`. Start by understanding the auto-compaction logic and the `EffectiveRole` enum. The fix is to allow compaction checks at `EffectiveRole::Tool` boundaries within a turn. Write a test that triggers compaction mid-turn using a long tool loop and verify the token count stays under the threshold.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
rust
Domaine
ai-infra-agents
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
Active
Clarté
Clairement spécifiée
Accessibilité débutants
65/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.