Publish an Honest Agent Card
An Agent Card is the agent's discovery document: name, description, interfaces, protocol version, capabilities, security schemes, default data modes, and skills. The client reads the card before calling any optional operations - and so the card is both the agent's public face and its promise.
A working card looks like this: it honestly declares what the agent can do and how to talk to it.
export function createReleaseAgentCard(baseUrl: string): AgentCard {
return {
name: "Release Review Agent",
description: "Checks a release snapshot against the approved policy and returns a report.",
supportedInterfaces: [{
url: `${baseUrl}/`,
protocolBinding: "JSONRPC",
tenant: "",
protocolVersion: A2A_PROTOCOL_VERSION
}],
provider: {
organization: "Developer Protocol Book",
url: "https://example.com/developer-protocol-book"
},
version: "1.0.0",
documentationUrl: `${baseUrl}/docs`,
capabilities: {
streaming: true,
pushNotifications: false,
extensions: [],
extendedAgentCard: false
},
securitySchemes: {},
securityRequirements: [],
defaultInputModes: ["text/plain"],
defaultOutputModes: ["text/markdown", "application/json"],
skills: [{
id: "review_release",
name: "Release review",
description: "Checks CI, tests, vulnerabilities, migration reversibility, and rollback readiness.",
tags: ["release", "ci", "security", "rollback"],
examples: ["Check the release web-portal@2.4.0"],
inputModes: ["text/plain"],
outputModes: ["text/markdown", "application/json"],
securityRequirements: []
}],
signatures: []
};
}It's found at a standard address, and the client goes over the card top to bottom before sending anything.
GET /.well-known/agent-card.json
Accept: application/json
The client picks supportedInterfaces[]
checks protocolVersion + protocolBinding
checks streaming/push/extendedAgentCard
negotiates input/output media types
then applies the declared security schemeThe key word in the chapter title is "honest". The client uses every field of the card for a real decision, and so each has its own typical design error.
Field · The client uses it for · Design error
supportedInterfaces- URL, binding, version; Putting localhost in productioncapabilities- Whether streaming/push/extended card is possible; Declaring a feature without an implementationskills- Agent selection and task examples; A marketing "does everything"- modes - Media negotiation; Returning an unnegotiated format
- security - How to authenticate a request; A secret in the card itself
- signatures - Verifying the card's provenance; Treating a signature as authorization
Let's take the most dangerous. supportedInterfaces gives the URL, binding, and version - and putting localhost here in production means breaking every client. capabilities declares streaming/push/extended card - declaring a feature without an implementation is worse than not declaring it. skills is agent selection and task examples, not a marketing "does everything". And the signature in signatures verifies the card's provenance, but is not itself authorization.
The card is a promise of compatibility. Version control is needed not only for the agent's code. Changing a skill's semantics, a required input mode, or a security requirement can be a breaking change even at the same HTTP endpoint. Change the meaning - change the version.
The card declares how to talk to the agent. The conversation itself is carried by messages - and here A2A carefully separates the communication from the result of the work.