You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Background shells are excluded from #870's turn-hold — the #866 hazard (out-of-turn permission/ask request) still reproduces via run_in_background #876
This is the background-shell twin of #866, which #870 fixed only for spawned
sub-agents. #870's own scoping is explicit: "a hold must NEVER wait on a
shell" (since a shell can outlive every turn — e.g. a dev server — and its
contract is wake-on-exit, not a turn-scoped drain). We reproduced the identical
hazard #866 described, through that deliberately-excluded door, on v0.59.0:
#870's hold-open logic keys on liveBackgroundTasks entries with isSubagent: true; shell tasks are explicitly walked past ("shells-never-defer" is even
named in a code comment). So a run_in_background shell's post-completion
followup gets none of the protection #870 added — the turn settles at launch,
and whatever the model does after the shell finishes (including raising a
request that blocks on user input) rides in as bare post-settlement session/updates, exactly as #866 originally described for sub-agents.
Client-side impact varies, but the hazard is real either way
We can't speak for every ACP client, but it's worth noting the failure mode
isn't uniformly "hang":
A client with a connection-scoped (not turn-scoped) request handler can still
answer it mechanically, but the product-level failure Async sub-agent stranded at turn settlement — frozen mid-tool-call on an out-of-turn permission request, promised result undeliverable #866 named remains: the
turn already settled, any "still working" indicator tied to the turn (rather
than the session) has already gone quiet, and then a blocking question
appears with no framing for why. From the user's perspective the session
looked done, and now something is unexpectedly asking them for input.
Either way, this is the same root cause #864/#865/#866 already describe — a
background task's continuation has no session-level representation once its
launching turn has settled — just reached via the one class (run_in_background
shells) that #870's fix intentionally does not cover.
Proposal
No new mechanism needed beyond what #864/#865/#866 already proposed — this
issue is here to flag that #870 leaves the identical hazard live for shells,
in case that wasn't an intentional accepted risk:
Summary
This is the background-shell twin of #866, which #870 fixed only for spawned
sub-agents. #870's own scoping is explicit: "a hold must NEVER wait on a
shell" (since a shell can outlive every turn — e.g. a dev server — and its
contract is wake-on-exit, not a turn-scoped drain). We reproduced the identical
hazard #866 described, through that deliberately-excluded door, on v0.59.0:
Bash(run_in_background)command. The turn resolvesend_turnimmediately — per Background sub-agents & shells aren't trackable to completion — forward background_tasks_changed / task_updated status #865, the tool result returns at launch, not atprocess completion.
(a
task-notification-style followup), with no turn held open for it (bydesign, per fix: hold a turn open while its background subagents are still live #870).
repro, the
ask_user_questiontool — fully out-of-turn, with no livesession/promptfor it to be framed inside. This is functionally the sameshape as Async sub-agent stranded at turn settlement — frozen mid-tool-call on an out-of-turn permission request, promised result undeliverable #866's frozen
session/request_permissioncall, just via adifferent tool and a shell instead of a sub-agent as the trigger.
Why this isn't fully covered by #870
#870's hold-open logic keys on
liveBackgroundTasksentries withisSubagent: true; shell tasks are explicitly walked past ("shells-never-defer" is evennamed in a code comment). So a
run_in_backgroundshell's post-completionfollowup gets none of the protection #870 added — the turn settles at launch,
and whatever the model does after the shell finishes (including raising a
request that blocks on user input) rides in as bare post-settlement
session/updates, exactly as #866 originally described for sub-agents.Client-side impact varies, but the hazard is real either way
We can't speak for every ACP client, but it's worth noting the failure mode
isn't uniformly "hang":
outstanding
session/prompt(or whose UI only surfaces requests while a turnlooks active) will drop or never display the request — the Async sub-agent stranded at turn settlement — frozen mid-tool-call on an out-of-turn permission request, promised result undeliverable #866 "stranded,
undeliverable" outcome.
answer it mechanically, but the product-level failure Async sub-agent stranded at turn settlement — frozen mid-tool-call on an out-of-turn permission request, promised result undeliverable #866 named remains: the
turn already settled, any "still working" indicator tied to the turn (rather
than the session) has already gone quiet, and then a blocking question
appears with no framing for why. From the user's perspective the session
looked done, and now something is unexpectedly asking them for input.
Either way, this is the same root cause #864/#865/#866 already describe — a
background task's continuation has no session-level representation once its
launching turn has settled — just reached via the one class (
run_in_backgroundshells) that #870's fix intentionally does not cover.
Proposal
No new mechanism needed beyond what #864/#865/#866 already proposed — this
issue is here to flag that #870 leaves the identical hazard live for shells,
in case that wasn't an intentional accepted risk:
a "still working" indicator alive across the shell's post-completion
followup, so a subsequent question/permission request isn't a surprise.
background_tasks_changed(Background sub-agents & shells aren't trackable to completion — forward background_tasks_changed / task_updated status #865) would let a client know ashell-triggered continuation is plausible before it happens.
session/request_permission(and, by extension, any tool requiring humaninput) may arrive between turns — so client authors know to keep that
channel's UI live independent of turn/status state, the way fix: hold a turn open while its background subagents are still live #870 now
guarantees for sub-agents but not shells.
Related
background_tasks_changed/ task completion statusEnvironment:
@agentclientprotocol/claude-agent-acp@0.59.0.