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
{{ message }}
Repository navigation
Add turn-complete signal for session_update notifications #554
After a prompt() call returns, there is no protocol-level signal indicating that all session_update notifications for that turn have been delivered. Clients that accumulate state from these notifications (e.g. streamed text chunks, usage updates) must resort to heuristic delays (asyncio.sleep) to wait for in-flight notifications to arrive before reading the accumulated result.
This is inherently racy — too short a delay misses late notifications, too long a delay adds unnecessary latency.
Current workaround
In OpenHands, we yield to the event loop and then sleep for a configurable duration (default 0.1s) after prompt() returns:
response=awaitconn.prompt(messages, session_id)
awaitasyncio.sleep(0) # yield to let queued handlers runawaitasyncio.sleep(0.1) # wait for in-flight notifications
Proposed solution
Add a protocol-level mechanism that signals when all notifications for a given turn have been delivered. For example:
A dedicated turn_complete notification sent by the server after all session_update notifications for a prompt response
Or a field on the PromptResponse indicating whether all associated notifications have been flushed
This would let clients reliably synchronize without arbitrary delays.
Follow-up clarification: the proposal is a TURN_COMPLETE session update barrier (plus sessionCapabilities.turnComplete capability advertisement) as an RFD-first step before unstable schema/runtime changes.
Add a protocol-level mechanism that signals when all notifications for a given turn have been delivered. For example:
A dedicated turn_complete notification sent by the server after all session_update notifications for a prompt response
The Agent MAY send session/update notifications with content or tool call updates after receiving the session/cancel notification, but it MUST ensure that it does so before responding to the session/prompt request.
@simonrosenberg Doesn't this imply the session/prompt response is covering the use-cause suggested by the dedicated turn_complete (at the very least for session/prompt requests)?
Having said that, I'm interested in additional markers/signals for a different reason. I'm looking to support broadcasted interactions (agent -> client). This would enable supporting flows like Claude's remote control in agent-shell.
Hi 👋🏻 yes I think I would like to move the entire prompt lifecycle to be notification based entirely, which I think will help with this.
@benbrandt is there a particular approach that's getting traction that would enable broadcasting session prompts to clients? I'd be happy to give it a try and see how well it works for a remote-control kind of flow.
@xenodium I believe you might be interested in #533 (already mentioned it here), it is basically covering agent to multiple clients scenario, your usecases might be important
+1 to a protocol-level signal — we hit exactly this race in slopus/happy and ended up shipping a client-side workaround in slopus/happy#1287: a two-signal state machine on the client that tracks responseReceived and updatesSettled independently, plus a POST_RESPONSE_GRACE_MS (500ms) fallback timer that closes the turn when the RPC response arrives but no further updates ever show up (the "empty turn" / response-first race).
In practice we did see agents flush the prompt response before the trailing session/update (Codex through the bridge was the reproducible one for us), so the assumption "updates arrive last" really does fail in the wild and the heuristic-sleep approach has the failure modes the OP describes. Our fake-timer tests pin down four distinct orderings — spec ordering / response-first / empty turn / tool-complete-before-response — and a re-entrant turn case for completeness.
Between the two options in this issue: a first-class turn_complete notification (option 1) would let us delete the entire state machine and the grace timer. A flag on PromptResponse (option 2) would also work but is slightly worse because it conflates "the server believes the turn is done" with the actual flush of in-flight session/update notifications — clients would still need a buffer/queue to handle the response-arrives-first case unless the transport guarantees strict ordering. So we'd lean toward option 1 (dedicated notification, sent as the last session/update of the turn).
Happy to help draft the spec PR + a reference SDK implementation if useful.
One interaction worth folding into the design here: if a backgrounded tool call can settle after prompt() returns, its tool_call_update would arrive after the turn — which would make an unconditional turn_complete signal inaccurate rather than merely early.
Either backgrounded tool calls need to be excluded from the completeness guarantee, or the signal means "all updates for the foreground turn" rather than "all updates for this session's work". Raised separately as #1847, since it may be a question about ToolCallStatus semantics rather than about this signal.
Activity
benbrandt commentedon Feb 23, 2026
Hi 👋🏻 yes I think I would like to move the entire prompt lifecycle to be notification based entirely, which I think will help with this.
denofevil commentedon Mar 2, 2026
Relates to 7375612#diff-d916e83e9af6279a58026089bd8758f3a0884148c3728e1b475106cc33f68df2R215
docs(rfd): draft turn_complete signal for prompt-stream sync
stablegenius49 commentedon Mar 4, 2026
I opened a draft RFD PR for this: https://github.com/agentclientprotocol/agent-client-protocol/pull/644\n\nIt proposes a barrier (with capability gating) as an RFD-first step before unstable schema/runtime changes.
stablegenius49 commentedon Mar 4, 2026
Follow-up clarification: the proposal is a TURN_COMPLETE session update barrier (plus sessionCapabilities.turnComplete capability advertisement) as an RFD-first step before unstable schema/runtime changes.
xenodium commentedon Mar 6, 2026
From the diagram in https://agentclientprotocol.com/protocol/prompt-turn and this text:
@simonrosenberg Doesn't this imply the
session/promptresponse is covering the use-cause suggested by the dedicatedturn_complete(at the very least forsession/promptrequests)?Having said that, I'm interested in additional markers/signals for a different reason. I'm looking to support broadcasted interactions (agent -> client). This would enable supporting flows like Claude's remote control in agent-shell.
@benbrandt is there a particular approach that's getting traction that would enable broadcasting session prompts to clients? I'd be happy to give it a try and see how well it works for a remote-control kind of flow.
denofevil commentedon Mar 6, 2026
@xenodium I believe you might be interested in #533 (already mentioned it here), it is basically covering agent to multiple clients scenario, your usecases might be important
docs: design doc for Zed↔Claude ACP event-flush-on-user-input bug
YOMXXX commentedon May 18, 2026
+1 to a protocol-level signal — we hit exactly this race in slopus/happy and ended up shipping a client-side workaround in slopus/happy#1287: a two-signal state machine on the client that tracks
responseReceivedandupdatesSettledindependently, plus aPOST_RESPONSE_GRACE_MS(500ms) fallback timer that closes the turn when the RPC response arrives but no further updates ever show up (the "empty turn" / response-first race).In practice we did see agents flush the
promptresponse before the trailingsession/update(Codex through the bridge was the reproducible one for us), so the assumption "updates arrive last" really does fail in the wild and the heuristic-sleep approach has the failure modes the OP describes. Our fake-timer tests pin down four distinct orderings — spec ordering / response-first / empty turn / tool-complete-before-response — and a re-entrant turn case for completeness.Between the two options in this issue: a first-class
turn_completenotification (option 1) would let us delete the entire state machine and the grace timer. A flag onPromptResponse(option 2) would also work but is slightly worse because it conflates "the server believes the turn is done" with the actual flush of in-flightsession/updatenotifications — clients would still need a buffer/queue to handle the response-arrives-first case unless the transport guarantees strict ordering. So we'd lean toward option 1 (dedicated notification, sent as the lastsession/updateof the turn).Happy to help draft the spec PR + a reference SDK implementation if useful.
ivebenfreed commentedon Aug 1, 2026
One interaction worth folding into the design here: if a backgrounded tool call can settle after
prompt()returns, itstool_call_updatewould arrive after the turn — which would make an unconditionalturn_completesignal inaccurate rather than merely early.Either backgrounded tool calls need to be excluded from the completeness guarantee, or the signal means "all updates for the foreground turn" rather than "all updates for this session's work". Raised separately as #1847, since it may be a question about
ToolCallStatussemantics rather than about this signal.benbrandt commentedon Oct 12, 2026
This is addressed by the idle state update in v2