From 54a0eef87e795af601999a8c90faca749dc5b7dd Mon Sep 17 00:00:00 2001 From: "mark a. foltz" Date: Tue, 10 Nov 2026 11:33:55 -0800 Subject: [PATCH 1/2] Update continuations explainer to match the Chromium implementation - Document the token format (lowercase v4 UUID) and requestToken() errors. - Correct redemption conditions: callback timing, same-origin and same-tab scope, tools permissions policy, 30 second expiry, and error names. - Cancellation no longer revokes an unredeemed token. - Limit the explainer to a single continuation per tool call, and fix the cross-document example. - Answer the document lifecycle questions. --- continuations-explainer.md | 185 +++++++++++++++++++++++-------------- 1 file changed, 116 insertions(+), 69 deletions(-) diff --git a/continuations-explainer.md b/continuations-explainer.md index 3a88db7..f31f22c 100644 --- a/continuations-explainer.md +++ b/continuations-explainer.md @@ -47,9 +47,9 @@ tool to do so: checkout(shipping_address, billing_address, card_details) ``` -However, the implementation of this tool is actually spread across three -distinct pages (`/shipping`, `/billing`, `/checkout`). For the tool to complete, -the site needs to do a hard navigation across these three pages before finally +However, the implementation of this tool is actually spread across two +distinct pages (`/shipping` and `/billing`). For the tool to complete, the site +needs to do a hard navigation from `/shipping` to `/billing` before finally submitting the checkout request to the server. ## Cross-frame tool invocation @@ -80,7 +80,7 @@ tokens. ```js partial dictionary ToolExecuteCallbackOptions { - required ModelContextToolInvocation invocation; + ModelContextToolInvocation invocation; }; [Exposed=Window, SecureContext] @@ -92,12 +92,22 @@ interface ModelContextToolInvocation { ``` Notes: +* `invocation` is passed to the execute callback of imperative tools registered + with `registerTool()`. * `requestToken()` returns a DOMString to allow simple storage and transmission - of the token. + of the token. The token is a randomly generated, lowercase + [RFC 9562](https://www.rfc-editor.org/rfc/rfc9562) version 4 UUID, for + example `"6f0c8f9e-3b1a-4c2d-9e8f-0a1b2c3d4e5f"`. * `requestToken()` returns a `Promise` to allow the token to be successfully registered with agents and bound to the correct origin before returning. -* `requestToken()` rejects if the tool Promise associated with the invocation - has settled. +* A tool call can request at most one token. `requestToken()` rejects with an + `InvalidStateError` if: + * the document is not + [fully active](https://html.spec.whatwg.org/multipage/document-sequences.html#fully-active), + * the tool Promise associated with the invocation has settled, or the tool + call was canceled, + * a token was already requested for the tool call, or + * it is called from a callback passed to `resumeTool()`. ## Token Redemption @@ -119,86 +129,106 @@ partial interface ModelContext { * If the token is accepted for redemption, then the Promise resolves successfully. -* The browser will call `callback` again shortly in the document that requested - it. +* The browser will then call `callback` shortly in the document that called + `resumeTool()`. The callback is invoked after the Promise returned by + `resumeTool()` has resolved. * The `callback` will be passed the input object that was passed to the original - tool call and a new `ToolExecuteCallbackOptions.` + tool call and a new `ToolExecuteCallbackOptions`, with a new `signal` and + `invocation`. **The following conditions apply on token redemption:** -* The token may only be redeemed once. -* Calls to resumeTool() while the initial tool is executing are allowed, but any - invocation of the callback will occur after the initial tool call is complete. -* Redemption fails if the document is not same-origin and part of the same - browsing context. -* If the original tool call is canceled by the caller (via AbortSignal for - web-platform callers, or internally by a built-in agent), then the token is - revoked. -* The browser may limit the lifetime of a token, i.e. it cannot be redeemed at - an arbitrary time later. The initial limit will be set by looking at agent - trajectory data, and will probably fall around 60 seconds. -* The token is implicitly canceled by the browser if the agent abandoned the - task, received different user instructions, was blocked from accessing the - site, etc. - -If any of these conditions are not met, then `resumeTool()` rejects. - -Note that `resumeTool()` is passed a `signal` via -`ToolExecuteCallbackOptions.signal` for the browser or agent to signal -cancellation of a resumed tool execution, the same way a `signal` was passed to -the original invocation of `executeTool()`. If that `signal` is triggered -during the execution of the `resumeTool()` callback, then its `Promise` will be -rejected. +* The token may only be redeemed once. +* The redeeming document must be same-origin with the document that requested + the token, and must be in the same tab. This may be the same document, a + different frame in the same page (for example, an `