← Back to articles

Agent Card in A2A: Full JSON Example and Field Breakdown

An Agent Card is a JSON document that tells a client agent whom to call, where to send a task, and which skills are available. In the A2A (Agent2Agent) protocol the card is usually published at /.well-known/agent-card.json: without it an agent is hard to discover; with a vague description it is hard to route correctly.

  • Agent Card - public contract of an agent's capabilities
  • Discovery - finding the card via a well-known URL or a registry
  • skills - concrete abilities, not a generic "I can do everything"
  • capabilities - streaming, push notifications, extended card
  • security - OpenAPI-style authentication schemes

Why You Need an Agent Card

A2A connects independent agents: one acts as a client, another as an executor. Before sending a task, the client reads the card and answers:

  1. Does this agent match the user's intent?
  2. Which endpoint accepts tasks?
  3. Which MIME types are supported on input and output?
  4. Is authentication required, and which kind?
  5. Are event streaming and webhook notifications supported?

The card is not marketing copy. Orchestrators and LLM routers parse it. The more precise description, skills, and examples are, the more stable executor selection becomes.

Full JSON Example

Below is a working card for an agent that searches products on a site, calculates pricing, and creates a lead after user confirmation. Fields use camelCase, as in typical A2A JSON cards.

{
  "name": "Site Commerce Agent",
  "description": "Searches the site catalog, calculates price and delivery time, and creates a lead after user confirmation. Works with catalog, draft cart, and order statuses. Does not process payments or change prices.",
  "version": "1.2.0",
  "protocolVersion": "0.3.0",
  "url": "https://api.example.com/a2a",
  "documentationUrl": "https://docs.example.com/a2a/commerce-agent",
  "iconUrl": "https://example.com/icons/commerce-agent.svg",
  "provider": {
    "organization": "Example Shop",
    "url": "https://example.com"
  },
  "capabilities": {
    "streaming": true,
    "pushNotifications": true,
    "stateTransitionHistory": true,
    "extendedAgentCard": false
  },
  "defaultInputModes": [
    "text/plain",
    "application/json"
  ],
  "defaultOutputModes": [
    "text/plain",
    "application/json"
  ],
  "skills": [
    {
      "id": "search-products",
      "name": "Product search",
      "description": "Searches products by query, category, price, and availability. Returns candidates with id, title, price, and a short description.",
      "tags": ["catalog", "search", "products"],
      "examples": [
        "Find laptops under 800 EUR with delivery this week",
        "Show available plans for a team of 20 people"
      ],
      "inputModes": ["text/plain", "application/json"],
      "outputModes": ["application/json", "text/plain"]
    },
    {
      "id": "calculate-quote",
      "name": "Quote calculation",
      "description": "Calculates price, taxes, shipping, and ETA for selected items and quantities. Does not create an order.",
      "tags": ["pricing", "quote", "shipping"],
      "examples": [
        "Calculate the cost of 3 units of product_id=sku-1042 with delivery to Berlin",
        "Compare Basic and Pro plans for 50 users"
      ],
      "inputModes": ["application/json", "text/plain"],
      "outputModes": ["application/json"]
    },
    {
      "id": "create-lead",
      "name": "Lead creation",
      "description": "Creates a draft lead or request after explicit user confirmation. Requires contact details and consent for data processing.",
      "tags": ["lead", "order-draft", "crm"],
      "examples": [
        "Create a Pro plan request for ACME, contact: ops@acme.example",
        "Create an order draft from quote_id=q-7781"
      ],
      "inputModes": ["application/json"],
      "outputModes": ["application/json", "text/plain"]
    },
    {
      "id": "get-order-status",
      "name": "Order status",
      "description": "Returns payment and delivery status by order_id for an authenticated user or a public tracking number.",
      "tags": ["orders", "status", "tracking"],
      "examples": [
        "What is the status of order ORD-20441?",
        "Where is the parcel with tracking number TRK-998877?"
      ]
    }
  ],
  "securitySchemes": {
    "bearer": {
      "type": "http",
      "scheme": "bearer",
      "bearerFormat": "JWT"
    },
    "oauth2": {
      "type": "oauth2",
      "flows": {
        "clientCredentials": {
          "tokenUrl": "https://auth.example.com/oauth/token",
          "scopes": {
            "catalog:read": "Read catalog and quotes",
            "leads:write": "Create leads",
            "orders:read": "Read order statuses"
          }
        }
      }
    }
  },
  "security": [
    {
      "oauth2": ["catalog:read"]
    },
    {
      "bearer": []
    }
  ]
}

In A2A v1.0 the endpoint is often described with a supportedInterfaces array instead of a single top-level url. The idea is the same: tell the client where to send tasks and which binding to use (JSONRPC, HTTP+JSON, GRPC, and so on).

v1.0 fragment example:

{
  "supportedInterfaces": [
    {
      "url": "https://api.example.com/a2a",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ]
}

Top-Level Field Breakdown

Field Required Purpose
name Yes Human-readable agent name
description Yes Concrete summary: what it does and what it does not
version Yes Agent implementation version (semver preferred)
url / supportedInterfaces Yes* Task endpoint(s), not the card URL
skills Yes At least one skill
capabilities Recommended Honest capability flags
defaultInputModes / defaultOutputModes Recommended Default MIME types
provider No Owning organization
documentationUrl / iconUrl No Docs and UI icon
protocolVersion Depends on schema Protocol version (often top-level in v0.3)
securitySchemes / security No How the client should authenticate

* In v0.3 schemas url is usually required. In v1.0 supportedInterfaces takes over the endpoint role.

name and description

name is for people and logs. description is for routers. Bad: "A helpful site agent". Good: list operations, limits, and result shape.

version

This is the agent implementation version, not necessarily the protocol version. Bump major for breaking changes in skills or response contracts. Clients may cache the card and refresh it when the version changes.

url - a common mistake

url is where message/send / tasks go. It is not the path to /.well-known/agent-card.json.

Wrong:

"url": "https://example.com/.well-known/agent-card.json"

Right:

"url": "https://api.example.com/a2a"

capabilities

Flag Meaning
streaming Supports streaming responses (SSE / stream)
pushNotifications Webhook notifications for long-running tasks
stateTransitionHistory History of task status transitions
extendedAgentCard After auth, an extended/private card is available

Set true only if the behavior is actually implemented. A client that opens a stream against a non-streaming agent will get an error.

defaultInputModes and defaultOutputModes

Default MIME types for the whole agent. A skill can override them. Typical values: text/plain, application/json, application/pdf, image/png.

skills Breakdown

A skill is a routing unit. One skill = one clear capability.

Field Required Notes
id Yes Unique within the agent; kebab-case works well
name Yes Short UI label
description Yes Inputs, outputs, and limits
tags No Keywords for search and filtering
examples No, but strongly recommended 2-3 real prompts for orchestrators
inputModes / outputModes No MIME overrides for this skill

Examples are not decoration. Without them an orchestrator model guesses inputs from the description alone and fails more often.

Bad skill:

{
  "id": "website",
  "name": "Website",
  "description": "Works with the website"
}

A good skill looks like the ones in the full example: concrete id, clear boundaries, tags, and examples.

Authentication: securitySchemes and security

Schemes usually follow the OpenAPI approach:

  • apiKey
  • http (Basic / Bearer)
  • oauth2
  • openIdConnect
  • mutualTLS

securitySchemes describes available methods. security sets the default requirement:

  • multiple objects in the security array = alternatives (OR);
  • multiple keys in one object = all required (AND).

Publish how to authenticate, not secrets. Do not put API keys, refresh tokens, or internal hostnames in the JSON.

Discovery: How Cards Are Found

Typical flow:

  1. The client knows the agent's base domain.
  2. It requests https://agent.example.com/.well-known/agent-card.json.
  3. It validates required fields.
  4. It picks a skill by description, tags, and examples.
  5. It authenticates using security.
  6. It sends the task to url / supportedInterfaces.

Cards are also published in registries or agent directories. Discovery then goes through search, while well-known remains the owner's source of truth.

Local check:

curl -s https://api.example.com/.well-known/agent-card.json

What Not to Publish in an Agent Card

  • API keys, passwords, private keys;
  • unprotected internal admin or staging URLs;
  • operations unavailable to external clients;
  • inflated capabilities (streaming: true without implementation);
  • vague skills like "does everything on the site".

A public card is both an attack surface and a routing surface. Keep it precise and minimally sufficient.

Common Mistakes

  1. Confusing url with the card URL.
  2. Empty skills array. The agent becomes almost unroutable.
  3. Description without boundaries. Missing what the agent does not do (payment, deletion, price changes).
  4. No examples. Orchestrators understand valid input worse.
  5. localhost in a production card. The endpoint must be reachable by clients.
  6. One skill for the whole product. Prefer several narrow skills with different rights and MIME types.

Mini Checklist Before Publishing

  1. The card is served over HTTPS with Content-Type: application/json.
  2. It has name, description, version, an endpoint, and at least one skill.
  3. Descriptions are concrete.
  4. Key skills have examples and tags.
  5. capabilities match the real server.
  6. The JSON contains no secrets.
  7. The endpoint from the card answers a test task.
  8. Version bumps on breaking changes.

Takeaway

An Agent Card is the main discovery contract in A2A. A complete JSON with precise skills, honest capabilities, and explicit security gives client agents enough data to find the right executor and avoid calling the wrong one.

If you need help designing an Agent Card, an A2A server, or wiring an agent to a site API - contact me.

Frequently Asked Questions

Where should the Agent Card live?

The standard public path is /.well-known/agent-card.json on the agent domain. You can also register the card in a catalog or registry, but the well-known URL remains a convenient discovery point without a separate index.

How is url different from the card address?

The card address is for discovery; url (or supportedInterfaces) is for task execution. The client first reads the JSON card, then sends messages/tasks to the agent's working endpoint.

How many skills should a card have?

As many as you have truly distinct abilities with different inputs or permissions. Usually 3-7 narrow skills beat one generic "do everything". Clear boundaries, tags, and examples matter for routing.

Is authentication required in an Agent Card?

Not always. A public read-only agent may omit security. For writes, personal data, and paid operations, declare securitySchemes and security, and keep secrets outside the card.

Should I update the card on every deploy?

Update it when skills, endpoint, capabilities, auth, or the agent's meaning change. A technical patch without contract changes can be reflected in version; breaking changes deserve a major bump and explicit docs.

Contacts