A2A Protocol
A2A routes provide gateway discovery plus task-style run submission and control.
Endpoints
Discovery:
GET /.well-known/agent-card.jsonGET /v1/a2a/agentsGET /v1/a2a/agents/:agent_id/agent-card
Task APIs:
POST /v1/a2a/agents/:agent_id/message:sendGET /v1/a2a/agents/:agent_id/tasks/:task_idPOST /v1/a2a/agents/:agent_id/tasks/:task_id:cancel
Discovery Semantics
/.well-known/agent-card.json:
- Returns a gateway card with
taskManagement,streaming, andagentDiscoverycapability flags. - Adds HTTP caching headers:
cache-control: public, max-age=30, must-revalidateetag: W/"a2a-agents-..."
- Supports
if-none-match(*and CSV values).
Single-agent deployment:
- Well-known card
urlpoints directly to/v1/a2a/agents/<id>/message:send.
Multi-agent deployment:
- Well-known card
urlpoints to/v1/a2a/agents.
message:send Request
Accepted payload fields:
contextId/context_id(optional)taskId/task_id(optional)input(optional string)message(optional object:{ role?, content })decisions(optionalToolCallDecision[])
Example (new task):
{
"input": "hello from a2a"
}
Example (continue existing task):
{
"taskId": "run-1",
"input": "continue"
}
Example (decision-only forward):
{
"taskId": "run-1",
"decisions": [
{
"target_id": "fc_perm_1",
"decision_id": "d1",
"action": "resume",
"result": { "approved": true },
"updated_at": 1760000000000
}
]
}
Response for submission (202):
{
"contextId": "thread-1",
"taskId": "run-1",
"status": "submitted"
}
Response for decision forwarding (202):
{
"contextId": "thread-1",
"taskId": "run-1",
"status": "decision_forwarded"
}
Task Query
GET /v1/a2a/agents/:agent_id/tasks/:task_id response:
{
"taskId": "run-1",
"contextId": "thread-1",
"status": "done",
"origin": "a2a",
"terminationCode": null,
"terminationDetail": null,
"createdAt": 1760000000000,
"updatedAt": 1760000005000,
"message": {
"role": "assistant",
"content": "final assistant reply"
},
"artifacts": [
{
"content": "final assistant reply"
}
],
"history": [
{
"role": "user",
"content": "hello from a2a"
},
{
"role": "assistant",
"content": "final assistant reply"
}
]
}
Notes:
messageis the latest public assistant output when one exists; otherwise it isnull.artifactscontains the latest public assistant output normalized as text artifacts.historycontains publicuser/assistant/systemthread messages in order.
Task Cancel
POST /v1/a2a/agents/:agent_id/tasks/:task_id:cancel
Response (202):
{
"taskId": "run-1",
"status": "cancel_requested"
}
Validation and Errors
- Action must be exactly
message:send. - Decision-only requests require
taskId. - Empty payloads are rejected unless at least one of
input/message/decisions/contextId/taskIdexists. - Cancel path must end with
:canceland must bePOST. 404for unknown agent or missing task/run.400when task exists but is not active (task is not active).
Error body shape:
{ "error": "bad request: unsupported A2A action; expected 'message:send'" }