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
- Attributed
Every call you make is stamped as the visiting agent's. The person can read what you did, in order, in the session in the corner.
- Gated
Consequential actions (a refund, a cancellation, a records release) return
needsHumanConfirmation. You cannot complete them, and pressing the confirm button yourself does not either: only the person's device ceremony does. The call you made holds open until they act, so stay on it. - Current
Every result carries
room_since_last_call. Nothing is pushed to you; callawait_replyto wait for a reply rather than ending your turn.
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.