The agent's card, and the door behind it
A card is how one of your agents introduces itself to an agent outside your company: its name, what it is for, the skills it has, and — when you have opened the door — the address to write to and how to authenticate there.
It is a document first. Whether anything answers behind it is a second, separate decision.
Why a card exists at all
Agents that speak A2A find each other by exchanging cards. There is no registry in the middle of the protocol: the card is the introduction. Before it, the name, the description and the skills existed in three places and could only be read by somebody signed into the cabinet.
What the card says, and where each line comes from
| on the card | from |
|---|---|
| name, description | the agent's own row |
| skills, with their descriptions | the skills this agent uses |
| what it can do | streaming yes while the door is open (AGNT2-355); no push notifications; one card |
version — a fingerprint | everything above, hashed |
| the address to call | the live A2A door — absent when there is none |
| how to authenticate | the same door: an API key in a header, or nothing |
Nothing on that list is a field somebody fills in «for the card». A second text is a text that disagrees with the first by next week. The consequence surprises people and is correct: give the agent a skill and the card changes under a link you handed out yesterday. A card describes what the agent is now, and the fingerprint is what lets the other side notice, in one comparison, without reading the whole document.
The link
Open the agent → the General tab → Agent card. You will see what a reader receives before you hand anything out, and a sentence saying exactly what the holder learns: the agent's name, its description and its skills with their descriptions — nothing else, and nothing about the rest of your team.
Get a link issues one. Four things about it:
- It is shown once. Nothing keeps a copy. Lose it and you revoke it and issue another.
- Issuing is refused while one is live. Somebody is holding the old address. Revoke, then issue — two decisions, in the order you actually mean them.
- Revoking takes effect on the next read, with no grace period.
- A revoked link is not deleted. After an address has reached the wrong person, somebody has to be able to see that it existed and when it was last read, so the row survives the revocation with both facts on it. That is in the database, not on the screen — once a link is revoked the panel goes back to offering Get a link and says nothing about the old one, because it reads only the live link.
The address looks like this, and it is the whole of what the reader needs:
https://<your api origin>/agent-cards/acd.<public half>.<secret half>Every refusal is the same refusal
Six causes — a made-up address, the wrong secret, a revoked link, an agent switched off, archived, or deleted — answer identically. The response does not confirm that such an agent ever existed. That is on purpose and it is measured: the response to a deleted agent is compared, whole, against the response to an address that was never issued.
A card with a dead address is worse than no card
An address on a card means «write here and you will be answered». So the address appears only when something answers, and vanishes when it stops. A reader that finds no callable interface stops there — readable, not callable — which is the honest statement, and it is better than sending a stranger's agent into silence and letting them conclude that we are broken.
Because the card is built at the moment it is read, that rule keeps itself. Nobody has to remember to edit a document when the door closes.
Opening the door — A2A
Publishing an agent on A2A is the same kind of act as putting it on a website: one binding, the same audit line, the same unpublish. Today it is an api call rather than a screen — POST /agents/:id/channels/a2a — and the card grows an address the moment it succeeds.
What the partner then does:
GET <the card link> → the address, in supportedInterfaces
POST /a2a/v1/agents/<agent id> → { "jsonrpc": "2.0", "method": "message/send", … }
X-Embed-Key: emk.<public>.<secret>
← a task, completed, with the answer
POST … { "method": "tasks/get", … }
← the same task, tomorrowBoth revisions of the protocol are answered at that one address, and the method name picks the revision — no header, no configuration. message/send and tasks/get are 0.3; SendMessage and GetTask are 1.0.
Four questions about an endpoint open to the outside
| Whose turn is it? | the agent's owner, in the agent's team, through the same membership check a member gets. A partner is never a principal. |
| What may it do? | nothing beyond answering. No worker, no network, no schedule — and on an A2A binding there is no route that opens those at all. |
| What does it write down? | its own conversation. Nothing reaches the agent's durable notes: a stranger's paragraph must not ride into the owner's next turn. |
| Where does it land? | one conversation per partner per agent, beside the website visitors' and never inside the owner's. |
The partner has a name, and that is the point
The credential is the same embed key a member issues to a party the team has agreed to talk to. Its public half is the partner's identity everywhere it matters: the conversation is keyed on it, the flow limit is theirs alone, and the spend has their name against it.
Say it out loud: this opens an agent to named partners, not to the internet. A key means «we already know each other». Opening an agent to the unnamed is a separate decision with a separate price, and it has not been taken. A missing or bad key is a refusal that names the scheme, never a bare one.
The answer arrives in pieces, and the work stays behind the door
Since AGNT2-355 the same address also answers message/stream (SendStreamingMessage in 1.0): the partner's client gets the task the moment it exists, then the answer piece by piece as the agent writes it, then a final status — over Server-Sent Events, in the order the agent produced them. The card says so: capabilities.streaming is true exactly while the door is open.
What the partner sees of the WORK — the agent's reasoning and the tools it reaches for — is the owner's decision, and it is closed by default: a partner's stream carries the answer and nothing else until the owner opens visibility on the A2A binding (PUT /agents/:id/channels/a2a/access). Opened, the reasoning and each tool step arrive as separate side remarks beside the answer, never inside it, and never with the tool's output. It is the only one of the four rights that can be opened for partners; hands, memory and the schedule stay closed.
Declared missing, rather than half-built
Webhooks out to a partner's address, reconnecting to a stream already running, cancelling a task, an extended card behind authentication, a gRPC binding, any access without a key, and a cabinet screen for the binding. Each is stated on the card as absent rather than faked.
The full argument, and the three lines it cost the core, is the Channels row of the decisions registry.
Check it end to end
- Open an agent → General → Agent card → Get a link. Copy it.
- Open that address in a browser with no session. You get the card — a JSON document with the agent's name, description and skills.
supportedInterfacesis empty. Nothing answers yet, and the card says so.- Publish the agent on A2A:
POST /agents/<id>/channels/a2a. - Re-read the same link. One interface per protocol revision has appeared, with an address, and an API-key scheme beside it. The field to watch is
version— it has moved. - Take the door away again — the entry vanishes and
versionmoves back.
Step 3 and step 5 read the same address. That is the whole property this page is about.