Steer prompts into the running turn instead of queueing them - #777
Open
OSadovy wants to merge 1 commit into
Open
Steer prompts into the running turn instead of queueing them#777OSadovy wants to merge 1 commit into
OSadovy wants to merge 1 commit into
Conversation
OSadovy
force-pushed
the
mid-turn-steering
branch
from
August 21, 2026 11:51
b5eec11 to
145b2a3
Compare
A prompt sent while the agent works is held until the turn ends and then sent as a new one, so a wrong direction can only be corrected after it has finished being wrong. Both the Claude and Codex adapters accept a message injected into the turn already running; this uses it. The method is `_session/steering', an extension rather than spec (the leading underscore says so), advertised as `_meta.steering.supported' in the initialize response and implemented under that name by both adapters. The standards-track proposal, `session/inject', is unmerged and targets ACP v2. Queueing remains the fallback and loses nothing: a steer is only attempted when the agent advertises it, `agent-shell-steer-when-busy' is on, and a turn is running that is not blocked on a permission answer. Every other answer -- the turn ended, the agent refused, the request failed -- puts the prompt back on the queue or submits it normally. A blocked shell keeps queueing deliberately. What an agent does with a message injected while a tool waits on a permission answer is left undefined by every implementation of this, so we don't send one. Neither adapter echoes a steered message back while the turn runs, so the prompt is rendered here or it appears nowhere. It takes the field and face shape comint gives a live prompt, closed with shell-maker's end-of-prompt marker: chat mode reads a last prompt with no marker after it as the live one, and the prompt bar hides that. `comint-highlight-prompt' is named alongside `agent-shell-prompt' rather than left to inheritance, the same way a restored prompt names it: `shell-maker--re-search-forward-prompt' tests for the symbol with `memq', which inheritance does not satisfy, and a steered prompt missing from `shell-maker--extract-history' leaves `agent-shell-interaction-at-point' nil, which silently keeps the viewport on the previous interaction.
OSadovy
force-pushed
the
mid-turn-steering
branch
from
August 22, 2026 21:38
145b2a3 to
0e35928
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the steering proposal from #773.
When the agent advertises steering and a turn is running, a prompt sent from the
shell is injected into that turn instead of being queued until it ends. Agents
that don't advertise it queue exactly as before.
The method is
_session/steering— an ACP extension rather than spec (hence theleading underscore), advertised in the
initializeresponse's top-level_metaas
steering.supported, a sibling ofagentCapabilities. Verified against@agentclientprotocol/claude-agent-acp0.66.0 and@agentclientprotocol/codex-acp1.2.0. The standards-track equivalent,
session/inject(agentclientprotocol/agent-client-protocol#1261), is unmerged and targets ACP v2,
so the extension is what's usable today.
Queueing stays the fallback and nothing is lost. A steer is attempted only
when the agent advertises it,
agent-shell-steer-when-busyis on, and a turn isrunning that isn't blocked on a permission answer. Every other outcome — the turn
had ended, the agent refused, the request failed — either submits the prompt
normally or puts it back on the queue. A shell waiting on a permission answer
keeps queueing deliberately: what an agent does with a message injected while a
tool sits on that question isn't defined by any implementation I could find.
Entry points:
C-u M-x agent-shell-prompt-queuequeues that one prompt instead.M-x agent-shell-steersteers explicitly and errors when it can't.agent-shell-steer-when-busy(the one new defcustom, since [feature] steer prompts into the running turn #773 asked foropt-out) turns the automatic behaviour off entirely.
Neither adapter echoes a steered prompt back while the turn runs, so it's rendered
client-side, reusing the field/face shape already used for replayed user messages
and closed with shell-maker's end-of-prompt marker — without that, chat mode reads
it as the live prompt and the prompt bar hides it. Also adds a
prompt-steeredsession event.
On automating cancel-and-resend instead (your comment in the issue): I don't
think they're equivalent. Interrupting drops the work in flight and leaves a
cancellation in the transcript, while a steer keeps the turn and what it has
already done. They compose, though —
agent-shell-steercould fall back tointerrupt-and-continue for agents that don't advertise steering, which is what
@liaowang11 suggested. Happy to do that as a follow-up if you'd like it.
Behaviour differs per agent, worth knowing before trying it: Claude interrupts
what it's generating and answers in a couple of seconds; Codex accepts the steer
but finishes the message in flight first.
Testing: five tests covering the request shape, outcome mapping, the decision to
steer, the four-way fallback (including that a failed steer keeps the prompt), and
the rendered prompt. Full suite passes at 568.
Checklist
M-x checkdocandM-x byte-compile-file.