[Bug] Session limit warning not surfaced to agent; background workflows continue consuming quota after threshold

Status Open
Reported on v2.1.209
Maintainer reply None cached
Activity 5 comments · opened Jul 14, 2026

Bug Description
Title: Session limit warning is not actionable by the agent — background workflows keep burning quota after the warning appears

What happened

I ran a task with /effort ultracode. Claude launched a Workflow with 14 subagents (7 explorers + 7 adversarial verifiers) to produce an
architecture document. It consumed ~1.6M subagent tokens and exhausted my entire session limit in a single prompt.

Partway through, the terminal showed the red banner: You've used 99% of your session limit · resets 2:10pm. I also told the agent in plain
language that the session was about to run out.

The agent kept waiting for the background subagents to finish anyway. It replied that nothing would be lost and wrote a "continuation note"
instead of stopping the workflow and assembling the deliverable with the ~9/14 results it already had.

Why this is a problem

  1. The session-limit warning is UI-only. It's rendered in the terminal chrome but is never surfaced to the model — not as a message, not as

a hook event, not as readable state. The agent is structurally blind to the one signal that should make it land the plane.

  1. There is no way to intercept it. No hook fires on quota thresholds, and there is no local command or API surface that reports remaining

session quota, so users can't build their own mitigation.

  1. Background workflows are not aborted. Once the limit is near (or hit), in-flight Workflow/subagent runs keep consuming quota with no way

for the main agent to react.

Expected behavior

  • The session-limit warning (e.g. >80%, >95%) should be surfaced to the agent as an actionable signal, so it can stop background work and

write out whatever deliverable exists.

  • Approaching/hitting the limit should abort or pause in-flight background workflows rather than letting them drain the remaining quota.
  • Ideally, expose a hook event (e.g. SessionLimitWarning) so users can define their own "land the plane" behavior.

Environment

  • Claude Code CLI, macOS (darwin 25.5.0)
  • Session was running Fable 5 while /effort ultracode was active — worth noting: ultracode explicitly tells the model "token cost is not a

constraint", which encourages exactly the kind of large fan-out that then nukes the session limit with no feedback loop.

Impact: an entire session's quota spent on one prompt, with the agent unable to react to the warning the user could plainly see on screen.

Environment Info

  • Platform: darwin
  • Terminal: vscode
  • Version: 2.1.209
  • Feedback ID: 5962dd77-a5e4-482d-ad05-c7a044e96d93

Errors

[]

View original on GitHub ↗

4 Comments

eltonylfgi-blip · 1 month ago

This does not solve in-flight Workflow cancellation, but there is a local pre-flight gate for the next run. I maintain usage-guard v0.3.0; its status-line shim snapshots Claude Code's own rate_limits locally, and:

node hooks/usage-guard-check.mjs --max-5h 80 --max-weekly 85 && my-agent

exits 1 before the agent starts when either threshold is crossed. Missing or stale data fails open; zero dependencies and no network calls: https://github.com/eltonylfgi-blip/claude-code-usage-guard

Important limitation: it cannot interrupt the 14 subagents already in flight, so the native SessionLimitWarning / cancellation hook requested here is still needed.

Disclosure: I'm the author.

davidsh7 · 1 month ago

Thanks read through usage-guard-check.mjs, it's clean and does what it says. Worth flagging for others in this thread though that a pre-flight gate doesn't cover the core ask: cancelling subagents already in flight. The native SessionLimitWarning / cancellation hook is still what's needed here.

davidsh7 · 1 month ago

Following up with something concrete, since I ended up building the workaround locally.

Credit where it's due: your two-piece design (status-line as sensor, hook as actuator) was the right starting point, and I only understood why it has to be shaped that way after reading your README. It turns out to be the only possible shape given how the data is exposed rate_limits reaches statusLine on stdin and nothing else. I re-verified that against the full hook input spec: no hook event receives quota data, so snapshotting to disk isn't a workaround, it's the only bridge available.

Two things I found on top of that, both from the docs rather than from anything clever on my part:

  1. SubagentStart exists but is "context only, no blocking or decision control", so it can't gate spawns. What does work is

PreToolUse with matcher Agent|Workflow returning:

   {"hookSpecificOutput":{"hookEventName":"PreToolUse",
    "permissionDecision":"deny","permissionDecisionReason":"..."}}

That moves the same sensor data from pre-flight to per-spawn. It still can't cancel subagents already in flight, your stated
limitation holds, but in a large orchestration spawns are staggered, so it stops the bleeding partway through instead of
only before the run.

  1. A trap worth flagging for anyone wiring this up: statusLine triggers go quiet while the main session is idle, including while

a coordinator waits on background subagents. The snapshot freezes during exactly the long orchestration you're guarding against, and
a staleness check then fails open at the worst possible moment. I hit this in my own implementation before noticing it in the docs.
"refreshInterval": 30 on statusLine keeps the snapshot warm.

None of this closes the ask in this issue. There's still no way to interrupt work already in flight, and no SessionLimitWarning event
exists today. PreToolUse-on-Agent just covers more of the gap than a pre-flight gate can.

eltonylfgi-blip · 1 month ago

This is really helpful, thanks for taking the time to dig in and write it up. The idle-coordinator trap is the part that stings: a snapshot that freezes during the exact long orchestration it's meant to guard is the worst case, and I'd missed that refreshInterval: 30 keeps it warm. That's going straight into the status-line setup docs, credited to you. Same with the PreToolUse + Agent|Workflow deny recipe as an optional per-spawn gate. You're right that it stops the bleeding partway instead of only pre-flight. And agreed, neither of us closes the actual ask here: nothing cancels in-flight subagents, so the native SessionLimitWarning / cancellation hook is still the real fix. Appreciate you reading the code properly, not many do.

Showing cached comments. Read the full discussion on GitHub ↗