Repository navigation
Show how much subagent tool-call context ctx_reduce cannot reclaim #643
Description
Short description
In long subagent tool loops, part of the tool-call context stays as skeleton_real arcs that ctx_reduce cannot drop, and neither the agent nor the user can see how large that part is. A subagent can sit above execute_threshold_tokens with nothing left to reduce. I suggest reporting the retained amount in /ctx-status and in the nudges. The numbers below may also help size what the signed-thinking harness listed in the v0.46.1 notes could recover.
What problem does this solve?
#619 fixed queued drops never being applied in subagent sessions. What remains is a floor the agent cannot lower. As I read shared/tag-transcript.ts (requiresToolArcSkeleton), tool calls in a message that carries native thinking blocks are kept as skeletons with their real arguments, which I assume is so the signed blocks stay valid. That fits Anthropic's rule that thinking blocks go back "alongside the tool_use block it accompanied", and that a tool-use loop is one assistant turn (Preserving thinking blocks). A subagent is usually one prompt followed by a long tool loop, so none of its history counts as an earlier turn.
I found nothing that separates this part from the rest: the Tool Calls row in shared/status-view.ts is a single total.
Numbers from my local context.db (Magic Context 0.46.1, OpenCode 1.18.35, execute_threshold_tokens: 262000). Across 111 subagent sessions with at least 20 dropped tool tags, the arguments kept by skeleton_real arcs were:
| Percentile | Tokens kept |
|---|---|
| p50 | 0 |
| p75 | ~4.5k |
| p90 | ~24k |
| max | ~165k |
Three sessions keep more than 50k and two keep more than 100k. The largest is a Claude Opus 5.5 subagent with 1,008 skeleton tags and ~165k tokens of kept arguments. Its tool_call_tokens is ~225k, it has no pending ops left, and its last input was ~372k tokens against the 262k threshold.
Thinking does not explain every skeleton: across all subagent sessions in the database, 2,037 of 5,531 skeleton-dropped tool tags have no reasoning tokens recorded in tags. I don't know whether that means no thinking block or an unrecorded one.
Proposed solution
- Split the retained part from the reclaimable part in the
Tool Callsrow of/ctx-status. When the retained part alone is above the execute threshold, say so in thectx_reducereply or the nudge, so the agent stops trying to reduce and the user can see why. - No change to what gets dropped is requested. The v0.46.1 notes list "A live test harness for Anthropic signed-thinking edits, seeded from a recorded request", which I read as you already looking at how the API treats edits to signed thinking. If it accepts removing a whole arc together with its thinking, subagent loops are where that would pay off most, and the table above gives a rough size. If it does not, the visible floor still helps choose a threshold.
Alternatives considered
- Raising
execute_threshold_tokensabove the floor defeats the cap it was set for. - Starting a fresh subagent when the floor nears the threshold is the only workaround I have.
Area
OpenCode plugin
Additional context
The figures come from one local database, so they say nothing about how common this is.
Activity
magic-alfonso commentedon Oct 9, 2026
Thanks, this is a valid finding and the numbers helped. Rather than only showing the retained part, we're going to reduce it.
When a recent tool call is dropped, Magic Context keeps a small skeleton of it (the call with its real arguments, and the result replaced by a placeholder) so the model can still see what it did. That choice is made once, at drop time, and today it's replayed for the rest of the session. A skeleton is never turned into a full removal later, even after it's far from the end of the conversation. That's why skeletons accumulate in long tool loops.
The change: on a pass that already rebuilds the cached prefix (crossing the execute threshold, a history fold,
/ctx-flush, or the 85% force band), skeletons that are no longer among the newest 20 tool calls become full removals. Those passes rewrite the prefix anyway, so this costs no extra cache.Skeletons kept because their message carries Anthropic thinking blocks are a separate case. Anthropic only accepts certain edits to signed thinking, and a subagent's whole tool loop counts as one assistant turn, where thinking can't be modified at all. We're checking exactly which of those can be removed safely before changing anything there. Your observation that many skeletons have no recorded reasoning tokens is part of that check.
I'll update this issue when the design is done and again when it ships.
null-axiom commentedon Oct 22, 2026
Adding a data point from OpenCode 2 (Magic Context 0.49.13–0.49.16, OpenCode's own
compaction.autooff as recommended).Long implementation subagents here peaked at 623K and 305K tokens of context in single runs. In the 623K run,
ctx_reducebrought it back down only to about 200–350K, and it climbed again from there; most of that run's cost was cache reads of this context on every step.The skeleton change above should lower that floor. The other part is that a subagent has nothing that folds its history at all: on overflow Magic Context records "subagents cannot run historian" and returns, so with native compaction off, the only lever is
ctx_reduceon individual items. Would either of these fit once the skeleton work lands?