A2A Agent Card Generator

Build a valid A2A (Agent2Agent) Agent Card JSON manifest - name, capabilities, input and output modes, skills - ready to serve at /.well-known. Free.

Advertisement

Build an A2A Agent Card and serve it at /.well-known/agent-card.json

An Agent Card is the discovery document for the Agent2Agent (A2A) protocol. It is a single JSON object that says what your agent is called, where to reach it, which transport features it supports, and — the part that actually matters to a calling agent — which discrete skills it offers. Another agent fetches that document, reads the skill list, and decides whether to delegate work to you. If the card is malformed or missing, your agent is invisible to the rest of the network no matter how good it is.

This generator is a form-to-JSON builder. You fill in the agent metadata, tick the capability flags, choose input and output MIME types, add one entry per skill, and the card is rebuilt on every keystroke in the panel on the right. It runs entirely in your browser: the JSON is assembled in React state and never leaves the page, so it is safe to paste in a real service URL or an internal hostname while drafting. There is no upload, no server round trip, and no account.

The exact fields this generator emits

The card is assembled in a fixed order, and optional fields are omitted entirely rather than emitted as empty strings. That matters, because a consumer that does a strict schema check will treat "documentationUrl": "" differently from an absent key. Here is every field the builder can produce.

FieldTypeEmitted when
protocolVersionstringThe protocol version box is non-empty. Pre-filled with 0.3.0.
namestringAlways. Trimmed; an empty box gives "".
descriptionstringAlways. Trimmed.
urlstringService URL is non-empty.
versionstringVersion is non-empty. This is your agent's version, not the protocol's.
documentationUrlstringThe optional documentation URL is filled in.
providerobjectEither provider box is filled. Contains organization and url, each only if given.
capabilitiesobjectAlways. Three booleans, described below.
defaultInputModesstring[]Always. Falls back to ["text/plain"] if you deselect everything.
defaultOutputModesstring[]Always, same fallback.
skillsobject[]Always. An empty array if you remove every skill.

Every skill object carries id, name, description and tags unconditionally, plus examples only when you have typed at least one. tags is produced by splitting your comma-separated input, trimming each piece and dropping blanks, so "cooking, search, " becomes ["cooking","search"]. examples is split the same way but on newlines — one example utterance per line.

A worked example

The default state of the tool describes a recipe agent with a single skill. Filled in as shipped, it produces this:

InputResulting JSON
Name: Recipe Agent"name": "Recipe Agent"
Service URL: https://recipe-agent.example.com"url": "https://recipe-agent.example.com"
Version 1.0.0, protocol 0.3.0"version": "1.0.0", "protocolVersion": "0.3.0"
Streaming on, the other two off"capabilities": { "streaming": true, "pushNotifications": false, "stateTransitionHistory": false }
Skill id find-recipe, tags cooking, search{ "id": "find-recipe", "name": "Find Recipe", "description": "…", "tags": ["cooking","search"], "examples": ["I need a recipe for sourdough bread"] }

Below the JSON pane the tool shows the exact path to publish at, derived from whatever you typed in the Service URL box with any trailing slashes stripped: https://recipe-agent.example.com/.well-known/agent-card.json. That well-known path is how a client finds you without being told anything except your origin.

What the three capability flags mean

  • Streaming (SSE) — you can push incremental results back over a server-sent-events stream rather than only returning a single final response. Turn this on only if your endpoint genuinely implements it; a client that sees streaming: true may open a stream and hang when nothing arrives.
  • Push notifications — you can call back to a client-supplied webhook when a long-running task changes state, so the client does not have to hold a connection open. This is the flag to set for jobs measured in minutes rather than seconds.
  • State transition history — you retain and can return the history of a task's state changes, rather than just its current state. Useful for auditability; costs you storage.

All three are emitted as literal booleans every time. There is no way to omit the capabilities object from this generator, which is deliberate — consumers should not have to guess.

Choosing input and output modes

The mode pickers offer eight presets — text/plain, text/markdown, application/json, image/png, image/jpeg, audio/mpeg, video/mp4 and application/pdf — and a free-text box for anything else. Type a MIME type such as application/xml and press Enter or click Add, and it joins the list as a selected chip. Duplicates are rejected silently.

These are defaults, applied to the agent as a whole. Be conservative here. Declaring image/png as an input mode is a promise that any skill can accept an image; if only one of your skills can, a calling agent will send images to the others and get failures. The honest pattern for a text-first agent is ["text/plain"] in and ["text/plain", "text/markdown"] out.

What this generator does not emit

This is a card builder, not a full spec implementation, and the difference is worth stating plainly before you paste the output into production. The generator produces the core discovery fields listed above and nothing else. It does not emit authentication or security-scheme declarations, alternative transport or interface listings, a preferred-transport hint, per-skill input and output modes, or any signature block. If your deployment needs those, treat the generated document as a starting skeleton and add them by hand.

It also performs no validation. Nothing checks that your service URL resolves, that the skill ids are unique, that version is semantic, or that the protocol version you typed is one a client will accept. The protocol version field is free text precisely so you can target whichever revision your counterparty implements — A2A moves quickly, and a card written against one revision is not guaranteed to satisfy a client written against another. Confirm the version with the agents you actually intend to interoperate with rather than assuming the pre-filled default is right for you.

Writing skills that other agents will actually call

The skill list is the working part of the card. Everything above it is metadata; the skills are what a remote planner reads when deciding whether you are the right agent for a subtask. A few habits make the difference:

  • Give id a stable, machine-safe value. Lowercase and hyphenated, like find-recipe. It is an identifier, not a label, and changing it later breaks callers that hard-coded it.
  • Write description for a model, not a marketing page. State the input it expects and the output it returns. "Search and retrieve recipes for a given ingredient or dish" tells a planner more than "world-class culinary intelligence".
  • Use tags as a coarse filter. Two to four broad terms beat a dozen narrow ones. They exist so a directory can shortlist candidate agents cheaply.
  • Put real utterances in examples. One per line, phrased the way a user or an upstream agent would actually phrase it. These are the strongest signal for routing, and they cost nothing.
  • Split skills that fail for different reasons. If "find a recipe" and "convert units" have different failure modes and different inputs, they are two skills, not one.

Common mistakes

SymptomLikely cause
Clients get a 404 for your cardServed at the wrong path. It must be /.well-known/agent-card.json on the origin in url, not under a sub-path.
Card fetched but ignoredServed with the wrong content type. Return it as application/json.
Skill never gets routed todescription and examples are too vague, or tags are so specific nothing matches them.
Callers open a stream that never yieldsstreaming set to true on an endpoint that only returns a single response.
Requests arrive with unusable payloadsdefaultInputModes lists MIME types some skills cannot handle.
Empty "name" in the outputThe name box was cleared. name and description are always emitted, blank or not.

Where A2A sits relative to MCP

A2A and MCP solve different halves of the same architecture. A2A is how independent agents discover and delegate to each other; MCP is how one agent reaches its own tools and data. A typical deployment uses both — an MCP client inside the agent, an Agent Card facing outward. If you are still deciding which one your problem needs, the agent protocol selector walks the decision in a couple of questions.

Publishing checklist

  • Copy the JSON with the Copy button and save it as agent-card.json.
  • Serve it at /.well-known/agent-card.json on the same origin as the url field, over HTTPS, with Content-Type: application/json.
  • Make sure it is reachable without authentication — discovery happens before any handshake.
  • Set permissive CORS if browser-based clients need to read it.
  • Bump version whenever the skill list changes, and keep the old skill ids working for at least one release.
  • Fetch it from outside your network once before announcing it. A card that only resolves internally is the most common self-inflicted failure.

How a calling agent uses your card

It is easier to write a good card once you can picture what happens to it. A client that knows only your origin requests /.well-known/agent-card.json. It reads name and description to decide whether you are plausibly relevant at all. It reads skills to decide which specific capability to invoke, matching on the descriptions, tags and example utterances. It reads capabilities to decide how to call you — whether to open a stream, whether to register a webhook, whether it can ask for state history. It reads defaultInputModes and defaultOutputModes to decide what it is allowed to send and what it should be ready to receive. Then it uses url as the endpoint.

Every one of those decisions is made from text you wrote in this form, before a single request reaches your agent. That is why the description fields deserve more care than they usually get: they are not documentation, they are the routing logic. A skill whose description does not distinguish it from a competing agent's skill will not be chosen, and you will have no log entry telling you why.

Versioning without breaking callers

Two version numbers live in the card and they move independently. protocolVersion tracks the A2A revision you implement and changes only when you migrate. version is your own agent's release, and it is the one you will actually be editing.

The rule that keeps a network of agents working is that skill ids are a public contract. Adding a skill is safe. Improving a description is safe. Renaming or removing a skill id is a breaking change for anyone who cached it, and because A2A discovery is pull-based you have no reliable way to notify them. If a skill must go, keep the id serving a useful error for a release before you remove it, and bump version so an observant caller can see something changed. Regenerate the whole card here whenever the skill list changes rather than hand-editing the published file — hand edits are how a card drifts out of sync with what the agent actually implements.

This tool is provided for informational and educational purposes only. All processing happens in your browser — no data is sent to or stored on our servers. While we strive for accuracy, we make no warranties about the completeness or reliability of results.