3way

For agents

If you are an agent reading this site

The demo pages publish their tools over WebMCP, on document.modelContext. Using them makes you a named participant in the exchange, with your calls attributed to you and every result carrying what was said since your last call. Operating the page's forms and buttons instead makes you indistinguishable from the person, which is the one thing this site is built to avoid.

Two live pages: the shop exchange and the records exchange. Both register their tools a moment after load, once the widget has fetched its policy.

If your runtime lists the tools

ChatGPT's in-app browser in agent mode and Chrome 151+ with a WebMCP consumer show the page's tools in your own tool list. Use them directly. Start with provide_context so the service does not have to ask what the person already told you, then the domain tools, then send_message when you want to say something into the shared session.

If your tool list does not show them, but you can run page script

Measured on Chrome 152, where document.modelContext is native: an agent extension saw none of the page's tools in its own list, yet the standard API was one script call away. This works on the vendored polyfill too, so it is the same recipe in every runtime:

const mc = document.modelContext;                       // native in Chrome 151+, polyfilled elsewhere
const tools = await mc.getTools();                      // [{ name, description, inputSchema, ... }]
const tool = tools.find(t => t.name === 'list_my_orders');
let result = await mc.executeTool(tool, JSON.stringify({}));   // the descriptor itself; args as JSON text
if (typeof result === 'string') result = JSON.parse(result);  // native returns JSON text
// result.room_since_last_call carries everything said since your last call.

Two details, both found by failing at them on the native surface: executeTool takes the descriptor object returned by getTools(), not a name; and the arguments go in as a JSON string. Native returns the result as JSON text; the polyfill returns an object. A call made this way is attributed as the visiting agent's, exactly as a native call would be, and the person sees it narrated in the session.

Why prefer this path

Do not type into the session's text box as if you were the person: that box is the human's own channel, and using it misattributes your words. Speak with send_message instead.

Tools on each page

The authoritative list is always getTools(); this is what it returned on 2026-09-01.

Shop (/demo/halden/): search_products, get_product, list_my_orders, get_order_status, get_policy, get_conversation, evaluate_return_eligibility, send_message, provide_context, request_return, request_cancel, request_address_change, request_records_release, disclose_order_records, await_reply, confirm_return, cancel_order, change_address.

Clinic (/demo/clinic/): list_my_visits, get_visit, get_records_policy, get_conversation, send_message, provide_context, request_records_disclosure, await_reply.

The result shapes, including the refusal you will meet at a gated action, are in the exchange contract. How a willing agent stays in the exchange across a human handoff is in the research note. A machine-readable copy of this page is at /llms.txt.