Agent2Agent (A2A) is the protocol that lets one agent hire another as a peer. Where llms.txt tells a crawler what to read and an MCP server tells a model what tools to call, A2A tells a foreign agent that your product is an agent it can hand a task to. The pointer to that fact is a small JSON document you publish at a fixed URL: /.well-known/agent-card.json.
This guide covers the minimum viable A2A agent card in 2026, the fields that actually get read by discovery clients, the split between skills and capabilities, and the verify loop that catches the two failures we see most often on scans.
Why the fixed URL matters
Unlike MCP, which is still settling around the /.well-known/mcp.json hint, A2A locked its discovery path early: the card lives at https://yourbrand.com/.well-known/agent-card.json, exact spelling, served with Content-Type: application/json. Clients probe that path and only that path. A card at /agent-card.json, /.well-known/agent.json, or anywhere else is invisible.
The fixed path is a feature. It means a peer agent looking to delegate a task to yours does not need a directory lookup or a marketing site read. Domain plus known path plus GET is the entire handshake. Do not fight the convention.
The minimum viable card
This is the smallest card that a compliant A2A client will accept and mount as a callable peer:
{
"name": "yourbrand-agent",
"description": "Ships llms.txt, JSON-LD, and MCP scaffolding for a scanned site.",
"url": "https://api.yourbrand.com/a2a",
"provider": {
"organization": "YourBrand Inc",
"url": "https://yourbrand.com"
},
"version": "1.0.0",
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"authentication": {
"schemes": ["bearer"]
},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text", "file"],
"skills": [
{
"id": "generate-llms-txt",
"name": "Generate llms.txt",
"description": "Produce an llms.txt file for a given site URL.",
"tags": ["llms.txt", "ai-seo"]
}
]
}Ten top-level fields, one skill entry. That is a functional card. Every extra field is discretionary and will churn as the spec matures; keep the surface small on version one.
Skills vs capabilities: do not confuse them
The two most misused fields on real A2A cards we scan.
capabilities— protocol features your endpoint supports.streamingmeans you can send incremental task updates.pushNotificationsmeans you can call a webhook the client provides. This is a technical contract about transport, not about what your agent does.skills— the actual jobs your agent will take on. Each skill needs anid(stable, machine-key),name(human label),description(one sentence, imperative), andtags(short strings a client can filter on). This is the field a peer agent reads to decide whether to hire yours.
A card with rich capabilities and a single empty skill teaches every client on the network that your agent is a hollow shell. A card with three sharp skills and no capabilities is fine — clients will use the defaults.
Authentication: pick one, stick to it
The authentication.schemes array is the whole contract about how peer agents call you.
[]or omitted — public agent, no auth. Fine for a demo or a read-only agent that only returns public data. Rate-limit at the edge.["bearer"]— the mainstream choice in 2026. Client sendsAuthorization: Bearer <token>. Simple, predictable, works with every hosted LLM stack.["oauth2"]— for agents acting on behalf of a specific user with user-scoped data. Higher friction; only pick it if the data model requires per-user consent.
Do not list all three "just in case". Peer clients pick the first scheme they recognize and hit your endpoint with those headers; if you cannot actually accept OAuth, listing it will produce silent failures at task-dispatch time.
When to publish an A2A card at all
A2A is a protocol for agents that accept task requests from other agents. If your product is a scanner, a report generator, a translator, a form-filler that runs as a service — yes, ship a card. If your product is a static content site, a blog, or a marketing page, an A2A card is not the right signal; those sites belong to the llms.txt and schema.org discovery layers instead.
Rule of thumb: if you cannot answer the question "what task can a foreign agent hand mine, and what does it get back", you do not need an A2A card yet. A missing card is neutral. A card pointing at a non-agent endpoint is a strong negative signal.
Cross-referencing A2A with your other agent files
Three signals should agree if you publish A2A:
/llms.txt— mention the A2A endpoint in the "Optional" section with one line. Agents that never read/.well-known/still get the pointer.- Schema.org JSON-LD on the marketing page — a
WebSiteblock withpotentialActionreferencing the same skills you list in the A2A card. Grounds LLM search on the same vocabulary. Templates in the JSON-LD guide. /.well-known/mcp.json— if you also expose an MCP server for tool sessions, list it in the same directory. A2A and MCP are complementary: A2A is "hire this agent to do a job", MCP is "let this model call these tools inside its own session". See the /.well-known/ directory guide for how the pointers coexist.
Three files, one story. That is what an AI-agent-ready site looks like in 2026.
How to verify the card is landing
curl -I https://yourbrand.com/.well-known/agent-card.json— expect200andContent-Type: application/json. If you gettext/html, your framework is wrapping the file in an HTML shell (Next.js, Nuxt, Astro all do this by default). Move the file topublic/.well-known/or add a route rule, then re-check.curl https://yourbrand.com/.well-known/agent-card.json | jq .skills[0].id— expect a skill id back cleanly, not an HTML parse error.- Point an A2A client at your domain (the reference client at a2aproject.github.io/A2A is the honest starting point in 2026). If it lists your skills and lets a test task through, the loop is closed.
- Run a full scan on agentfix.pro. It checks the card path, the content-type, the required fields, and the endpoint reachability alongside 30 other agent-readiness signals, and ships the missing files back filled in.
The two failure modes that catch everyone
First: HTML wrapper on the JSON. The card returns 200 but the framework injected a full HTML shell around it. Every client rejects the parse and moves on silently. Test with curl -I, not a browser tab. Fix by serving the file as a raw asset, not through the app router.
Second: card without a live endpoint. The url field points at a service that returns 502, 404, or an HTML login page. The card looks fine to a scanner; the first real task dispatch fails and the client will not retry your domain for days. If the endpoint is not ready, do not ship the card. Silence beats a broken promise.
Related: MCP server card for your site, the /.well-known/ directory for AI agents, and the 33-signal GEO checklist.
