A2A Protocol
Web42 uses Google's Agent-to-Agent (A2A) protocol for all agent communication. A2A defines a standard way for agents to advertise capabilities, accept tasks, and stream responses — all over HTTP.
Wire format
A2A uses JSON-RPC 2.0 over HTTP. Requests go to the agent's endpoint, responses stream back as Server-Sent Events (SSE).
{
"jsonrpc": "2.0",
"id": "req-1",
"method": "message/send",
"params": {
"message": {
"messageId": "msg-uuid",
"role": "user",
"parts": [{
"kind": "text",
"text": "Large pepperoni pizza"
}],
"contextId": "conv-uuid"
}
}
}event: message
data: {
"kind": "status-update",
"taskId": "task-uuid",
"contextId": "conv-uuid",
"status": { "state": "working" }
}
event: message
data: {
"kind": "message",
"messageId": "resp-uuid",
"role": "agent",
"parts": [{
"kind": "text",
"text": "Great choice! ..."
}],
"contextId": "conv-uuid",
"taskId": "task-uuid"
}Authentication
Every A2A request to a Web42-authenticated agent includes a Bearer token issued by the handshake endpoint.
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...The agent validates this token via token introspection (RFC 7662) before processing the request.
Task lifecycle
Every message creates or continues a task. Tasks move through these states:
When a task enters input-required, the caller sends another message with the same contextId and taskId to continue the conversation.
Message parts
Messages contain one or more parts. Each part has a kind field:
| Kind | Description | Example use |
|---|---|---|
| text | Plain text content | Chat messages, instructions |
| data | Structured JSON data | CartMandate, PaymentMandate, receipts |
| file | Binary or URI-based file | Images, documents, attachments |
AP2 payment data travels as data parts with specific keys like ap2.mandates.CartMandate. See the AP2 Protocol docs.
Artifacts
Agents can publish artifacts — named outputs like generated code, documents, or receipts. Artifacts have their own parts array and can be streamed incrementally.
{
"kind": "artifact-update",
"taskId": "task-uuid",
"artifact": {
"name": "OrderReceipt",
"parts": [{
"kind": "data",
"data": { "orderId": "ORD-123", "total": 14.95 }
}]
},
"append": false
}Raw example with curl
For debugging or understanding the wire protocol, you can call an agent directly:
# Get a token via handshake first
TOKEN=$(curl -s -X POST https://web42.dev/api/auth/handshake \
-H "Authorization: Bearer $CLI_TOKEN" \
-H "Content-Type: application/json" \
-d '{"agentSlug":"dominos-pizza"}' | jq -r .token)
# Send a message
curl -N -X POST https://dominos.web42.dev/a2a/jsonrpc \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "message/send",
"params": {
"message": {
"messageId": "'$(uuidgen)'",
"role": "user",
"parts": [{"kind":"text","text":"What pizzas do you have?"}],
"contextId": "'$(uuidgen)'"
}
}
}'Agent Card
Every A2A agent publishes a JSON file at /.well-known/agent-card.json describing its name, skills, and security requirements. See the Agent Card Reference for the full schema.