Skip to content

await_control.notes

kubed-io[bot] edited this page Oct 29, 2026 · 3 revisions

When to call it

When a call is refused because a person holds the browser in the admin's Live tab — a 409 over HTTP, a tool error over MCP, saying who and since when — or when a result's control field says a person asked for it or holds it. Call it instead of retrying: every call that would change the browser is refused the same way until they hand back. Reads of the page as it is still answer.

Tasks, or a blocking call with a cap

Over MCP the tool supports background tasks (optional, polled every second). A client that negotiates them gets a task, which waits as long as the person takes; tasks/cancel stops the wait and changes nothing for the person.

A client that does not gets a blocking call. It sends a progress notification every 15 seconds, and at live.await_cap (default 90 seconds, no lower than 30) answers normally — not as an error — with handed_back: false and still in <who>'s control; call again. Call it again until it hands back. The cap sits under Claude Code's two-minute move of a slow call to the background.

POST /browser/await-control is a long poll with the same cap and the same answer.

Through agentgateway

agentgateway v1.6.0 passes MCP Tasks through: per its source, it routes tasks/get, tasks/update and tasks/cancel. It strips the tasks extension from a client on the older protocol, which therefore gets the blocking call. The blocking answer is streamed, so the gateway's backendRequestTimeout does not cut it off.

A task's worker has no request, so the workspace it waits for is the one named when it was submitted. Behind the gateway that is the Sf-Workspace header.

What the answer means

  • page is the page the browser is on now. It is not the page-error hint other results carry under the same name.
  • visited is in the order they were reached. Titles are read just after each page is reached, so on a single-page app a title may still be the previous route's.
  • Nothing here is written to History; the next call records the page as any call does.
  • With nobody in control it answers at once: a hand-back the agent had not been told of yet, or control: null with the page when a browser is open.
  • If the server stops while a call waits, the call usually just ends with the connection; one still running answers the server is stopping: call await_control again once it is back. Either way, call it again once the server is back. Who held Control is forgotten with the process.

Not a flow step

A flow cannot wait for a person. A step refused for control stops the run, whatever its onError, and whoever started the run calls await_control.

Clone this wiki locally