A Tool Call Is Not an Authorization
What we built on top of WebMCP, and what we deliberately did not build
The retry that kills the sale
Picture an agent halfway through a checkout. It calls the merchant page’s checkout tool, gets a response, and then the laptop sleeps. The agent wakes up, finds its context gone, and asks the same question again.
If that second call spends the same authorization the first one did, the agent has just destroyed a valid purchase by being careful.
This failure is routine. Agents retry. They refresh context between turns, they lose sockets mid-request, and they very often want to show a user what’s about to happen before committing to it. Any design that treats “is this allowed?” and “claim this for a purchase” as the same call will eat retries for breakfast.
That’s the short version of what we found building on WebMCP. The interesting problem isn’t how the agent asks. It’s who answers.
What WebMCP actually gives you
WebMCP is a proposed browser API for exposing structured tools from a web page. A page registers a tool — checkout, say — with a name, a description, an input schema, and a function. An agent that supports the API discovers the tool and calls it with data that matches the schema.
That’s a real improvement. Today an agent shopping on your site is reverse-engineering a UI: guessing that the green button means continue, inferring a form’s shape from its layout, and breaking the first time you ship a redesign. WebMCP replaces the guess with a contract.
What it leaves out is the caller. The API describes the shape of a request. Four questions stay unanswered: which agent made it, who that agent works for, whether the wallet behind it can cover the amount, and whether the same authorization was already spent thirty seconds ago. A tool schema is a grammar, not a credential.
It’s also early. Chrome documents WebMCP as a proposed standard, currently reachable through an origin trial and a local development flag. Build on it. Keep your authorization model somewhere else.
For current API status and browser constraints, see the Chrome WebMCP documentation and the WebMCP proposal.
Where we draw the line: WebMCP describes the interaction. KYA records and evaluates delegated authority. The merchant and its payment processor still make the call.
Splitting the question in two
In our implementation, a browser agent uses the merchant page’s WebMCP tool to ask for a checkout preflight. The request carries a KYA signed trace, a cart reference, and a wallet reference. The trace names the agent and its operator, the audience it was minted for, the capability it grants, and the limits that bound it — amount, currency, expiry, number of uses.
The page never holds a KYA private key. It calls a same-origin merchant adapter, and the adapter calls us. Signing material stays in the merchant’s environment, and the request inherits whatever authentication and organization checks that environment already enforces.
Preflight is read-only. It answers the question without claiming the trace. Its response is short-lived, never returns the raw trace, and carries only what the page needs in order to explain the next step to a human. The cart travels as an opaque fingerprint rather than a copy of the merchant’s cart data.
So the agent in the opening scene can ask twice, or five times, and lose nothing. An accept here means eligible under the checks we ran at this moment. It goes stale, and capturing payment takes a separate authorization.
The checks a merchant can inspect:
- Which agent and operator the signed trace names.
- Which merchant audience and checkout capability it was minted for.
- Which amount, currency, expiry, and use limits apply.
- Whether the cart and wallet references match the request.
- Whether the trace is active and still available for checkout.
The decision happens on the server
When the merchant creates a checkout session, the server evaluates the request from scratch. It ignores the browser’s response, an earlier preflight, and any client-supplied claim that a trace was fine a minute ago.
It rechecks the current cart and wallet context, the trace status, audience, operator, capability, and limits. On session creation, the trace claim binds to that session, so a single-use trace is spent and a second session finds nothing left to claim. If a session was somehow created before the claim attached, the confirm path recovers and verifies it there.
Four outcomes come back: accept, review, decline, unverified. Unknown or inconsistent state fails closed. Everything the merchant already runs — fraud, payment, inventory, fulfillment — still runs afterward. We’re one input to that decision, not a replacement for it.
The separation that matters: preflight helps an agent explain what may happen. Checkout decides what does.
The second tool is deliberately boring
We also ship a KYA-hosted tool, kya_validate_trace, for a much smaller job: a browser-side self-check. It fetches our published public key directory and uses Web Crypto to verify the trace signature and claims. It reports whether the signature holds, whether the trace is inside its time window, and what scope and limits it declares.
And that’s all it reports. The output is a signature check, a time window, and a declared scope — trust scores, registry profiles, operator identity, and the status of unrelated agents all stay out of it. Authorization belongs to checkout, and the tool’s response says so in as many words: the self-check is advisory, and the checkout server decides on its own.
We kept it narrow on purpose. Verification tools get dangerous when a cryptographic check quietly inflates into a reputation claim. A valid signature tells you something precise about some bytes. It tells you nothing about whether you want this agent’s business.
What is not done
This is a repository slice rather than a finished merchant story. Three pieces are still open, and we’d call this a pilot only once they close:
- A merchant-owned
/_kya/verify-agentendpoint and a publishable adapter package. - A privacy-reviewed, rate-limited public self-check that can use registry data without turning a browser tool into a profile lookup.
- A live merchant pilot: migration applied, checkout path deployed, browser-to-payment evidence captured.
We’re listing those as release gates rather than footnotes, because the failure mode here is well documented. Code in a working tree proves the code exists; the migration still has to run. A green local test proves a local pass; the deployed checkout still has to enforce the same policy. A visible browser tool proves the tool is visible; the payment still has to be authorized safely.
Three questions worth asking your own stack
If you’re putting agent interaction anywhere near a checkout, here’s where we’d start:
- What exact action is the agent asking to perform?
- Which server makes the final authorization decision?
- What record explains that decision after the fact?
WebMCP is a good answer to the first. Signed traces and server-side checks are how we answer the second and third. Each of the three needs its own answer.
Making a website act as though every agent is trustworthy was never the goal. The goal is a legible conversation, with authorization kept explicit, bounded, and something you can go read later.