Skip to content

Compaction thrash loop: sub-agent with oversized working set loops for hours (463 compactions, ~31.8M tokens) with no circuit breaker; cache hits permanently drop to 0 after first compaction #352

Description

@danshapiro

Summary

A delegated sub-agent (explorer-type, spawned via delegate) whose working context exceeded the compaction threshold entered a stable pathological loop: compaction evicted its accumulated findings → the agent re-read the same files to recover them → context refilled → compaction fired again.

In the observed session the loop ran 463 compaction cycles over 108 minutes (roughly one every 14 seconds), consuming 31.8M input tokens ($41) to ultimately produce a two-sentence answer. No mechanism detected the lack of forward progress or halted the agent. The parent session simply saw a delegate call that hadn't returned yet.

The task itself was trivial (determine what icon files a repo needs); the actual implementation work after the explorer returned took ~4 minutes.

Observed behavior (from the sub-session's events.jsonl)

  • 1,771 tool calls in one sub-session: 887 file reads, 652 bash commands, 169 greps — with the same handful of files re-read dozens of times each
  • 475 provider round-trips
  • 463 context compactions in 108 minutes
  • ~31.8M input tokens consumed (~$41 at list price) for a task whose useful output was two sentences
  • Prompt cache permanently collapsed: after the first compaction, cache_read_tokens dropped to 0 and never recovered — every subsequent request was a full uncached re-send. This is the cost multiplier: the same work with healthy cache hits would have been roughly $1.
  • The loop terminated only by luck: the agent happened to emit its final answer during a window where enough context survived compaction.

Reproduction conditions

The trigger is any delegated agent whose minimum working set exceeds the post-compaction context budget:

  1. Delegate a broad investigation (here: "investigate these two repositories" in a single explorer delegation — one Python CLI repo plus one Rust codebase)
  2. The agent issues 4–8 parallel file reads per step; context balloons past the compaction threshold quickly (observed: ~238K tokens against a ~203K budget within the first 90 seconds)
  3. Compaction fires and evicts the older half of the findings
  4. The agent no longer remembers what it read, so it re-reads the same files (the same README, pyproject.toml, build script, and source files recur throughout the trace)
  5. Context refills; go to 3

The loop is self-sustaining — there is no state from which it naturally recovers, because the agent's working set never fits in the post-compaction budget.

Why this is a platform bug and not just a bad delegation

Yes, the delegation was over-broad (two repos in one explorer), and narrower scoping avoids the problem. But the platform behavior is the issue:

  • The system has a stable failure attractor with unbounded wall-clock time and unbounded cost, and no detection or escape mechanism.
  • It fails silently from the parent session's perspective — no warning, no progress signal, no cost signal, for nearly two hours.
  • The compaction ↔ cache interaction multiplies the damage: once compaction rewrites history, cache hits go to zero for the remainder of the sub-session, so every thrash cycle is billed at full context price.

Expected behavior / suggested mitigations

Any of these would bound the damage:

  1. Compaction-loop circuit breaker — if compaction fires more than N times (e.g. 5) in a sub-session without forward progress, abort the agent and return partial findings with an explanatory note to the parent.
  2. Duplicate-work detection — an agent re-reading the same file it has already read multiple times post-compaction is a strong thrash signal; surface it or count it toward the breaker.
  3. Cache-health canarycache_read_tokens: 0 sustained across many consecutive requests indicates the session is thrashing and will not recover on its own.
  4. Budget ceilings on delegated agents — configurable wall-clock / token / cost caps per sub-session so the worst case is bounded regardless of failure mode.

Possible companion issue

Even outside a thrash loop, "the first compaction permanently kills prompt-cache hits for the remainder of the sub-session" may deserve its own investigation as a cost bug, if that behavior is general and not specific to this failure mode.

Diagnostics

The signature is easy to spot in a sub-session's events.jsonl:

  • compaction events at a regular, rapid cadence (every ~10–20s)
  • cache_read_tokens falling off a cliff to 0 immediately after the first compaction and staying there
  • the same file paths recurring in read-tool calls throughout the trace

Environment

  • Root session on an OpenAI GPT-5-class model via the OpenAI provider; failure occurred inside a delegated explorer sub-session
  • Linux (WSL2), amplifier-app-cli

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions