Repository navigation
Description
What happened
An agent's progress update sent with t3_thread_send can abort the tool currently running in the receiving Claude thread. Claude then reports "The user doesn't want to take this action right now", although the human refused nothing. Queueing every agent update until the whole turn ends avoids cancellation but delays coordination for long turns.
Diagnosis
The Claude adapter sends active steering as SDKUserMessage with priority: "now". Claude Code treats that priority as an interruption. The activeSteeringInterruptsTools capability already identifies the difference from Codex's steering.
The initial #21158 patch queued agent auto/steer messages whenever an active session declared that capability, including when no tool was currently running. It did not apply this queueing rule to Codex or idle threads. The updated PR proposes replacing that coarse fallback with safe delivery during the active turn.
Steps to reproduce
- Start a Claude thread and have it run a command or parallel tool calls.
- From another agent, send an automatic or explicit steer to that thread while the calls are running.
- Observe the tool cancellation and misleading user-refusal result. With the initial fix(server): agent messages no longer cancel Claude tools #21158 patch, observe that the update instead waits until the entire turn ends.
Version and environment
Observed on a Windows desktop personal fork; original failure recorded on 2026-10-18. Exact installed T3 build was not re-queried for this report. Controlled SDK experiments on 2026-10-19 used @anthropic-ai/claude-agent-sdk 0.3.276 and Claude Code 2.1.303. No T3 installation or restart was performed.
Evidence
The original provider log offered the agent update with priority: "now" at 2026-10-18T09:46:43.510Z; cancelled-tool results followed at 09:46:43.964Z. Seven parallel delegation calls were in flight: two succeeded, one returned an interruption, and four returned the user-refusal message.
Fresh bounded SDK experiments found:
priority: "next"during a six-second tool let the tool finish normally and folded the update into one native result. Sending it during a no-tool answer instead produced two native results; the first reportedqueued_turn_count: 0despite the continuation. Using that priority alone leaves a native continuation that T3 must track and cancel.PostToolBatch.additionalContextdelivered once after both tools in one model batch completed, without cancellation, within one native result. The probe's MCP runtime executed those two calls serially; simultaneous execution was not tested. The documented hook contract supplies the completed batch rather than a per-tool boundary.Stop.additionalContextlet a no-tool answer consume an update and continue before producing its single native result.- Child hook callbacks carried
agent_id; filtering those preserved the root update. Clearing the local pending input before interrupt produced no injection or continuation during five seconds of observation.
Options and workaround
The narrow option proposed in #21158 holds agent input in T3 for a root PostToolBatch or Stop hook, up to five seconds, then uses the existing durable next-turn queue if no boundary arrives. Stop revokes pending delivery; task acknowledgement/disposal rechecks ownership before hook handoff. Human steering keeps its current interruption semantics. The committed patch has passed focused tests and independent review; full checks are in progress.
Native next is another option if T3 also implements native queued-input ownership and cancellation across multiple results. A plain stream tool-end callback followed by native now has a race with the next tool starting. A PostToolUse hook also fires before all parallel tools finish; PostToolBatch gives the safer batch boundary.
Explicit mode: "queue" remains the existing workaround when avoiding interruption matters more than prompt delivery. No fix has been installed on this PC.
Related reports
PR #21158 addresses agent-originated messages. #15720 and #15708 concern human steering and Stop around running Bash; #18641 and #15868 propose different human-steering behavior. This report concerns an agent update being mistaken for a user refusal.
Filed by GPT-6.1 Sol at high effort in T3 Code through the Codex harness, using source inspection, retained diagnostic evidence, and fresh controlled SDK probes. This did not run the interactive t3 triage command.
Activity
Alb11747 commentedon Oct 19, 2026
The safe tool-boundary implementation is now in #21158. It uses root PostToolBatch/Stop hook context, with a five-second durable queue fallback and cancellation/ownership checks. Focused SDK probes and regression tests are recorded there; final independent GPT-6.1 Sol xhigh review has no remaining findings. Fork checks are running. No build has been installed and T3 has not been restarted.
juliusmarminge commentedon Oct 21, 2026
Triaged against main at 70e5e384da. Scanned open issue titles for agent steering, tool cancellation, and user-refusal wording; no matching duplicate found. Runtime reproduction was not performed. The proposed fix changes agent-originated t3_thread_send steer/queue delivery semantics, which this automated triage flow reserves for maintainer review. Leaving open for Julius; no implementation changes.
juliusmarminge commentedon Oct 22, 2026
Reproduced on Linux against main 8acbefefc5, using the isolated web dev server and Claude Opus 5.5. An agent-originated explicit steer interrupted all three parallel 45-second t3_thread_wait calls immediately; a separate running Bash command was also aborted. The MCP calls returned interruption errors rather than the older user-refusal wording. Runtime transcript. Existing #21158 remains open and unchanged.
immakermatty commentedon Oct 24, 2026
One more failure mode with the same cause, in case it helps the maintainer takeover of #21158: an agent message can also cancel a pending question or approval. The person never sees the question.
What we observed (a fork based on v0.1.1, 2026-10-24, Claude Opus 5.5 in Claude Code):
AskUserQuestion.t3_thread_sendwith the defaultmode: auto.Tool permission request aborted, and the question disappeared from the UI before the person answered it.The same path on
main(909e4c9):ThreadManagementService.sendToThreadturnsautointosteer_activewhenever a steerable run exists.awaitClaudeUserInputAnswersresumes with empty answers, andawaitClaudeApprovalDecisionresumes withcancel.As far as I can read it, the takeover's guard (agent sends to a session with
activeSteeringInterruptsToolsgo to the durable queue) covers this case for Claude, so no separate fix is needed.Our interim fix: until it lands, our fork queues an
autosend while the thread has a pending runtime request, with a focused test (commit). We will drop it once #21158 is in a release. I have not checked whether steering a Codex turn affects a pendingrequest_user_input, so I am not proposing that broader guard here.Prepared through T3 Code with Claude Opus 5.5.
guryanov-a commentedon Nov 2, 2026
Human steers from the composer hit this too. As taken over, #21158 leaves human steering unchanged, so this case remains once it lands.
Seen on T3 Code 0.1.6, Claude Opus 5.5, Claude Code 2.1.316 (from the thread's activity log, not a controlled reproduction). A
Bashcall and aToolSearchwere issued together. I sent a steer 19 s into theBashcall.Bashfinished normally, and at that same moment the waitingToolSearchreturned "The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed." The agent followed my steer, but abandoned the work that call belonged to and told me "you stopped me".Claude Code 2.1.316 also ships neutral texts for this situation, such as "[Tool call did not complete: the turn was ended to deliver the message that follows. Nothing refused it; re-run it if still needed.]", but this steer got the refusal text. Delivering human steers at the next tool boundary (#15287) would avoid the cancellation altogether.
jamesdchen commentedon Nov 3, 2026
Same bug on T3 Code 0.1.6 (Windows x64, Claude Opus 5.5), from an orchestration run with about 15 Claude delegates. A coordinator thread steers delegates with
t3_thread_send(mode: auto), and the delegates read the cancellation as a human decision. No human saw or refused anything.Counts from one evening's provider logs: 14
tool_results withis_error: trueand this text, across 5 threads, within about 30 minutes: 13Bash, 1t3_thread_send. Each came 1-25 s after the call was issued.Why it costs more than one retried call:
Bashhad written local files and was piping them to a remote host, so the agent had to work out what had actually happened before it could continue.What would help beyond the queueing in #21158:
t3_thread_senddescription:steerandautocan kill the receiver's running tool. Agents currently have no way to know, andqueuelooks like merely a slower option.Caveat: I matched these to steers by timing and by the coordinator's send log. I don't have a per-call record tying each one to a specific
priority: "now"frame. I can share redacted log lines if useful.Meorir commentedon Nov 3, 2026
Frequency data and controlled runs for this bug, from a setup where many Claude threads coordinate through
t3_thread_send. The main additions:queuecaused no interruptions in our data, the outcome depends on the tool's state, and one outcome is an empty error that earlier comments don't mention.Environment: T3 Code desktop on Windows 11, now 0.1.6 with Claude Code 2.1.317. The 14-day window also includes earlier T3 builds and Claude Code back to 2.1.304.
steer_activeforautoandpriority: "now"are still onmaintoday.How often (14 days to 2026-11-03)
queue-operationin the transcript; this count comes from a first pass and includes a few Esc interrupts).Interruptions by the mode of the incoming message, matched on exact message text:
auto(explicit or default)steerqueue"No matching send" is probably human composer steers, wake-ups and senders outside these transcripts. We did not separate them. The send counts include idle and non-Claude recipients, so they don't give a per-busy-thread rate.
What the agent receives
The user doesn't want to take this action right now. STOP what you are doing...Error calling tool (Bash):with nothing after the colonThe tool call was interrupted before a result was received. It may or may not have completed...Command running in background with ID: ...The neutral wording mentioned above ("Nothing refused it") appeared 0 times. All 146 empty errors and all 209 STOP results have no
permissionDecisionin the transcript, while 106 of the 108 remaining interrupted MCP calls have one. The 146 and the 209 span Bash, Edit, Write, PowerShell and MCP. That is why we read the empty error as "interrupted before the permission decision", but this is an inference.The empty error is the hardest case for an agent: it has no reason text, so the agent can't tell what happened or whether the command ran.
Controlled runs
Each run used a Claude Haiku 5.5 child thread with a 1 s tick script and a
Writequeued behind it. The parent sent the message, on 0.1.6 with Claude Code 2.1.317.WriteWritesteer, about 12 s inWritesteer, about 12 s inWritequeueSo in the PowerShell case the agent reads a refusal while its first command is still running. A retry of that command would run it twice. Afterwards, the child in the first run described its write as having been rejected.
Three more steers during 16 sequential short PowerShell calls: one moved a just-started command to the background, and two landed between calls and cancelled nothing.
Cost
About one interruption in eight (35) was followed by more than 60 s before the agent's next tool call, and 16 by more than 5 minutes. That is an upper bound, because some of those gaps are ordinary ends of turns. In one time-boxed rollout, an agent waiting on what it read as a human refusal contributed to a 48-minute delay.
What would help
queuenumbers support its direction, but it currently has merge conflicts and was last updated on 25 Oct.t3_thread_senddescription thatautoandsteercan cancel running tools. Agents can't learn this today, and it's what we have just added to our own instructions as a workaround (mode: "queue"by default). We have no results from that yet.These are aggregates from local transcripts. The transcripts contain business data, so we can't attach them, but we can run other counts on request.
Prepared through T3 Code with Claude Opus 5.5.