Report a surface-owned tool call to the surface - #77
Open
rhlsthrm wants to merge 1 commit into
Open
Conversation
agent-langgraph ends a run when the model calls a tool the surface owns, rather than inventing a result for it. That is the right shape: the run finishes, the browser acts, and the next run carries the result back. But the TOOL_CALL_* events were only sent from the branch watching the node that executes this deployment's own tools, and an ending run never enters that node. The assembled call sat in `pending` and was dropped, so the run was a clean RUN_STARTED/RUN_FINISHED pair carrying nothing: no answer under the person's message, no call for the surface to execute, and no error, because an empty run is not one. Drained before the run finishes now, without a result. Producing that is the surface's half, and it begins the next run holding it. `finalMessage` goes with it: it was written twice and never read, which is what was left after the events it was collected for were not sent.
rhlsthrm
requested review from
MikeRyanDev,
davidmckayv,
guidovizoso and
tylerslaton
as code owners
August 21, 2026 08:16
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.
What this changes
agent-langgraphends a run when the model calls a tool the surface owns, which is the right shape and is documented as such in the conditional edge: the run finishes, the browser acts, and the surface starts the next run with the result in hand.The
TOOL_CALL_*events were only sent from the branch watchingon_chain_endfor thetoolsnode — the node that executes this deployment's own tools, and precisely the node an ending run skips. So the assembled call sat inpendingand was never emitted. The run was a cleanRUN_STARTED/RUN_FINISHEDpair carrying nothing at all: the person's message with no answer under it, no tool call for the surface to execute, and no explanation, because an empty run is not an error by the protocol and the stopped-turn banner only fires onRUN_ERROR.Every browser action was affected, since all of them are
useFrontendToolregistrations: opening a page, filling a form, asking for help at a sign-in. As the default/botagent isrisk-analyst, which points at this Bot, that is the first thing a fresh clone tries.The fix drains
pendingbeforeRUN_FINISHED, emittingTOOL_CALL_START/ARGS/ENDand no result — producing the result is the surface's half, and it begins the next run holding it.finalMessageis removed with it: it was written twice and never read, which is what was left behind when the events it was accumulated for were not sent.Where it runs
pendingis per-run, inside the stream's own closure, and is now emptied before the run ends rather than being left populated.Boundary and audit
Changelog
Unreleased→Fixed.Proof
Local stack on this commit,
COMPUTER_SUPERVISOR_URLset so each Bot gets its own container.Before, three times over, on
/bot(default agent, sorisk-analyst): "Open news.ycombinator.com and tell me the top story", "Use your browser to open https://example.com and tell me the exact h1 text", and a third variation. Each produced no assistant message, nocomputer.*row inaudit_events, and no computer container. Plain prose turns on the same Bot answered normally, so the transport was fine.After: same Bot, "Open https://example.com on your computer and quote its h1 exactly" → the live screen renders the page and the answer is
"Example Domain".audit_eventshas the matching row:and no failure row beside it.
openbot-computer-risk-analystwas deleted before the run, so that container was also built from nothing during it.