Agent Card validation errors explained, one by one
Validator output is only useful if you know which findings block interoperability and which are advice. This walks all six layers of checks in the order they run, with the trigger and the fix for every message — including the ones whose severity changes depending on what else is in your card.
How to read the output
Every check below comes from the A2A specification. Findings come in three severities, and the distinction is not cosmetic:
- Error — the card cannot do its job. A client either cannot parse it, cannot find your endpoint, or cannot tell what you do. Fix all of these before publishing.
- Warning — the card works but under-delivers, or it contains something that will bite you. Some warnings are trivial; one of them (an embedded credential) is the most serious thing the validator can find.
- Pass — a check that had something to confirm. An empty pass list on a card with no errors usually means the document is far thinner than you think.
Checks run in layers, and later layers assume earlier ones held. That is why fixing the first error often removes several others at once — and why working bottom-up wastes time.
Layer 0 — JSON that will not parse
Invalid JSON: Unexpected token } in JSON at position 412
Nothing else runs until this passes. In hand-written cards the cause is almost always one of three things: a trailing comma after the last item in an array or object, a smart quote pasted in from a document, or a raw newline inside a string literal. JSON allows none of them.
Multi-line descriptions are the usual culprit. If you want a long description, keep it on one logical line and let your editor soft-wrap it, or build the card from code rather than editing JSON by hand.
Layer 1 — pre-1.0 fields
Top-level "url" is a pre-1.0 field. A2A v1.0 moved it to supportedInterfaces[0].url.
Five top-level fields were relocated or renamed in v1.0. Finding any of them tells the validator this is a migration in progress, which changes how it reports everything downstream.
| Pre-1.0 field | Where it went |
|---|---|
url | supportedInterfaces[0].url |
preferredTransport | ordering of supportedInterfaces[] — first entry is preferred |
additionalInterfaces | further entries in supportedInterfaces[] |
protocolVersion | supportedInterfaces[].protocolVersion |
supportsAuthenticatedExtendedCard | capabilities.extendedAgentCard |
Layer 2 — identity
| Message | Severity | Fix |
|---|---|---|
Missing required identity field: name. | error | Add a name. Use the agent's product name, not a service id |
Missing required identity field: description. | error | Say what the agent does and when to route work to it |
| Description is present but short… | warning | Under 20 characters. Expand to include the boundary of what it will not do |
Missing required field: version. | error* | The version of your agent ("1.2.0"), not the protocol |
* downgraded to a warning on cards that still carry pre-1.0 fields, per the previous section.
The short-description warning is worth more than its severity suggests. This field is read by another agent's model to make a routing decision. "Invoice agent" is syntactically fine and practically useless; a description that names the inputs it expects and the cases it declines is what gets you correctly invoked — and, just as valuably, correctly skipped.
Layer 3 — interfaces and endpoints
This layer produces more errors than any other, because one array carries four separate requirements.
Missing service endpoint. A2A v1.0 requires supportedInterfaces[]
with at least one { url, protocolBinding, protocolVersion } entry.
Raised when there is no supportedInterfaces array and no legacy top-level
url to fall back on. This is the finding to fix first: without it, nothing can
address your agent at all.
| Message | Severity | Trigger and fix |
|---|---|---|
supportedInterfaces[0] must be an object. | error | A bare string in the array. Each entry is an object with three keys |
supportedInterfaces[0] is missing url. | error | Absolute URL of the endpoint, including scheme and path |
supportedInterfaces[0] is missing protocolBinding. | error | One of JSONRPC, GRPC, HTTP+JSON, or a custom binding URI |
| protocolBinding "REST" is not a core binding… | warning | Not a recognised value. Use HTTP+JSON, or identify a genuinely custom binding by URI |
supportedInterfaces[0] is missing protocolVersion. | error | The A2A version this endpoint speaks — "1.0", not your agent's version |
| Endpoint … is not a valid URL. | error | Usually a missing scheme (agents.example.com/a2a rather than https://agents.example.com/a2a) |
| Endpoint … is not HTTPS. | warning | Fine for localhost during development; the spec requires encrypted transport in production |
Layer 4 — capabilities and content modes
| Message | Severity | Fix |
|---|---|---|
Missing required field: capabilities. | error* | Add the object even if everything in it is false — its absence is ambiguous, its contents are not |
| capabilities.stateTransitionHistory is not part of A2A v1.0. | warning | Removed in v1.0. Delete it, or model the behaviour as an extension |
| defaultInputModes should list supported input media types… | warning | IANA media types, e.g. ["text/plain", "application/json"] |
| defaultOutputModes should list supported output media types… | warning | e.g. ["application/json"] |
The two mode fields are required by the specification but reported as warnings, and that gap is deliberate: a caller missing your mode list can still attempt a request and negotiate, whereas a caller missing your endpoint cannot do anything at all. Severity here tracks what breaks, not what the spec text says. Fix them anyway — guessing what to send is not a good first experience.
Layer 4b — skills
skills must include at least one skill describing what the agent can do.
A card with no skills describes an agent that accepts nothing. Then each skill is checked on four fields:
| Message | Severity | Fix |
|---|---|---|
skills[0] must be an object. | error | A bare string in the array |
skills[0] is missing id. | error | Stable machine identifier, kebab-case: order-investigation |
skills[0] is missing name. | error | Short human-readable label |
skills[0] is missing description. | error | What the skill takes and what it returns |
| skills[0] description is short… | warning | Under 20 characters. Add task boundaries and expected inputs |
skills[0] is missing tags. | error | A non-empty array. Required in v1.0 — tags drive skill discovery |
Missing tags is the most common error on real cards, because they were optional
in pre-1.0 drafts. Tag with the words someone searching for the capability would
use rather than your internal vocabulary:
["invoices", "reconciliation", "finance"], not ["fin-svc-v2"].
{
"id": "reconcile-payment-batch",
"name": "Reconcile a payment batch",
"description": "Given a bank statement export, match each line to an open
invoice and report exceptions with reasons.",
"tags": ["finance", "invoices", "reconciliation"],
"examples": ["Reconcile yesterday's ACH batch against open invoices."]
}
Layer 5 — security metadata
Authentication is not declared. Add securitySchemes and security requirements when the endpoint is not fully public.
Raised when the card declares neither securitySchemes nor security. That is
correct for a genuinely open agent and a serious omission for anything else — a
caller reading your card has no way to know a credential is needed until it gets
a 401 it did not plan for.
The card appears to contain an API key (sk-...). Agent Cards are public discovery documents; declare securitySchemes instead of embedding credentials.
This one is a warning by severity and an incident by consequence. The scan looks
for the recognisable shapes — sk-… keys, JWTs, AWS access key ids, GitHub
tokens, bearer headers — anywhere in the serialised document, including inside
descriptions and examples where they usually arrive by copy-paste.
Layer 6 — provider and signatures
| Message | Severity | Fix |
|---|---|---|
| provider metadata is missing. | warning | Add provider.organization and provider.url — directories and marketplaces use them to attribute your agent |
| provider.name is a pre-1.0 field. | warning | Renamed to provider.organization in v1.0 |
Nothing in this layer blocks a request, which is exactly why it gets skipped. It is also what a human decides with: an unsigned card from an unnamed provider is hard to justify approving in a partner review, however valid the JSON is.
If your card carries signatures, the validator confirms their presence as a
pass. Verifying them is a separate operation — a JWS over the card canonicalised
per RFC 8785 — but publishing them at
all signals that the document is meant to be checked.
Triage order
Work top-down. Each step assumes the previous one holds, so this order minimises re-runs:
- Make it parse. Nothing else runs until it does.
- Restructure the transport section. If pre-1.0 field warnings appear, fix
supportedInterfacesbefore anything else — it silently changes the severity of later findings. - Clear every error. Identity, interfaces, capabilities, skills. These are the interoperability blockers.
- Deal with any credential warning immediately, regardless of where it sits in the list.
- Close the remaining warnings. Modes, security declarations, provider metadata — each one is a question a caller would otherwise have to ask you.
- Check the live URL. Validation covers the document — including that it sits at the RFC 8615 well-known path; the well-known URL checker covers the delivery — path, status code and content type on your real domain.
Paste your card into the Agent Card validator to run all of these at once, or read the schema reference for the field-level detail behind any single message.
Frequently asked questions
My card passes validation but nothing discovers it. Why?
Validation checks the document, not the delivery. A perfectly valid card served at the wrong path, without HTTPS, with the wrong content type, or without a CORS header is still undiscoverable. Check the live URL separately with a well-known URL checker after every deploy.
Are warnings safe to ignore?
Some are, and some are the most consequential findings in the report. Missing defaultInputModes is a warning but leaves callers guessing what to send; an embedded credential is a warning but is a security incident. Treat warnings as a reading list, not a backlog you can defer wholesale.
Why is a missing version sometimes an error and sometimes a warning?
Because the validator detects pre-1.0 cards. If the document still carries top-level url or preferredTransport, it is mid-migration, and reporting every v1.0 requirement as a hard error buries the one finding that matters — that the transport section needs restructuring. Once supportedInterfaces exists, the same omissions become errors.
Does the validator check that my endpoint is reachable?
No. It checks that the URLs in the card are syntactically valid and use HTTPS. Whether anything answers at those addresses is a different question, and an important one: an interface listed in the card is a promise a caller will act on.
What is the single most common error?
Missing skill tags. They were optional in pre-1.0 drafts and are required in v1.0, so almost every card written before the change fails on it — and because tags drive skill-level discovery, a card missing them is findable but not matchable.
References
- A2A protocol specification (a2aproject/A2A)github.com/a2aproject/A2A
- RFC 8615 — Well-Known Uniform Resource Identifierswww.rfc-editor.org/rfc/rfc8615
- RFC 8785 — JSON Canonicalization Scheme (JCS)www.rfc-editor.org/rfc/rfc8785
- IANA media types registrywww.iana.org/assignments/media-types/media-types.xhtml
Related tool: Agent Card Validator
Next step
Paste your card. Get the list.
The validator runs every check on this page against your JSON — required fields, interface shape, skill tags, pre-1.0 leftovers and embedded credentials — and tells you which ones block interoperability.