Skip to content

Cross-document tool response mechanism #135

Open

Description

@domfarolino

Should the agent receive a response from the next page, after a declarative <form> tool navigates? This is mostly a follow-up to #76 (comment) and #76 (comment), where the whole concept of using the form target page's <script type=application/ld+json> contents as the tool's response, and possible using the entire HTML page as a back-up if the JSON-LD doesn't exist.

This whole mechanism came about after discussion about how agents ingest structured data like markdown and JSON better than HTML, and when an agent actuates a declarative tool that triggers a navigation. We considered introducing a new script type in the target page that contained structured data representing the target page's contents, but then realized that many of the target pages would have this already in the form of JSON-LD, so we considered re-using this.

But some good alternatives that were discussed are:

  • A <context>, <resource>, or other kind of purpose-built element to shuttle target-page data to the tool that triggered the navigation
  • A simple, standardized "the navigation succeeded" message, with no information specific to the target page
  • Unconditionally the full HTML response to the agent as the tool's "response"

I will note that this relates to #9, since the task of defining an output schema for a form tool is tricky, so connecting the form to the shape of data on the other side of the navigation is something to consider.

Activity

  1. anssiko commented on Apr 16, 2026

    @anssiko
    Member

    RESOLUTION: Explore <context> element without committing to form submission response with it. (issue #135)

  2. self-assigned this
    on Sep 23, 2026
  3. markafoltz commented on Sep 29, 2026

    @markafoltz
    Collaborator

    I have added a PR with an explainer to add tool continuations to allow cross-document tool calling in #327. PTAL.

  4. anssiko commented on Oct 1, 2026

    @anssiko
    Member

    RESOLUTION: The group explores the Continuation Tokens design outlined in the explainer and welcomes further feedback. (issue #135 and PR #327)

  5. markafoltz commented on Oct 2, 2026

    @markafoltz
    Collaborator

    @sushraja-msft You mentioned in the meeting on Thursday that you had a version of this that exposed partial outputs to subsequent tool calling steps. Do you mind sharing more about the motivations for that and what API shape you were thinking of? Was the agent able to observe the intermediate outputs, or only the final output?

    We also considered this, but didn't see a compelling need for it. I believe intermediate output chaining can be added in a backwards-compatible way as well.

  6. domfarolino commented on Oct 3, 2026

    @domfarolino
    CollaboratorAuthor

    @sushraja-msft You mentioned in the meeting on Thursday that you had a version of this that exposed partial outputs to subsequent tool calling steps. Do you mind sharing more about the motivations for that and what API shape you were thinking of?

    I understood it to be a higher-level way of directing the agent to participate in the continuation, sort of like Alex Jose's proposal of passing the continuation ID/request to the model itself and hoping it re-invokes the tool on the next page to simulate the continuation. If it's just then, then I would hope the current proposal covers everything there. Otherwise, I would love to hear if this proposal is lacking something that MSFT's first stab had and see how we might reconcile that!

  7. sushraja-msft commented on Oct 5, 2026

    @sushraja-msft
    Collaborator

    Our prototype was designed for the imperative WebMCP proposal, where a tool invocation on one page may trigger a navigation, and the destination page must perform additional work before the final tool result can be returned.

    In this model, a tool on the source page could return:

    {
    "continueAfterNavigation": true,
    "continuation": { ...state... }
    }

    The browser would then wait for the navigation to complete and for WebMCP tools to be registered on the destination page. It would invoke the same tool again on the destination page, passing along the continuation state. If that invocation completes without setting continueAfterNavigation, its result would be returned to the model.

    This orchestration is transparent to the model, but visible at the WebMCP API layer.

    Motivations for this design

    • Keep continuation state within WebMCP. Applications should not need to transport continuation state through side channels. Tools may come from shared libraries or third parties, and requiring them to use mechanisms such as URL parameters can create conflicts with existing application behavior or parameter usage.

    • Support existing JavaScript workflows that cannot persist state externally. A tool may simply invoke existing application logic and have no opportunity to store state through a side channel. For example, a tool might populate a set of form fields, post a message to trigger form submission, and then return:{ "continueAfterNavigation": true }. The tool cannot modify the form submission itself, nor can it inject state into the navigation. However, it still needs to resume execution after the destination page loads so it can inspect the resulting page and return information such as an arrival date. Encapsulating the continuation within WebMCP enables this scenario without requiring changes to the application's navigation flow.

  8. markafoltz commented on Oct 6, 2026

    @markafoltz
    Collaborator

    Thank you for the detailed explanation.

    Two main distinctions in the approach we are proposing and what you described above.

    1. The site requests a continuation through an explicit API, instead of returning a sentinel value in the tool output, that yields a unique token for that tool invocation.
    2. A site can handle the continued tool call without requiring re-registering the tool.

    For passing state from page to page, there are a number of options for the site. They can pass additional URL parameters, or they can pass only the token and use local storage keyed to that token to store and retrieve additional context for the tool continuation. In my mind, tools that are adapting existing site flows should already have the context they need in most cases.

    That being said, if there is a strong need for a new state-passing mechanism that can't be addressed with existing ones, it could easily be added as an extension to the ModelContextToolInvocation we pass to the continuation:

    partial interface ModelContextToolInvocation {
      // Output from previous calls to execute() or requestContinuation().
      readonly attribute DOMString output;    // Or possibly a sequence for multi-step continuations.
    }
    

    For the second point, it doesn't always make sense to require tool re-registration, or to have the same callback used for new invocations and continuations. Two examples:

    • In a checkout flow, the final page of the flow is just showing a final confirmation that checkout succeeded. You wouldn't want the confirmation page to re-register checkout and the agent have the option to restart a checkout flow that already completed.
    • For a search results page, you want the continuation callback to handle providing the current search results to the agent, and a separate search_products tool registered that begins a new search. These are different functions, so makes sense to have distinct callbacks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions