[Feature Request] Real-time steering: priority message channel for redirecting Claude mid-execution

Open 💬 27 comments Opened Mar 3, 2026 by idiolect-ai

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

When Claude Code is executing a complex, multi-step workflow (pipelines, multi-file refactors, coordinated subagent work), the user has no way to steer the work mid-execution. Messages typed during processing are queued and delivered at the next turn boundary — by which point Claude may have completed significant work in the wrong direction.

The existing interrupt mechanism (Escape) is destructive: it discards in-progress work and forces a restart. What's missing is a non-destructive steering channel — a way to say "pivot to file X instead" or "skip the tests, focus on the implementation" without losing what's already been done.

Related issues address adjacent problems:

  • #29224 addresses acknowledging queued messages (side-channel responses)
  • #29490 addresses detecting stop-words to pause execution
  • #26388 addresses temporal misinterpretation of queued messages

This request addresses a different need: intentional mid-execution redirection — giving the user the ability to change the agent's course while it's working, without interrupting or restarting.

Why This Matters

As Claude Code is used for increasingly autonomous, longer-running workflows — agent teams, multi-step pipelines, large refactors — the gap between "fully autonomous" and "user-steerable" becomes a real problem. Users who delegate complex work need to be able to course-correct when they see the agent heading in a suboptimal direction. The current options are:

  1. Wait until the turn completes (potentially minutes of wasted work)
  2. Escape to interrupt (destructive — loses in-progress work)
  3. Hope the queued message is interpreted correctly at the next boundary (unreliable per #26388)

None of these support the natural collaboration pattern: "hey, I see what you're doing — shift your focus to this instead."

Proposed Solution

A priority message channel that delivers user messages to Claude between tool calls during active execution, rather than queuing them for the next turn boundary.

Core mechanism: Between tool calls (Read, Edit, Bash, etc.), Claude Code already runs PreToolUse hooks. A native priority message system could use this same interstitial window to deliver queued user messages as high-priority context, tagged so Claude recognizes them as steering input rather than conversational replies.

Possible implementation approaches:

  1. Native priority injection: Messages typed during execution are tagged as [steering] and injected into Claude's context at the next tool call boundary (before the next PreToolUse hook fires), rather than waiting for the full turn to complete. Claude sees: [User steering message — typed during active execution]: "skip the tests, focus on implementation"
  1. Explicit steering mode: A user-activated mode (e.g., /steer or a keybinding) that changes message delivery from queued to priority. When active, typed messages are delivered between tool calls. When inactive, normal queuing behavior applies.
  1. Priority classification: Claude Code automatically classifies queued messages as "steering" (directional — "focus on X", "skip Y", "pivot to Z") vs. "conversational" (reactions, questions) and delivers steering messages with priority.

What this would look like for the user:

# Claude is actively running a multi-step refactor...

# User types (while Claude is working):
> Actually, start with the API layer, not the UI

# Instead of being queued until Claude's turn ends,
# the message is delivered at the next tool-call boundary.
# Claude sees it before its next Read/Edit/Bash call
# and adjusts course without losing completed work.

Workaround (Current)

It's possible to approximate this today using a PreToolUse wildcard hook that:

  1. Checks a file for user messages on every tool call
  2. Injects any contents as additionalContext
  3. Clears the file after reading

Combined with a shell alias (steer "pivot to X"), this gives near-real-time steering during tool-heavy work. But it requires the user to write to a file from another terminal rather than typing naturally into Claude Code, and the hook overhead (however small) applies to every tool call in every session.

A native solution would be simpler, more natural (type into the same interface), and could handle edge cases the workaround can't (like delivering messages during the gap between a tool completing and the next generation starting).

Additional Context

This becomes increasingly important as agent teams and long-running autonomous workflows mature. The team lead pattern (where Claude coordinates multiple sub-agents) already provides partial steerability — the user can message the lead while teammates work. But the lead itself is unsteerable during its own processing turns. A priority message channel would close this gap entirely.

The fundamental insight: Claude Code already has interstitial windows between tool calls where context can be injected (PreToolUse hooks prove this). The feature request is to make those windows available for user messages natively.

View original on GitHub ↗

27 Comments

github-actions[bot] · 4 months ago

Found 1 possible duplicate issue:

  1. https://github.com/anthropics/claude-code/issues/29490

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

sam0x17 · 4 months ago

yeah this is 100% needed and is something codex has supported for a while now

ThinkOffApp · 4 months ago

This is a real problem we hit daily running Claude Code as a persistent agent (via IDE Agent Kit, where external room messages get relayed to Claude Code sessions).

The current behavior is exactly as described: messages typed during processing queue up and arrive at the next turn boundary, often misinterpreted because temporal context is lost. Our workaround (tmux send-keys injection) has the same limitation, it can only deliver at turn boundaries.

Worth noting: Codex already ships a turn/steer API (added Feb 2026) that injects user messages into an active turn without waiting for completion. Enter steers mid-execution, ESC interrupts. This is becoming table stakes for agentic workflows. Claude Code is the only major IDE agent that still forces you to wait for the current turn to finish before you can redirect.

The most useful version of this for us would be a non-blocking priority channel that surfaces as a system-level notification within the current turn. Something Claude sees immediately and can choose to act on or defer, rather than a queued user message that gets batched with everything else.

jkanczura-work · 4 months ago

This is one of the biggest pain points I have with Claude Code! This should be higher priority with how much Opus 4.6 churns through tokens and how badly it can spiral. Attempting to steer it with regular follow-up messages (in the current functionality) often causes context corruption because it keeps referring back to those statements you made trying to guide it during semi-related tasks.

msmccor100 · 4 months ago

Yes, I find this is a huge annoyance that makes me wanna use another tool like Cline.

rpcai · 4 months ago

++ for this feature.

yurukusa · 3 months ago

A UserPromptSubmit hook can implement priority message injection:

PRIORITY_FILE="/tmp/cc-priority-message"
[ -f "$PRIORITY_FILE" ] || exit 0
MSG=$(cat "$PRIORITY_FILE")
rm -f "$PRIORITY_FILE"
[ -z "$MSG" ] && exit 0
jq -n --arg m "$MSG" '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"⚡ PRIORITY: " + $m}}'
exit 0

Send priority messages from outside:

echo "Stop current task — urgent bug in production" > /tmp/cc-priority-message

The next time Claude processes a prompt, the priority message is injected ahead of normal context.

ronle · 3 months ago

+1 — I'm building https://github.com/anthropics/claude-code/issues/30492, a multi-agent orchestration dashboard that runs on top of Claude Code in headless mode
(--input-format stream-json).

The gap is even more acute in headless/programmatic mode than in the interactive CLI:

  • Interactive CLI: ESC interrupts the current tool → agent stops → user types new instruction. Destructive but functional.
  • Headless stream-json: No equivalent. Writing to stdin queues until turn end. SIGINT kills the process entirely. The only option is kill + respawn with -r, which is slow, fragile, and frequently leaves sessions in broken states.

I've had to implement an "interrupt" mechanism server-side that kills the agent process and immediately respawns with -r <session_id> plus the new prompt. It works, but it's a hack — you lose in-flight tool state, and the respawn adds seconds of latency.

What would solve this for headless consumers:

A minimal first step — even before full mid-turn steering — would be an interrupt message on stdin:
{"type": "interrupt"}
{"type": "user", "message": {"role": "user", "content": "Stop and do X instead"}}

This would replicate ESC behavior: abort the current tool, keep the process and session alive, process the next queued user message. It's destructive (like ESC), but it avoids the kill/respawn cycle and keeps the conversation context intact.

The full priority-channel / steering proposal in this issue would be even better — non-destructive redirection between tool calls would eliminate the need for any process management on the orchestrator side.

xiaotonng · 3 months ago

Shipped this in pikiclaw — an open-source web dashboard for managing Claude Code, Codex, and Gemini sessions.

Steer from the dashboard:

  • While a task is running, send a new message → it queues up
  • Hit Steer to interrupt the current task and redirect the agent with your new input
  • The previous task's output is frozen in place (non-destructive), and the steered task starts immediately

Queue and steer are separate, explicit actions in the dashboard UI — no confusion about whether your input is steering or a new task.

Works with Claude Code CLI driver (stdin injection) and Codex (turn/steer RPC).

npx pikiclaw@latest
ProfSynapse · 2 months ago

Running into this specifically in the Agent Teams / subagent context too (see #21419). The same turn-boundary queueing applies to lead → teammate SendMessage — by the time my "stop doing X" message lands, the subagent has already done X and the turn is closing. Each teammate is effectively its own session from the scheduler's perspective, so any priority-injection mechanism shipped for the main session should apply symmetrically to teammate mailboxes.

The proposed PreToolUse injection point would solve both flavors cleanly. Would strongly prefer this over a destructive kill like TaskStop, which currently is the only escape hatch.

horonaka · 2 months ago

+1, with a data point from the other side of the client/model boundary:

I've been operating under a strict system-prompt rule that says "treat consecutive user messages as additions/corrections to the previous turn, especially when the response was slow." The rule is there precisely because of the failure mode in this thread — I kept interpreting mid-generation follow-ups as reactions to my latest (not-yet-read-by-user) reply, and conversations went sideways.

Outcome: the rule helps sometimes, but it cannot close the gap on its own. The model has no way to tell whether a queued user message was typed while the previous reply was still streaming, or after the user had read it. Without that signal from the client, the rule either over-applies (treating every follow-up as a mid-generation patch, breaking normal turn-taking) or under-applies (missing the real ones). Multiple failure rounds in the same session are routine.

This is a strong argument that the fix has to live on the client side: the temporal metadata exists only there. The proposals in this thread (priority injection, queue-mode tagging) and in the now-locked #26388 ([typed while Claude was writing] wrapper) are the right shape. Even the minimal version — just tagging queued messages with the fact they were typed pre-completion — would let system prompts reliably disambiguate.

So this is less a feature request than a structural requirement: no amount of prompting can substitute for a client-side timing signal.

ianbrandt · 2 months ago

It would be nice to be able to edit the last message sent to steer Claude (e.g., if it might be headed in the wrong direction because of a typo or poorly worded prompt).

everlats · 2 months ago

Exactly what I'm waiting for! ++

ShneorCr · 2 months ago

+1 — please bring back the old behavior where Claude could read messages while actively working on a task, just like a natural conversation with a human. The model could see the new message mid-run and decide for itself whether it was relevant to the current task (and adjust on the fly) or whether it should wait for the next turn.

This was one of Claude Code's standout features — it made the workflow feel collaborative instead of transactional. You could drop in a quick "actually, also check X" or "ignore the tests for now" without breaking flow or killing in-progress work.

Now that messages just sit in the queue until the current run finishes, that natural back-and-forth is gone. Pressing Esc to interrupt is destructive and loses context. Waiting for the turn to end defeats the purpose of catching a misdirection early.

Please restore this. It was a top feature and a big part of what made Claude Code feel different.

knyck-knostalgia · 1 month ago

Is this still not possible? Is this in the desktop app? This is an important feature that I miss when I come over from codex, i use claude for work and codex for personal

MrVlnka · 1 month ago

+1 — and a bit of history: this actually existed in earlier versions of the
Claude Desktop app. I loved it, and honestly it was one of the more compelling
reasons for me to switch over from Codex. I was genuinely disappointed when it
got removed in an update.
I get that the community seems split on this (see #49373 for the opposite camp,
who want messages to wait until the very end of a turn). So instead of arguing
over the "right" default, my proposal is simple: just give us a setting — a
toggle for how queued messages get injected:
• steer at the next tool boundary (inject mid-task, the old behavior)
• queue until end of turn (current behavior)
• interrupt immediately
That's the best of both worlds, it ends the debate, and it should be fairly
straightforward to implement. Please bring it back as an option. 🙏

A nice UX angle: instead of a settings toggle, make it per-message via the
keybind. Enter = queue (current), and a separate bind (e.g. Ctrl+Enter, since
Shift+Enter is usually newline) = inject/steer immediately. Decide per message,
no menu round-trip. The keybinds are already user-rebindable, so once a
"steer/inject" action exists, wiring this up should be trivial.

ProfSynapse · 1 month ago

Codex actually does this already at least in the app so I agree toggle it up!

afram123 · 1 month ago

+1 — this is the one feature I keep missing from Codex, where it's called steer: while the agent is mid-run you push a short note and it's folded into the current turn, without interrupting.

Right now my only options are Esc (throws away in-progress work) or typing and hoping the queue picks it up at a sane moment — and the timing is a coin flip: sometimes it derails a tool call, sometimes it lands minutes too late after the agent already went the wrong way.

This gets more painful the longer agents run. On multi-hour runs, being able to drop a small correction the moment I see it heading the wrong way — instead of interrupting or waiting — would be huge. A dedicated steer channel (separate from Interrupt and the existing queue) would close the biggest day-to-day gap with Codex for me.

chk-mk · 1 month ago

+1, On "Claude Desktop Code", I've seen the agent work for 15 minutes, do dozens of tool calls, including ones that I had to manually approve and the message is still pending. This is absurd. On denying - and there's no deny-message option that I can see - the message fires off immediately, potentially confusing the model, as if the thing I tried to clarify 15 minutes ago is the problem with the latest tool call (when it's not), and then I had to interrupt the model anyway and try to get things back on track.

This is just unnecessary pain.

As noted in #36326, this also contradicts the documentation, which describes the message as immediately steering. That issue was closed with no fix to the documentation.

Agreed with others that 'queue up' can be useful too, so the fix should be both, not to just change it and break someone else's use case.

bob-obringer · 1 month ago

I've recently written a coding agent with claude agent sdk using input streaming. It was beautiful. Did a wonderful job steering the conversation mid flow. Just like Codex does now.

Why was I able to do this in my own agent using the Claude Agent SDK but Anthropic can't?

BobbinFortnox · 1 month ago

Yeah this sucks. Closed my issue, but I would suggest a /btw style pre-evaluation that determines whether the current block of stuff (however that is defined) should be interrupted.

Qcko · 25 days ago

+1 — strong need. Most of this thread is about the delivery mechanism (when/how a note reaches the model). There's an agent-behavior half that's just as important for the pain described here — silent misinterpretation, stale notes landing late — and it survives whatever channel ships:

1. Restate-before-act. On draining a note, the agent should echo back its reading in a line or two before acting. The core flaw of async steering is the sender never knowing whether the note landed or how it was read; restating closes that loop and fixes the "silently misapplied" failure mode.

**2. A non-destructive soft stop, distinct from Esc.** Esc is a hard kill; steering keeps going. The missing third intent is "wind down cleanly" — reach a consistent state, then halt, losing no in-flight work. Worth its own tier, not folded into Esc.

3. Stale-note handling. If a note refers to work already passed, the agent should say so rather than retrofit it.

NickAry83 · 23 days ago

+1, and one dimension I don't see called out yet in the thread:

In extended-reasoning / max-effort modes the turn isn't atomic. A single turn often stacks several self-posed questions and permission prompts before it ever reaches a boundary, so "wait for the turn to end" can mean waiting through a dozen sub-decisions the agent has already resolved on its own. That's the precise reason queue can't cover this case: queue assumes a boundary arrives soon, and in long autonomous runs the agent burns through the decisions I'd have answered well before that boundary shows up. The longer and more autonomous the run, the more the gap costs, which is the opposite of where you'd want it to scale.

Strong support for the non-destructive priority channel as described, especially Ocko's state-note handling point.

reveal79 · 21 days ago

Strong +1 on this. Want to add a framing that hasn't come up yet: this is a token efficiency problem, not just a UX problem.

Right now there are two failure modes when I spot a problem mid-task:

  1. Interrupt — kills the turn, I lose context, and burn tokens reconstructing state before the correction can even land.
  2. Let it finish — burn tokens completing work I already know is wrong, generate artifacts I'm about to throw away, then correct after the fact — so Claude now has to reason about undoing prior steps on top of the new direction.

The actual cost of a mid-task correction today is:

(remaining wrong work) + (interrupt overhead) + (state reconstruction) + (correction itself)

With steer-at-seam — injecting at the next PreToolUse boundary as you've proposed — that collapses to just the correction. No wasted work, no reconstruction overhead.

At scale across power users running complex multi-step sessions, this isn't just a quality-of-life improvement. It's a meaningful reduction in wasted compute — which matters to Anthropic as much as it does to us.

The infrastructure argument you've already made is exactly right: PreToolUse hooks prove the interstitial windows exist. This is a UX layer on top of a mechanism that already works.

ciscodevelop · 20 days ago

Design Proposal: Doorbell-model message injection at agent lifecycle boundaries

Status: Proposed
Related: #30492 (this), #49373 (end-of-turn queue), #29224 (side-channel responses), #30677 (VS Code queueing)

Context

When the main agent is working, a user message has only two fates today: interrupt the turn (Esc) or sit in a queue that flushes at the next LLM pause — often mid-task, derailing the run (#49373). Both are blunt.

The current queue is effectively a pull / polling model: the loop must reach a pause, then drains whatever is waiting, with no notion of who sent it or what authority it carries. This produces two well-known failure modes:

  • Authority ambiguity — a queued "also update the tests" is read as a fresh instruction and the agent abandons what it was doing.
  • Boundary cost — proposals that check for input at every step imply the loop must constantly watch for arrivals, which is wasteful.

The key observation: the agent already has a return-path it traverses when a subagent finishes. A subagent returning ("here's what I found, here's what changed") is an established, trusted ingestion pattern. The main agent reads that return, evaluates it, and decides the next action. We don't need a new mechanism — we need to let a user message arrive through that same boundary, marked for what it is.

Decision

Treat the user as a first-class external actor in the multi-agent lifecycle, not as an exception that breaks the turn. Two coupled mechanisms:

1. Doorbell, not polling (event-driven delivery)

The loop does not check for input at each step. There is no watching. Like a house with a closed front door: you don't continuously look outside, you wait for the bell. The incoming message raises the event; the loop spends nothing while no one is there.

When a message arrives, it is parked at the door. At the next existing lifecycle boundary (subagent return, or tool-call boundary where PreToolUse hooks already fire), the main agent "hears the bell," checks the peephole, and admits it. Cost is zero when the queue is empty; ingestion is immediate when it isn't. This replaces a pull model with a push / interrupt-driven one.

2. Badge-carrying agent, evaluated by the main agent (authority via judgment, not flags)

The message enters wrapped as an external agent return with a provenance badge — semantically identical to a subagent saying "heads up, this came up." The main agent reads and evaluates it, exactly as it already evaluates subagent returns, and decides authority from content:

  • "Luca flagged a thing to change because X happened" → note it, continue.
  • "The lead said we should do it this way" → suspend, recalibrate.

Authority is not a flag the user sets upfront. It's a judgment the main agent makes downstream, where the intelligence to make it already lives. The badge only guarantees provenance — "this genuinely came from outside, the model did not hallucinate it" — and a double-verification step hardens that provenance against spoofing / injection.

Why this is a reuse, not an addition

| Existing primitive | Reused for |
|--------------------|-----------|
| Subagent return-path | User message ingestion |
| Tool-call / PreToolUse boundary | The "door" where admission happens |
| Main agent evaluating a return | Deciding advisory vs. directive |

The novel surface is small: (a) park-at-door + admit-at-next-boundary, and (b) the provenance badge + verification. Everything else is plumbing that already exists.

Consequences

Easier

  • Long autonomous runs stay steerable without derailment.
  • Users become peers in the lifecycle — they can knock at any time and be admitted at the right point.
  • No per-step polling cost.

Harder / to revisit

  • Trust boundary: subagent returns are system-initiated; a user message injected mid-turn is external input arriving during autonomous reasoning. The badge must carry provenance and survive a verification check.
  • Boundary admission must not stall the loop when the door is empty — the check fires on event, not on schedule.
  • Defining the badge schema and the double-verification contract.

Action Items

  • Define the provenance badge schema (origin, verification token, advisory/directive hint left for the main agent to resolve).
  • Specify the double-verification step for badge authenticity.
  • Add park-at-door + admit-at-next-boundary at the subagent-return / PreToolUse interstitial windows.
  • Have the main agent classify admitted messages (advisory → continue, directive → recalibrate) the same way it classifies subagent returns.
  • Optional explicit /steer to force directive-priority delivery (aligns with this issue's proposal).
jkanczura-work · 20 days ago
# Design Proposal: Doorbell-model message injection at agent lifecycle boundaries Status: Proposed Related: #30492 (this), #49373 (end-of-turn queue), #29224 (side-channel responses), #30677 (VS Code queueing) ## Context When the main agent is working, a user message has only two fates today: interrupt the turn (Esc) or sit in a queue that flushes at the next LLM pause — often mid-task, derailing the run (#49373). Both are blunt. The current queue is effectively a pull / polling model: the loop must reach a pause, then drains whatever is waiting, with no notion of who sent it or what authority it carries. This produces two well-known failure modes: Authority ambiguity — a queued "also update the tests" is read as a fresh instruction and the agent abandons what it was doing. Boundary cost — proposals that check for input at every step imply the loop must constantly watch for arrivals, which is wasteful. The key observation: the agent already has a return-path it traverses when a subagent finishes. A subagent returning ("here's what I found, here's what changed") is an established, trusted ingestion pattern. The main agent reads that return, evaluates it, and decides the next action. We don't need a new mechanism — we need to let a _user message_ arrive through that same boundary, marked for what it is. ## Decision Treat the user as a first-class external actor in the multi-agent lifecycle, not as an exception that breaks the turn. Two coupled mechanisms: ### 1. Doorbell, not polling (event-driven delivery) The loop does not check for input at each step. There is no watching. Like a house with a closed front door: you don't continuously look outside, you wait for the bell. The _incoming message_ raises the event; the loop spends nothing while no one is there. When a message arrives, it is parked at the door. At the next existing lifecycle boundary (subagent return, or tool-call boundary where PreToolUse hooks already fire), the main agent "hears the bell," checks the peephole, and admits it. Cost is zero when the queue is empty; ingestion is immediate when it isn't. This replaces a pull model with a push / interrupt-driven one. ### 2. Badge-carrying agent, evaluated by the main agent (authority via judgment, not flags) The message enters wrapped as an external agent return with a provenance badge — semantically identical to a subagent saying "heads up, this came up." The main agent reads and evaluates it, exactly as it already evaluates subagent returns, and decides authority _from content_: "Luca flagged a thing to change because X happened" → note it, continue. "The lead said we should do it this way" → suspend, recalibrate. Authority is not a flag the user sets upfront. It's a judgment the main agent makes downstream, where the intelligence to make it already lives. The badge only guarantees provenance — "this genuinely came from outside, the model did not hallucinate it" — and a double-verification step hardens that provenance against spoofing / injection. ## Why this is a reuse, not an addition Existing primitive Reused for Subagent return-path User message ingestion Tool-call / PreToolUse boundary The "door" where admission happens Main agent evaluating a return Deciding advisory vs. directive The novel surface is small: (a) park-at-door + admit-at-next-boundary, and (b) the provenance badge + verification. Everything else is plumbing that already exists. ## Consequences Easier Long autonomous runs stay steerable without derailment. Users become peers in the lifecycle — they can knock at any time and be admitted at the right point. No per-step polling cost. Harder / to revisit Trust boundary: subagent returns are system-initiated; a user message injected mid-turn is external input arriving during autonomous reasoning. The badge must carry provenance _and_ survive a verification check. Boundary admission must not stall the loop when the door is empty — the check fires on event, not on schedule. Defining the badge schema and the double-verification contract. ## Action Items Define the provenance badge schema (origin, verification token, advisory/directive hint left for the main agent to resolve). Specify the double-verification step for badge authenticity. Add park-at-door + admit-at-next-boundary at the subagent-return / PreToolUse interstitial windows. Have the main agent classify admitted messages (advisory → continue, directive → recalibrate) the same way it classifies subagent returns. * Optional explicit /steer to force directive-priority delivery (aligns with this issue's proposal).

I don't know if an AI generated, copy and pasted implementation plan is the way to go here

Keenvisionary · 14 days ago

+1. Daily use case here: desktop app with heavy subagent orchestration. Queued messages currently sit until the whole turn completes, so a mid-task course correction is either a destructive Esc or a long wait. With multi-minute tool chains that is a real workflow tax. Codex's turn/steer (Enter injects into the running turn at the next reasoning step, Tab queues for the next turn) is useful prior art for the interaction model. Happy to test a beta.