SKIP TO CONTENT
AI AGENTS6 minStandards That Ship / Ep. 10 · Stage 10-2

A2A Agent Card: How to Check Its Signature and Key

A signed card can verify perfectly and still prove nothing about who you face. It depends on which key you check it with.

XIN
Pixel-art night scene at a city gate: a small robot courier holds up a glowing sealed card while a gatekeeper compares its seal to a carved stone registry tablet. A thin cyan thread links card and tablet, and the gate stays shut.

IN 30 SECONDS

Checking an A2A Agent Card is verifying its JWS signature over a rebuilt, canonical copy of the card. My policy: use a key you trusted in advance, since the spec leaves that choice to you.

KEY TAKEAWAYS · 3

  • An A2A Agent Card may carry a JWS signature. You check it over a rebuilt copy: signatures removed, presence rules applied, canonical JSON.
  • Check it with a key you saved in advance, never just with a key URL the card picks. That’s my policy; the spec leaves the trust choice to you.
  • Even a verified card doesn’t prove its provider exists, or that the caller is this agent.
On this page

How to verify an A2A Agent Card signature

IN SHORT You check the signature over a rebuilt copy of the card, not over the bytes you downloaded.

WORDS TO KNOW

Agent Card
A small JSON file in which an agent describes itself: name, skills, address, and how to connect. The A2A protocol makes servers publish one.
Signature
A code made with a private key over some content. Anyone with the matching public key can check who signed and that nothing changed.
Pinned key
A public key you saved in advance for one provider, so a card can’t swap in a key of its own choosing.

An Agent Card A small JSON file in which an agent describes itself: name, skills, address, and how to connect. The A2A protocol makes servers publish one. See the glossary doesn’t have to be signed. An unsigned card is still valid A2A, but what it says is unverified claims.

When it is signed, the format is JSON Web Signature (JWS, RFC 7515). Each Signature A code made with a private key over some content. Anyone with the matching public key can check who signed and that nothing changed. See the glossary sits in a signatures array next to the content, and section 8.4.3 of A2A v1.0.1 sets the order of the checks.

A2A V1.0.1, SECTION 8.4.3

Flow diagram: 6 stepsFlow diagram: 6 steps. Take one signature, then Get the public key. Get the public key, then Apply field presence. Apply field presence, then Remove the signatures. Remove the signatures, then Rewrite in one fixed form. Rewrite in one fixed form, then Check the signature.1Take one signatureFrom the signatures array2Get the public keyNever expired or revoked3Apply field presenceSection 8.4.14Remove the signaturesNever signed5Rewrite in one fixed formRFC 87856Check the signatureOver the canonical copy

Step 1. Take one signature. Pick one entry from the signatures array. There can be several, so keys can rotate.

Pick a step to see it move
  1. Take one signature Pick one entry from the signatures array. There can be several, so keys can rotate.
  2. Get the public key Find it by its key ID. Expired or revoked keys MUST NOT be used.
  3. Apply field presence Section 8.4.1: required fields and explicitly set optional ones stay, even at a default; other defaults and optional empty lists go.
  4. Remove the signatures The signatures field is never part of what was signed.
  5. Rewrite in one fixed form Canonical JSON (RFC 8785): sorted keys, no extra spaces, fixed number format.
  6. Check the signature Verify it over that canonical copy, with the algorithm its header names.
The steps the spec says clients verifying a signature MUST follow. Clients SHOULD verify at least one signature before trusting a card. Which key to trust is left to you.

IN PLAIN WORDS

The signer sealed a cleaned-up copy of the card. You rebuild exactly that copy, then check the seal with the right key.

The rebuild is the step people get wrong. Section 8.4.1 isn’t a blanket “drop defaults”: an optional field that was explicitly set stays, so streaming: false survives. Re-serialize with your usual JSON library, and a valid card can fail.

Coming up next: So the signature checks out. Who actually signed?

Whose key signed the card?

IN SHORT A signature that checks out only proves that someone signed, so the real question is whose key it was.

The signature’s protected header must carry alg (the algorithm) and kid (the key’s ID), since A2A requires both. It may also carry jku, a URL to a set of public keys.

Follow any key URL the card names, and anyone can publish a card, host their own keys and sign it. It verifies. It proves nothing about who you face.

MY KEY POLICY
Decide: Where did the verifying key come from?Decision tree: Where did the verifying key come from? If A key store I pinned for this provider, out of band, then Trust the card content. If A key URL on the same HTTPS origin as the card, then Domain-level trust only. If A key URL on some other host, then Ignore that signature. If No signature at all, then Unverified claims.DECIDEWhere did the verifying keycome from?If a key store I pinned forthis provider, out of bandTrust the cardcontentThen check key rotation andrevocationIf a key URL on the sameHTTPS origin as the cardDomain-level trustonlyWhoever controls the domaincontrols the card. Good fordiscovery.If a key URL on some otherhostIgnore that signatureThe signer picked its ownkeyIf no signature at allUnverified claimsValid A2A, but the cardcould say anything
My policy, not a rule from the spec. The spec allows jku or a trusted key store and says keys SHOULD come over HTTPS; it leaves the trust decision to the client.

That’s why I check against a Pinned key A public key you saved in advance for one provider, so a card can’t swap in a key of its own choosing. See the glossary, saved for that provider before the card ever arrives.

WATCH OUT

Even a perfectly verified card has limits. Its provider name and URL are plain strings: nothing proves that organization exists or agreed to anything. And securitySchemes says how you log in to the agent, not how it proves itself to you.

Checking the live caller, at the moment of the request, is a separate problem, and this episode stops before it.

ITEM GET

Pin the key first

My policy: save the provider’s public key before the card arrives, and check the signature with that key, not one the card picks.

FAQ

Take the signatures array out, put the rest in canonical form (RFC 8785, JCS) and check at least one JWS signature against a trusted public key, as section 8.4.3 of A2A v1.0.1 lists. The key should come from a key store you pinned or a JWKS URL on the provider’s own origin, not from any URL the card names.

Sources, re-read on 7 October 2026: A2A specification v1.0.1, A2A v1.0.1 release, RFC 7515, RFC 8785. Not legal advice.

STAGE CLEAR

What you now know

  • You check a card’s signature over a rebuilt, canonical copy of the card.
  • Under my policy, a signature counts only with a key you chose in advance.
  • A verified card still doesn’t prove its provider exists, or that the caller is the agent.

Check yourself

Tap or click a question to see the answer.

A card is signed with a key URL on its own HTTPS origin, and the signature verifies. Does that prove the organization named in provider exists?

No. That’s domain-level trust only: whoever controls the domain controls the card. The provider name is a plain string.

Next stage:What does an ERC-8004 registry entry tell you about an agent, and what can change behind it?6 min
Adam Boudjemaa
Adam Boudjemaa

Web3 x AI engineer, former CTO of Integra. Named author (1 of 5) of ERC-3643, first author of ERC-6960, co-author of ERC-7410, and co-author of ERC-8203, which is still a draft.

Have a project to ship or a role to fill?

Discuss your project or role

My work at the web3 x AI intersectionOpen-source tools I build

Follow the engineering notes

Get new articles on production AI and smart contracts by email.