Skip to content

Subagents never apply queued ctx_reduce drops between the execute threshold and the force band #619

Closed

Description

@dhaern

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:

  • hardFold needs m0M1EnabledForFold, which requires fullFeatureMode (transform-postprocess-phase.ts:1826-1829), and fullFeatureMode is !isSubagent (transform.ts:988-989).
  • publishedHistory needs a historian run, and canRunCompartments also requires fullFeatureMode (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.
  • explicitFlush comes from /ctx-flush and 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

  1. Treat scheduler === "execute" as a ride for subagent sessions. They have no historian or fold that could provide another one, and execute already means the scheduler decided a bust is acceptable.
  2. 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

  1. magic-alfonso commented on Oct 4, 2026

    @magic-alfonso

    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-flush is the right workaround.

  2. magic-alfonso commented on Oct 8, 2026

    @magic-alfonso

    Fixed in 0.46.0. Subagents now apply queued ctx_reduce drops 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) or opencode plugin update. Release notes: https://github.com/cortexkit/magic-context/releases/tag/v0.46.0

    The Pi package @cortexkit/pi-magic-context 0.46.0 is published; npm is still making it available, so if Pi still installs 0.45.0, try again a little later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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