advisor() tool inflates reported input tokens by forwarding full transcript, triggering premature auto-compaction on extended context models

Status Open
Reported on v2.1.111
Maintainer reply None cached
Activity 15 comments · opened Apr 25, 2026

Summary

When advisor() is called, the full conversation transcript is forwarded to a second model (currently claude-opus-4-7). The token usage from both the main executor and the advisor sub-inference are summed in the top-level usage fields. If Claude Code's auto-compaction logic uses these summed totals, the advisor call effectively doubles the apparent context usage, triggering compaction when the main model's actual context is only ~50% full.

Reproduction

  1. Start a Claude Code session with claude-opus-4-6[1m] (1M context)
  2. Work normally until the main context reaches ~400K-500K input tokens
  3. Call advisor()
  4. Observe: auto-compaction fires immediately after the advisor call returns

Evidence from session JSONL

Session ID: c3a29188-290f-4af2-be48-8f6fb6929111
Model: claude-opus-4-6[1m]
Project: CriticalSkip

Token progression at the compaction boundary

| JSONL line | Total reported input | Notes |
|-----------|---------------------|-------|
| 1972 | 513,354 | Normal turn, main context only |
| 1979 | 1,028,789 | advisor() called — reported total doubled |
| 1994 | — | "Conversation compacted" system message |
| 2012 | 35,693 | Post-compaction context (wiped to ~36K) |

Iteration breakdown for the advisor turn (line 1979)

{
  "input_tokens": 4,
  "cache_creation_input_tokens": 1731,
  "cache_read_input_tokens": 1027054,
  "iterations": [
    {
      "type": "message",
      "input_tokens": 3,
      "cache_read_input_tokens": 513353,
      "cache_creation_input_tokens": 348,
      "output_tokens": 35
    },
    {
      "type": "advisor_message",
      "model": "claude-opus-4-7",
      "input_tokens": 701354,
      "cache_read_input_tokens": 0,
      "cache_creation_input_tokens": 0,
      "output_tokens": 5672
    },
    {
      "type": "message",
      "input_tokens": 1,
      "cache_read_input_tokens": 513701,
      "cache_creation_input_tokens": 1383,
      "output_tokens": 544
    }
  ]
}

Key observation: The main model's actual context was 513-515K tokens (iterations 1 and 3). The advisor sub-inference consumed 701K tokens (iteration 2 — the full transcript forwarded uncached). The top-level cache_read_input_tokens reports 1,027,054 — the sum across all iterations — making it appear the context is at 1M when only half is actually used by the executor.

The math

  • Main executor context: ~513K tokens (well within 1M window)
  • Advisor receives full transcript: ~701K tokens (separate model, separate inference)
  • Reported total: ~1,028K tokens (sum of both)
  • Auto-compaction threshold: likely ~95% of 1M ≈ 950K
  • Result: compaction fires at 513K actual context because 1,028K > threshold

Expected behavior

Advisor sub-inference tokens should not count toward the auto-compaction threshold. The advisor is a separate model call with its own context window. The executor's context at 513K is well within the 1M budget and should not trigger compaction.

Actual behavior

The summed total (executor + advisor) exceeds the compaction threshold, and auto-compaction fires immediately. The session loses ~500K tokens of working context unnecessarily.

Impact

  • On extended context models (1M): Any advisor call past ~400K main context will trigger compaction, since 400K main + ~550K advisor = ~950K ≈ threshold
  • Effectively halves usable context: The 1M context window becomes ~400-450K when advisor is used, because the remaining ~550K is reserved for the advisor's copy of the transcript
  • Inconsistent: Early-session advisor calls work fine. Late-session calls compact. Users experience this as random/intermittent compaction
  • Counterproductive: The advisor is most valuable late in a session (complex decisions with full context), but that's exactly when it triggers compaction and destroys the context it was supposed to help with

Workaround

Setting CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=98 and/or using a PreCompact hook that blocks auto-compaction:

{
  "hooks": {
    "PreCompact": [{
      "hooks": [{
        "type": "command",
        "command": "bash -c 'INPUT=$(cat); TRIGGER=$(echo \"$INPUT\" | python3 -c \"import sys,json; print(json.load(sys.stdin).get(\\\"trigger\\\",\\\"unknown\\\"))\" 2>/dev/null); [ \"$TRIGGER\" = \"auto\" ] && echo \"{\\\"decision\\\":\\\"block\\\"}\" && exit 2; exit 0'",
        "timeout": 3
      }]
    }]
  }
}

This blocks all auto-compaction and relies on manual /compact. Not ideal but prevents the advisor from triggering premature compaction.

Related issues

  • #34332 — Opus 4.6 (1M context): autocompact triggers at ~76K tokens
  • #50204 — Auto-compact triggers prematurely with extended context models
  • #15377 — Conversations compacting prematurely at ~65% token capacity
  • #49994 — Sessions using advisor() become permanently unrecoverable (expired encrypted payloads)
  • #42647 — High token burn due to redundant context resubmission in compaction pipeline

Suggested fix

When calculating context usage for the auto-compaction threshold, use only the executor's input_tokens + cache_read_input_tokens + cache_creation_input_tokens from type: "message" iterations. Exclude type: "advisor_message" iterations from the calculation. The advisor tool documentation already states that "top-level max_tokens applies to executor output only" and that "the advisor's tokens do not draw from any task budget applied to the executor" — the compaction logic should follow the same principle.

Environment

  • Claude Code version: 2.1.111
  • Model: claude-opus-4-6[1m]
  • Advisor model: claude-opus-4-7
  • Platform: Windows 10 Pro
  • Settings: advisorModel: "opus", effortLevel: "medium"

View original on GitHub ↗

13 Comments

kerneltoast · 4 months ago

Ditto. I have this exact same issue and even filed an issue (#55702) that turned out to be a duplicate of this one. I'm using Linux with Opus 4.6 [1M] as my main model and Opus 4.7 as the advisor model.

kerneltoast · 4 months ago

I have auto-compaction disabled. My workaround has been to /rewind to right before the advisor call and ask Claude to generate a session handoff file with the next instruction saying to call the advisor. Then I /clear and run @SESSION_HANDOFF.md.

kerneltoast · 3 months ago

This bug still occurs on v2.1.126.

Yesterday I started a new session on v2.1.126 with Opus 4.7 and gave it a single complex prompt using a session handoff file. The context window limit was reached before Claude could completely finish my prompt, and it happened because Claude invoked the advisor at around 480K context tokens which triggered this bug; thus, the context size doubled and my prompt died due to hitting the context limit.

Since my session was literally just a single prompt, I couldn't /rewind back before the advisor call to salvage my session.

Please update the tags to specify that this bug isn't limited to Windows, as I experience this bug in Linux.

The bug is 100% reproducible. It really diminishes the value of the advisor feature.

kerneltoast · 3 months ago

This issue still occurs on v2.1.140. Please, kindly prioritize fixing it as it significantly limits the advisor's potential.

AttacktheDPoint-com · 3 months ago

still happening...

kerneltoast · 3 months ago

Still happens on v2.1.148, and it is still 100% reproducible. I even got a weird one today where 3 back-to-back Advisor calls caused my session to hit the 1M context limit even though I started with 25% of the context window full. So multiple consecutive Advisor calls can bust a session even when you're well below 50% of context filled.

genesiscz · 3 months ago

More info — independently reproduced on claude-opus-4-7[1m], with two facets worth adding.

Hit this on Claude Code 2.1.150 / macOS / claude-opus-4-7[1m]. A single advisor() call took the statusline from ~406K → 1170k/1000k (117%), +782k in one turn. Iteration-level data confirms your diagnosis exactly, and adds (1) a timeout-driven ×3 and (2) confirmation it's display-only — the prompt cache and the executor's real context are untouched (the #17959 symptom).

Same accounting, confirmed

The advisor turn's usage:

// top-level: input=2977  cache_creation=10421  cache_read=1156259  output=3604
"iterations": [
  { "type": "message",         "cache_read_input_tokens": 381449, "cache_creation_input_tokens": 5956, "output_tokens": 2946 },
  { "type": "message",         "input_tokens": 2973, "cache_read_input_tokens": 387405, "output_tokens": 218 },
  { "type": "advisor_message", "model": "claude-opus-4-7", "input_tokens": 395834, "cache_read_input_tokens": 0, "output_tokens": 6026 },
  { "type": "message",         "cache_read_input_tokens": 387405, "cache_creation_input_tokens": 4465, "output_tokens": 440 }
]

381449 + 387405 + 387405 = 1156259 = the top-level cache_read exactly. So the top-level cache_read is Σ cache_read over the executor (type:"message") sub-iterations, and each advisor() invocation adds one executor re-read of the same cached context. General rule:

N advisor invocations in a turn ⇒ the executor's context is counted (N+1)× in the top-level cache_read.

The advisor's transcript forward is the separate advisor_message (input_tokens=395834, uncached) and is not in the top-level cache_read. Control from the same session — a successful, single advisor call on a ~113K context reported cache_read = 113080 + 114484 = 227564×2, matching your 513K→1028K.

Facet 1 — execution_time_exceeded → auto-retry → ×3 (not ×2)

My turn has two server_tool_use{name:"advisor"} blocks. The first returned:

{ "type": "advisor_tool_result_error", "error_code": "execution_time_exceeded" }

…on a ~385K transcript (the reviewer can't finish within its server-side budget), so it auto-retried. Two invocations → three executor message iterations → ×3 (1,156,259), not ×2. The timed-out attempt left no billed advisor_message iteration but cost ~8 min wall-clock and forced the extra re-read at iteration [1]. So on large contexts the inflation multiplier can exceed 2.

Facet 2 — the inflation is display-only; cache and real context are untouched

The 117% does not reflect real context growth. The next turn read cache_read=387405 with cache_creation=7167 — a normal incremental, so the prompt cache stayed fully intact and the executor's real context never left ~385K. The inflated figure is a pure accounting artifact of the summed cache_read, not a real approach to the window limit — exactly the #17959 symptom (context_window.used_percentage not matching the real/internal figure).

The harm this issue raises is that the same summed figure also feeds the auto-compaction trigger, so a complete fix needs both the statusline and the auto-compaction trigger to use the executor's real context and exclude server-tool sub-iteration re-reads of already-cached content.

Honest cost (so the multiplier isn't misread)

  • 1,156,259 is the same ~385K counted 3× at cache_read rate (~0.1×) — cheap (~115K full-rate-equiv).
  • The genuine extra is the uncached advisor_message forward: ~396K full-rate input + 6K output, once.
  • Net real cost ≈ 396K, not 1170K — but it isn't free, and the timeout wasted a full ~8-min attempt.

Environment: Claude Code 2.1.150, claude-opus-4-7[1m], Anthropic API, macOS, Ghostty/zsh.

kerneltoast · 3 months ago

Still happens on v2.1.156. I ran into it with Opus 4.8 (1M) today.

junaidtitan · 2 months ago

The advisor() double-count is nasty because the usage fields in the JSONL show the inflated sum, which is what CC's auto-compact trigger reads — so from CC's perspective you've "hit 1M" even though the actual transcript is half that.

cozempic (github.com/Ruya-AI/cozempic) helps in two ways here, though I want to be honest about what it can and can't do: it doesn't fix the double-counting in CC's token reporting. What it can do:

  1. cozempic current --diagnose reads the raw per-message token counts directly from the JSONL and gives you the real context footprint independent of the running usage total. If you're seeing 1M reported but the actual accumulated transcript is ~500K, the diagnose output will show the discrepancy — which at minimum tells you whether you're hitting a real limit or a counting bug.
  1. The prune side: cozempic strips the bulky advisor/subagent turn outputs (large responses, tool output blocks) from the JSONL to reduce the real baseline. So when an advisor call fires and doubles the apparent count, there's slack in the real transcript that absorbs it.

pip install cozempic / pipx install cozempic. Given this bug has been reproducing on 4.6, 4.7, and 4.8 across multiple people — would be curious whether the diagnose numbers match what you're seeing or surface something different.

kerneltoast · 2 months ago

Still not fixed.

alexrojco · 2 months ago

An abysmal bug and still an issue 2 months later!

kerneltoast · 2 months ago

Still occurs on v2.1.196.

johnsfleming · 1 month ago

Same root cause without advisor() — plain message continuation/retry iterations also trigger it

I hit the same premature auto-compaction mechanism described here, but with no advisor call anywhere in the session — every entry in the iterations arrays is "type": "message". This suggests the fix belongs in the compaction accounting (it should use the actual prompt size of the last/largest single call, not the summed top-level usage), not in the advisor tool specifically.

Environment

  • Claude Code 2.1.217, darwin
  • Model: claude-sonnet-5 (no 1M variant, no advisor, no custom compaction overrides)
  • Session: a398982a-2ad8-48a5-9560-95c2b60fc539 — 44 minutes, 3 auto-compactions

Evidence from the session JSONL

Each compact_boundary's preTokens matches the summed multi-iteration usage of the preceding assistant turn, roughly 2x the real context of the largest single API call:

| Compaction | preTokens | Largest single iteration (real context) | Inflation |
|---|---|---|---|
| #1 (auto) | 269,302 | ~131k (in=709, cache_read=130,705) | ~2.0x |
| #2 (auto) | 167,697 | ~65k (in=55,291, cache_read=9,629 — cache-miss full resend) | ~2.6x |
| #3 (auto) | 171,976 | ~87k (in=640, cache_read=84,035) | ~2.0x |

Iteration breakdown for the turn preceding compaction #2 (top-level usage is the sum of all three calls):

{
  "input_tokens": 55682, "cache_read_input_tokens": 107212, "cache_creation_input_tokens": 3367,
  "iterations": [
    { "type": "message", "input_tokens": 2,     "cache_read_input_tokens": 47108, "cache_creation_input_tokens": 3367 },
    { "type": "message", "input_tokens": 389,   "cache_read_input_tokens": 50475, "cache_creation_input_tokens": 0 },
    { "type": "message", "input_tokens": 55291, "cache_read_input_tokens": 9629,  "cache_creation_input_tokens": 0 }
  ]
}

The third iteration is a cache-miss retry that re-sent the conversation uncached (~55k real context), yet the summed total (~166k) is what the compaction trigger saw. Compaction #2 fired when the window was roughly a third full.

Impact: the three compactions burned ~8.5 minutes of a 44-minute session (durationMs 263,741 / 109,517 / 136,274) and repeatedly discarded working context that was nowhere near the limit. Because retries/continuations can happen on any model, this isn't limited to extended-context models or advisor users.

Showing cached comments. Read the full discussion on GitHub ↗