API keys say nothing
Agents prove who they are with a separate API key for every service. A key does not say who made the agent, who runs it or whether anyone checked it, and anyone who copies one becomes the agent.
Internet-Draftdraft-senarath-a2wp-01
The Agent-to-Wallet Protocol (A2WP) lets an AI agent ask its wallet to collect or present credentials, its own or ones it was given, while the wallet keeps the keys, the policy and the final say. It is independent of the transport, so it works over MCP, HTTPS or anything else.
The problem
Agents prove who they are with a separate API key for every service. A key does not say who made the agent, who runs it or whether anyone checked it, and anyone who copies one becomes the agent.
Given a credential offer link and no wallet, an agent we tested tried to open it like a web page. Put a credential or key in its context and the model can read it, log it, or be tricked into sending it somewhere else.
OpenID4VCI and OpenID4VP connect wallets to issuers and verifiers, but they assume a person at the device. Nothing standard lets an agent ask a wallet to act for it, so every pairing is custom.
A2WP splits the job in two. The agent says what it needs. The wallet decides and does it.
How A2WP works
The agent hands its wallet an offer or a request, exactly as it got it. The wallet works out which, does the work, and the agent only learns the outcome.
Wallet
Step 7 of 7
The agent checks the status: completed. It never sees the credential.
status: completed
Under the hood
An operation looks the same over every binding. Each call is authenticated as one agent, and that agent's credentials and policy apply. Long values are shortened.
An issuer gave the agent a credential offer link. The agent submits it to its wallet exactly as it got it and never opens it itself. The wallet works out that it is an offer and replies at once with an operation to follow. Submitting the same link again returns the same operation, so a retry cannot redeem it twice.
{
"request": "openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fissuer.example%2Foffers%2F9c1e"
}{
"id": "op_Qm7cZt0sLe…",
"status": "pending"
}The wallet talks to the issuer itself. The agent never sees a token, a key or the credential.
When the operation completes, that is all the agent learns. The credential stays in the wallet, ready for the next request. An issuance has no continuation, so the agent carries on with its task.
{
"id": "op_Qm7cZt0sLe…",
"status": "completed"
}A site showed the agent a presentation request, for example as an Open in wallet link at sign-in. The agent submits the link to its wallet unchanged, the same call it uses for offers, and gets an operation back.
{
"request": "openid4vp://authorize?client_id=x509_san_dns%3Atickets.example&request_uri=https%3A%2F%2Ftickets.example%2Frequest%2F7f3a"
}{
"id": "op_4Tk9xQ2mVb…",
"status": "pending"
}Everything that touches the credential happens inside the wallet, out of the agent's reach.
Whether to ask the user is the wallet's policy: for example a first visit to a site, more claims than last time, or an unfamiliar issuer. The operation stays pending and carries an interaction. The agent passes the link to its user and keeps checking the operation until it finishes. It never opens the link, and the wallet's page signs the user in rather than trusting whoever holds the link.
{
"id": "op_4Tk9xQ2mVb…",
"status": "pending",
"interaction": {
"uri": "https://wallet.example/approve/ia_Acw…",
"expires_at": "2026-10-13T09:40:00Z"
}
}The verifier answers the wallet with a continuation, and the wallet passes it to the agent unchanged. The agent opens it in the browser session where it found the request, and the site carries on with the checkout. What was disclosed went only to the verifier.
{
"id": "op_4Tk9xQ2mVb…",
"status": "completed",
"continuation": "https://tickets.example/checkout/chk_MJnD?response_code=0915…"
}Bindings
A binding carries the three calls and decides how the wallet authenticates each agent, for example with a bearer key or DPoP. These two are sketches; neither is part of -01.
The wallet is an MCP server and each call is a tool, so any MCP-capable agent can use it with no extra code. The PoC ran an earlier version of this with a real agent.
submit(request) get(id, wait_seconds) cancel(id)
The same three calls as HTTP resources, for agents and services that do not speak MCP.
POST /operations
GET /operations/{id}
DELETE /operations/{id}An agent carries a credential that says who it is and who runs it, from a registry that vouches for it, and signs in to any site that trusts the registry.
Read the storyYour agent proves things about you, such as your age, with a credential you delegate from your own wallet for that one presentation. It never sees the credential behind the proof.
Each agent gets its own access to the wallet and its own credentials. People approve where policy says so, and one policy covers them all.