anatomy

Taken apart.

Four things happen underneath this site, and none of them is complicated once it is drawn. Everything on this page can be operated, and every number it shows was measured on your machine while you were looking at it.

1 · The boundary

There is a line around your computer. Almost every AI feature you have ever used crosses it on every single request: your words go out to a server, a GPU somewhere runs the model, and the answer comes back. That is why those features need an API key, why they cost money per token, and why the company operating them can read what you typed.

Two shapes of request, compared across the edge of your machineIn the conventional shape, every prompt leaves your machine, crosses the network to a server and a datacentre GPU, and returns — a cost paid on every prompt. In the on-device shape nothing crosses the boundary at all; the model was downloaded once and now sits on your own disk.your machineeverything elseCONVENTIONALyouthe pagea servera GPUevery prompt, foreverON-DEVICEyouthe pagethe modeldownloaded onceGoogle, one time
The boundary is the whole argument. In the top lane every prompt you ever write crosses it. In the bottom lane the crossing happens once, at install, and never again — which is why there is no key, no bill and nothing for this page to see.

Chrome changed the shape. Over the course of 2026 it distributed a language model to desktop installations directly — several gigabytes, fetched once from Google, then resident on your own disk. The Prompt API, stable since Chrome 148, is a door onto that local copy.

The consequences are unusually clean. There is no key because there is nothing to authenticate to. There is no cost per prompt because no request happens. This page cannot see what you ask it, not as a policy but as a matter of topology — the question never leaves the boundary.

The price is hardware. Chrome asks for at least 22GB free on the volume holding your profile, plus either more than 4GB of VRAM or a CPU fallback of 16GB of RAM and four cores. Fall short of any of those and the API reports the model unavailable, which is what the status bar on the front page is reading when it says so.

2 · What a server costs to ask

“It runs locally” is easy to say and hard to feel. So rather than describe the difference, here is the actual cost of the smallest possible request to a server, on your connection, right now.

What a server costs to ask

Seven requests for four bytes, to this site’s own origin, on your connection. The link is already open and the TLS handshake is already done, so this is close to the best case a network can give you — and it is spent before a model has read a single word.

No measurement taken yet.

Note what that number does not include. It is four bytes to an origin you are already connected to, with DNS resolved and TLS negotiated. A genuine inference request adds a fresh connection to a different host, authentication, a queue, the model’s own thinking time, and the whole journey back. The local path skips the entire measurement.

3 · What a tool call is made of

A tool call sounds like a large idea and is a small one: a name, some arguments, a schema those arguments must satisfy, and a function. The schema is the part people skim past, and it is the part doing the work — it is what stands between an agent’s guess and your application state.

Below is this site’s real validator and its real tools. Break the arguments on purpose: put a string where a number goes, invent a field, delete a required one, push the lamp past 100. Watch where it stops.

Edit it. Put a string where a number belongs, invent an argument, delete a required one, push the lamp past 100 — the refusals below are the site’s real validator, not a demonstration of one.

  1. parse

    Well-formed JSON object.

  2. validate

    Every argument matches the schema.

  3. execute·

    Ready. Nothing has run yet.

  4. log·

    Nothing recorded from here yet.

parse: pass. Well-formed JSON object. validate: pass. Every argument matches the schema. execute: pending. Ready. Nothing has run yet.

Every refusal you just produced was generated by the same function that guards the buttons on the front page and the tools handed to WebMCP. There is one validator, and it does not know or care who is calling.

4 · The handoff

Until very recently, an agent operating a website did it the way a person would, badly: read the rendered page, infer what the controls probably mean, guess a selector, simulate a click. It works until a class name changes.

How an agent operates a page, before and after WebMCPBefore: the agent reads the rendered page, infers what the controls mean, guesses at selectors and simulates clicks — a chain that breaks whenever the markup changes. After: the page declares typed tools and the agent calls one directly, with no interpretation step.BEFORE — INFERENCEagentscreenshotguess intentfind selectorclickfour places to be wrong · breaks when the markup movesAFTER — DECLARATIONagentnavigator.modelContextthe toolhere is what I can dotyped call
The top row is how agents work on almost every site today, and every arrow is a place to be wrong. The bottom row removes the interpretation step entirely: the page says what it can do, in types, and the agent calls it.

WebMCP replaces the guessing with a declaration. navigator.modelContext lets a page register tools — a name, a description written for something with no eyes, a JSON Schema, and a function. The agent receives that list and calls one directly.

It is in origin trial from Chrome 149 to 156 and the shape has already moved once: provideContext replaces the whole tool set, while registerTool and unregisterTool add and remove them individually. This site prefers the first, because replacing is idempotent and it owns every tool it declares.

5 · Who is allowed to do this

Two things are worth knowing before anyone builds this into something that matters.

A tool call needs an open tab. Nothing here runs headlessly. An agent cannot reach these tools without a browser sitting on this page, which also means there is no background surface to attack.

The page is a shared room. Because provideContext clears the existing set before installing a new one, any script running on the page can replace your tools with its own — and on a normal commercial site that means analytics tags, ad scripts, chat widgets and partner embeds all have the same power you do. It is a live discussion in the spec rather than a settled matter.

It does not arise here, and not by luck: this site loads no third-party script of any kind. No analytics, no tag manager, no embeds, no fonts from a CDN. The room has one occupant.

Sources