How your store knows which agent is calling (and why there are no API keys) Free & Pro
How a personal agent proves its identity to your store: a published address, public keys, signed requests and key-bound tokens, explained without the acronyms first.
Updated October 12, 2026
Most integrations start with a key: you generate one, hand it to the other side, and hope it stays secret. Agent Adapt has no keys to issue, and that is not a missing feature. The Personal Agent Protocol turns the usual arrangement round: the agent publishes its identity, and your store checks it. This guide explains how that works, in plain words first and with the standards named afterwards.
The idea in one paragraph
An agent has a name card: a small public document at an HTTPS address it controls, say https://assistant.example/agent.json, giving its name, its logo and the address of its public keys. That address is the agent’s identity. When the agent wants to visit your store it signs a request with the matching private key, which only it has. Your store fetches the name card and the public keys from the agent’s address, checks the signature, and knows two things for certain: this request came from whoever controls that address, and nobody who merely copied the request can send it again.
What your store checks, every time
- The address is HTTPS and resolves to a document that names itself. The document’s own
client_idfield must equal the address it was fetched from. The key address and any redirect addresses must be on the same domain. Your store refuses to fetch from private or local network addresses, caps the size and follows only a few redirects. - The signature is good. The agent signs a short statement saying who it is, which store it is talking to and when. Your store verifies it against the agent’s published keys only, never against a key included in the request. Only ES256 and RS256 are accepted;
noneand shared-secret algorithms are refused. - It is fresh and unused. The statement must be at most five minutes old and carry an ID the store has never seen. A replayed request is refused.
- The agent is not blocked. If you pressed Block, every request from that address is refused from that moment.
Only then does the store hand back a token for the visit.
Why a stolen token is not enough
The token itself is bound to a second key the agent generates for this customer at this store. Every API call carries a signed proof that the caller holds that key, naming the exact method and address being called and the token being used. A token copied from a log, a proxy or a crashed process does nothing without the key, and each proof is accepted once.
Your store never stores the token or the proof in a usable form. It keeps a one-way hash, enough to recognise the token when it comes back and useless to anyone who reads the database.
What this gives you as a merchant
- A name you can trust, within limits. The name and logo on WooCommerce → Agents come from the agent’s own document, but the address next to them is the real identity. Two agents cannot share an address unless they share the private key, and an impostor cannot use a well-known agent’s address without that key.
- Blocking that holds. Blocking is by address. The agent cannot pick a new one without publishing a new document somewhere else, and that new address is a new, unknown agent with no customer approvals.
- Nothing to leak. There is no key of yours that an agent could lose. The secrets are all the agent’s.
- Nothing to manage. Agents arrive, prove themselves and appear. You block the ones you don’t want. With Pro, you can invert that and accept only the ones you tick.
What it does not prove
It proves which agent is calling. It does not prove the agent is well behaved, or that the company behind it is who it says it is beyond controlling the domain. A domain name is a useful identity, in the way a business’s website address is, and no more. Judge agents by the domain, and block any you don’t trust.
Key rotation
Agents are expected to rotate keys. Each published key has an ID, and when your store sees a signature from a key ID it does not know, it fetches the agent’s keys again, once, within rate limits. Published documents are cached for up to a day, so a key the agent removes stops working within a day at most.
The standards behind it
For developers and the curious. The name card is an OAuth client metadata document, and its address is the client_id. The signed statement is a client assertion with private_key_jwt authentication (RFC 7523), verified against the agent’s JWKS (jwks_uri). The visit is started with the JWT bearer grant, and the key-bound token is DPoP (RFC 9449). Token revocation is RFC 7009. Agent Adapt’s OAuth server metadata (RFC 8414) lists all of it at /.well-known/oauth-authorization-server/agent-adapt on your store. The full details for agent developers are on the developers page.
Common questions
Can I give a particular agent an API key instead?
No, and nothing in the protocol needs one. If you want to limit which agents your store accepts, block the ones you don’t want, or with Pro switch on the allowlist and tick the ones you do.
Could someone register a look-alike domain and pretend to be a known agent?
They could publish an agent at assistant-example.com with the same name and logo as assistant.example. The address shown on your Agents screen and on the customer’s consent page would be the look-alike’s, which is exactly how a customer or a merchant would tell them apart. The protocol makes impersonation visible rather than impossible, as domains do on the web generally.
Does my store call out to the agent on every request?
No. It fetches the agent’s documents when it first sees the agent, caches them for up to a day, and refetches the keys once when it sees an unknown key ID. Ordinary API calls are verified locally against the cached keys.
What does the agent learn about my store from all this?
Only what is public: your discovery documents and whatever it is allowed to read through the API. Your store sends nothing about your customers when it fetches an agent’s documents.
Still stuck? Email [email protected].