A2A (Agent2Agent) is an open standard for AI agents to talk to each other. An agent card is a small public JSON file that tells other agents about yours: its name, what it can do, and where to send questions. Another business's agent (a comparison service's, say, or a partner's) reads the card and then asks your agent questions directly, server to server, with no person or browser in between.
Your agent answers as it would in a chat, with its own knowledge and persona, screened by its compliance rules.
What you need#
- Agent access on your plan, and your account paid up. If you don't see Agent access under Organisation in the dashboard, ask us.
- To be an owner or manager of your organisation.
- A live agent (one in production with a published version). Only live agents can answer.
Set up a card#
- In the dashboard, open Organisation > Agent access and choose Manage agent card.
- Press New integration and set:
- Name: for your own reference, for example "Main website card".
- Card description: what calling agents are told about your agent. Leave it blank to use a default.
- Served from: one of your Subcontext-hosted sites, or Not hosted by Subcontext to host the card on your own website.
- Agent that answers: which live agent answers calls. Leave it as First live agent to use your first live agent.
- Enabled: when it's off, the card isn't served and calls are refused.
- Press Create integration.
Where the card lives#
Agents look for a card at a fixed address on a website: /.well-known/agent-card.json.
- On a Subcontext-hosted site, the card is served for you at that address, for example
https://your-site.sites.subcontext.com/.well-known/agent-card.json. The integration's page shows the exact address. Each site can serve one card. - On your own website, press Download agent-card.json on the integration's page and put the file at
/.well-known/agent-card.jsonon your web server, so it's at an address likehttps://www.example.com/.well-known/agent-card.json. Download it again if you change the card's description or agent.
Either way, questions go to Subcontext, never to your web server.
What's in the card#
{
"protocolVersion": "0.3.0",
"name": "Your agent's name",
"description": "The AI assistant for Northbank. Ask about products, cover and support.",
"url": "https://subcontext.com/a2a/YOUR_INTEGRATION_ID",
"preferredTransport": "JSONRPC",
"version": "1.0.0",
"capabilities": { "streaming": false, "pushNotifications": false, "stateTransitionHistory": false },
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{
"id": "answer_question",
"name": "Answer questions about Northbank",
"description": "Ask anything about Northbank, their products or cover, and get an answer from their AI assistant.",
"tags": ["insurance", "support"]
}
]
}
nameis your answering agent's name.descriptionis your Card description, or a default naming your firm.urlis where questions go. It's always on https://subcontext.com, wherever the card is hosted.skillslists what the agent can do. It has one skill, answering questions in text.
How another agent uses it#
This section is for developers building the calling agent. The calling agent reads the card, then sends
JSON-RPC 2.0 requests with POST to the card's url. There's no sign-up and no key.
Ask a question with message/send:
curl -X POST https://subcontext.com/a2a/YOUR_INTEGRATION_ID \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "message/send",
"params": {"message": {"role": "user", "messageId": "msg-1",
"parts": [{"kind": "text", "text": "Do you cover people with diabetes?"}]}}}'
The answer comes back straight away, as a completed task:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "TASK_ID",
"contextId": "CONTEXT_ID",
"kind": "task",
"status": { "state": "completed" },
"artifacts": [
{ "artifactId": "TASK_ID", "name": "answer", "parts": [{ "kind": "text", "text": "The agent's answer." }] }
]
}
}
- To carry on the same conversation, send the
contextIdback in the next message ("message": {"contextId": "CONTEXT_ID", ...}). Your agent then continues from the earlier messages. - To fetch an answer again, use
tasks/getwith"params": {"id": "TASK_ID"}. - There's no streaming and there are no push notifications. Every answer arrives in the response.
Errors are JSON-RPC errors:
| Code | Means |
|---|---|
-32700 |
The body isn't valid JSON. |
-32600 |
Not a JSON-RPC 2.0 request, or the card is unknown or switched off. |
-32601 |
A method other than message/send or tasks/get. |
-32602 |
No text in the message, or a contextId this card didn't start. |
-32603 |
The agent couldn't answer, or there's no live agent. Try again shortly. |
-32001 |
No such task. |
Each address can make 30 calls every five minutes; after that, calls get 429 Too Many Requests until the
five minutes are up.
Running a card#
- It's public. Anyone who finds your card can ask your agent questions, as anyone can chat on your website. Your agent's compliance rules apply to every question and answer, and what other agents tell it is treated as unconfirmed.
- It uses AI credit. Each question is a turn of your agent, like a chat message.
- Everything is recorded. Each exchange is kept as a conversation on your agent. Insights, under Agent access, shows what agents asked and how often calls succeed.
- To stop it, untick Enabled, or delete the integration under Danger zone. The card stops resolving and calls are refused straight away. A card on your own server stays there until you remove it, but calls to it are refused.
Need help?#
Email hello@subcontext.com.