Repository navigation
Subagents never apply queued ctx_reduce drops between the execute threshold and the force band #619
Description
What happens
A subagent session queues ctx_reduce drops and keeps growing. The drops stay in pending_ops and are never applied, even though the scheduler answers decision=execute on every pass.
Two subagent sessions from the same day, sampled at one moment:
| provider input per request | queued drops | tokens held by those tags | |
|---|---|---|---|
| session A | 349k | 107 | about 259k |
| session B | 343k | 150 | about 221k |
Applied, those drops would leave roughly 90k and 120k.
The log repeats the same pair of lines on every pass (22 and 37 times so far in the two sessions):
transform scheduler: percentage=39.3% inputTokens=342998 cacheTtl=30m lastResponseTime=... decision=execute
pending ops held — reason=no originating cache-bust opportunity; scheduler=execute, historianRunning=false
The only passes that ever applied anything were heuristics WILL RUN — reason=explicit_flush hours earlier, one of them right after a model switch.
Why
Queued drops are applied only on a reclaim ride: hasReclaimRide is hardFold || force || explicitFlush || publishedHistory (cache-busting-signals.ts:49, used at transform-postprocess-phase.ts:2018-2034). scheduler === "execute" is not one of them, which is the same point #524 ran into for the historian.
A subagent can reach almost none of those rides:
hardFoldneedsm0M1EnabledForFold, which requiresfullFeatureMode(transform-postprocess-phase.ts:1826-1829), andfullFeatureModeis!isSubagent(transform.ts:988-989).publishedHistoryneeds a historian run, andcanRunCompartmentsalso requiresfullFeatureMode(transform.ts:1108).- A session that gets an answer every few seconds never lets the 30m cache TTL expire, so an idle-expiry rebuild would not fire either.
explicitFlushcomes from/ctx-flushand a few other materialization triggers; in my logs those passes were rare.
That leaves force: usage at or above the force band, and either 95% or no earlier emergency sample. The band is max(85, threshold + 2) (escalation-bands.ts:15), where threshold is the effective execute threshold as a percentage of the window.
My config sets execute_threshold_tokens: { default: 260000 } and the window resolves to 872k. The threshold is then 29.8%, but the band stays at the 85% floor, so force starts at about 741k. Between 260k and 741k every turn is execute and nothing is reclaimed.
With a 272k window the same setting is clamped to 90% (244.8k) and the band is 92% (about 250k). The two points sat close together, so the gap did not show.
Impact
The subagent still gets the ctx_reduce guidance and every call answers Queued, so it spends turns on reductions that never land. On a provider that bills requests above a given context size at a higher rate (mine does above 272k), every turn of the session pays that rate until usage reaches the force band.
Environment
- magic-context 0.44.4 on OpenCode 1.18.34 (v1), subagents started through
task. - Code paths above checked against master
9fdaf2876. execute_threshold_tokens.default: 260000,protected_tokens: 16000, resolved window 872k.
Related and already closed: #524 (the historian skip waiting on drops that need a ride), #423 (emergency reclaim on Pi).
Possible directions
- Treat
scheduler === "execute"as a ride for subagent sessions. They have no historian or fold that could provide another one, andexecutealready means the scheduler decided a bust is acceptable. - When the execute threshold is configured in tokens, derive the force band from that threshold plus a margin instead of flooring it at 85%. This changes primary sessions too, so it needs more care than the first option.
It may also help if the ctx_reduce reply to a subagent said when queued drops will apply.
For now, /ctx-flush drains the queue once. I also capped limit.input for that model at 272k so the window resolves to 272k. By the arithmetic above the band then lands near the threshold; I have not observed it live yet.
Activity
magic-alfonso commentedon Oct 4, 2026
Thanks, confirmed. The analysis is right, and it contradicts our own design: subagents have no historian and no history fold, so for them an execute pass is meant to be the point where queued drops and other cleanup apply. That ride got lost, and drops wait for the force band instead. We're restoring it for subagent sessions, so queued drops land together on the next execute pass while primary sessions stay as they are. The fix will be checked on a real host with a token-configured threshold like yours. The force-band formula for token thresholds is a separate question; we'll look at it after this. Until then,
/ctx-flushis the right workaround.magic-alfonso commentedon Oct 8, 2026
Fixed in 0.46.0. Subagents now apply queued
ctx_reducedrops on execute passes, so drops no longer pile up between the execute threshold and the force band. This applies on OpenCode 1 and 2, Pi and Rust mode. Thanks for the report.To upgrade, quit every OpenCode, OpenCode 2 and Pi process first (they share one database, which moves to schema v95), then start them on 0.46.0. OpenCode 2 needs 2.0.22 or newer and updates plugins through
/plugins(ctrl+u) oropencode plugin update. Release notes: https://github.com/cortexkit/magic-context/releases/tag/v0.46.0The Pi package
@cortexkit/pi-magic-context0.46.0 is published; npm is still making it available, so if Pi still installs 0.45.0, try again a little later.