Detailed explanation of AI Agent protocol A2A interaction details

Get an in-depth understanding of how AI agents can collaborate efficiently through the A2A protocol.
Core content:
1. Aaron, an AI expert, shares his personal background and practice
2. The release of Google's A2A protocol and its significance to AI agents
3. Detailed examples and application scenarios of the A2A protocol interaction process
summary
Google has released the A2A protocol (Agent2Agent) for multi-agent scenarios, which will enable AI Agents to communicate with each other, exchange information securely, and coordinate actions on various enterprise platforms or applications. This article is a detailed supplement to the previous article.
Example method and JSON response
The following is a detailed example description of the entire interaction process.
AgentCard
{
"name" : "Google Maps Proxy" ,
"description" : "Plan routes, remember locations and generate navigation" ,
"url" : "https://maps-agent.google.com" ,
"provider" : {
"organization" : "Google" ,
"url" : "https://google.com"
} ,
"version" : "1.0.0" ,
"authentication" : {
"schemes" : "OAuth2"
} ,
"defaultInputModes" : [ "text/plain" ] ,
"defaultOutputModes" : [ "text/plain" , "application/html" ] ,
"capabilities" : {
"streaming" : true ,
"pushNotifications" : false
} ,
"skills" : [
{
"id" : "route-planner" ,
"name" : "Route Planning" ,
"description" : "Helps plan a route between two locations" ,
"tags" : [ "map" , "route" , "navigation" ] ,
"examples" : [
"Planning a route from Sunnyvale to Mountain View" ,
"What is the commute time from Sunnyvale to San Francisco at 9 AM?" ,
"Creating turn-by-turn navigation from Sunnyvale to Mountain View"
] ,
"outputModes" : [ "application/html" , "video/mp4" ]
} ,
{
"id" : "custom-map" ,
"name" : "My Map" ,
"description" : "Manage custom maps with your saved places" ,
"tags" : [ "Custom map" , "Save location" ] ,
"examples" : [
"Show my favorite restaurants on a map" ,
"Create a visualization of all the places I've visited in the past year"
] ,
"outputModes" : [ "application/html" ]
}
]
}
Sending tasks
Allows a client to send content to a remote agent to start a new task, resume an interrupted task, or reopen a completed task. A task may be interrupted because the agent requires additional user input or because of a runtime error.
// ask
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"method" : "tasks/send" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"message" : {
"role" : "user" ,
"data" : [ {
"type" : "text" ,
"text" : "Tell me a joke"
} ]
} ,
"metadata" : { }
}
}
// Response
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"status" : {
"state" : "completed"
} ,
"artifacts" : [ {
"name" : "joke" ,
"parts" : [ {
"type" : "text" ,
"text" : "Why did the chicken cross the road? Because it wanted to go to the other side!"
} ]
} ] ,
"metadata" : { }
}
}
Get Tasks
Clients can use this method to retrieve artifacts generated by a task. The broker determines the retention window for previously submitted tasks. The broker may return error codes for tasks that exceed the retention window or for short-lived tasks that the broker does not persist. Clients can also request the last N history items of a task, which includes all messages sent in order by the client and the server. The default value is 0 (no history).
// ask
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"method" : "tasks/get" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"historyLength" : 10 ,
"metadata" : { }
}
}
// Response
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"status" : {
"state" : "completed"
} ,
"artifacts" : [ {
"parts" : [ {
"type" : "text" ,
"text" : "Why did the chicken cross the road? Because it wanted to go to the other side!"
} ]
} ] ,
"history" : [
{
"role" : "user" ,
"parts" : [
{
"type" : "text" ,
"text" : "Tell me a joke"
}
]
}
] ,
"metadata" : { }
}
}
Cancel a task
A client may choose to cancel a previously submitted task as follows.
// ask
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"method" : "tasks/cancel" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"metadata" : { }
}
}
// Response
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : 1 ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"status" : {
"state" : "canceled"
} ,
"metadata" : { }
}
}
Set up task push notifications
Clients can configure a push notification URL to receive updates for task status changes.
// ask
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"method" : "tasks/pushNotification/set" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"pushNotificationConfig" : {
"url" : "https://example.com/callback" ,
"authentication" : {
"schemes" : [ "jwt" ]
}
}
}
}
// Response
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"pushNotificationConfig" : {
"url" : "https://example.com/callback" ,
"authentication" : {
"schemes" : [ "jwt" ]
}
}
}
}
Get task push notification
Clients can use this method to retrieve the push notification configuration currently configured for a task.
// ask
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"method" : "tasks/pushNotification/get" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64"
}
}
// Response
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"pushNotificationConfig" : {
"url" : "https://example.com/callback" ,
"authentication" : {
"schemes" : [ "jwt" ]
}
}
}
}
Multi-round dialogue
If the remote agent requires additional user input, the task may pause execution. When a task is in the "Input Required" state, the client needs to provide additional input in order for the task to resume processing on the remote agent. Messages included in the "Input Required" state MUST include details indicating the actions that the client must perform. Examples include "Fill out this form" or "Log in to SaaS service foo". If structured data is included, the instructions SHOULD be sent as one part and the structured data as a second part.
// Request - Sequence 1
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"method" : "tasks/send" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"message" : {
"role" : "user" ,
"parts" : [ {
"type" : "text" ,
"text" : "Buy me a new phone"
} ]
} ,
"metadata" : { }
}
}
// Response - Sequence 2
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"status" : {
"state" : "input-required" ,
"message" : {
"parts" : [ {
"type" : "text" ,
"text" : "Select phone type (iPhone/Android)"
} ]
}
} ,
"metadata" : { }
}
}
// Request - Sequence 3
{
"jsonrpc" : "2.0" ,
"id" : 2 ,
"method" : "tasks/send" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"message" : {
"role" : "user" ,
"parts" : [ {
"type" : "text" ,
"text" : "Android"
} ]
} ,
"metadata" : { }
}
}
// Response - Sequence 4
{
"jsonrpc" : "2.0" ,
"id" : 2 ,
"result" : {
"id" : 1 ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"status" : {
"state" : "completed"
} ,
"artifacts" : [ {
"name" : "order-confirmation" ,
"parts" : [ {
"type" : "text" ,
"text" : "I have ordered a new Android device for you. Your request number is R12443"
} ] ,
"metadata" : { }
} ] ,
"metadata" : { }
}
}
Streaming support
For clients and remote agents capable of using SSE communication over HTTP, the client can send an RPC request with method tasks/sendSubscribe when creating a new task. The remote agent can respond with a series of TaskStatusUpdateEvents (for communicating state changes or instructions/requests) and TaskArtifactUpdateEvents (for streaming the results of the build). Note that TaskArtifactUpdateEvents can append new parts to existing artifacts. Clients can use tasks/get to retrieve the entire artifact outside of streaming. The agent must set the final: true property at the end of the stream or when the agent is interrupted and requires additional user input.
// ask
{
"method" : "tasks/sendSubscribe" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"message" : {
"role" : "user" ,
"parts" : [ {
"type" : "text" ,
"text" : "Write a long text describing the accompanying image"
} , {
"type" : "file" ,
"file" : {
"mimeType" : "image/png" ,
"data" : "<base64-encoded-content>"
}
} ]
} ,
"metadata" : { }
}
}
// Response
data : {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : 1 ,
"status" : {
"state" : "working" ,
"timestamp" : "2025-04-02T16:59:25.331844"
} ,
"final" : false
}
}
data : {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : 1 ,
"artifact" : [
"parts" : [
{ "type" : "text" , "text" : "<section 1...>" }
] ,
"index" : 0 ,
"append" : false ,
"lastChunk" : false
]
}
}
data : {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : 1 ,
"artifact" : [
"parts" : [
{ "type" : "text" , "text" : "<section 2...>" }
] ,
"index" : 0 ,
"append" : true ,
"lastChunk" : false
]
}
}
data : {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : 1 ,
"artifact" : [
"parts" : [
{ "type" : "text" , "text" : "<section 3...>" }
] ,
"index" : 0 ,
"append" : true ,
"lastChunk" : true
]
}
}
data : {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : 1 ,
"status" : {
"state" : "completed" ,
"timestamp" : "2025-04-02T16:59:35.331844"
} ,
"final" : true
}
}
Resubscribe to Task
Disconnected clients can resubscribe to a streaming-capable remote agent to receive task updates via SSE.
// ask
{
"method" : "tasks/resubscribe" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"metadata" : { }
}
}
// Response
data : {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"artifact" : [
"parts" : [
{ "type" : "text" , "text" : "<section 2...>" }
] ,
"index" : 0 ,
"append" : true ,
"lastChunk" : false
]
}
}
data : {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"artifact" : [
"parts" : [
{ "type" : "text" , "text" : "<section 3...>" }
] ,
"index" : 0 ,
"append" : true ,
"lastChunk" : true
]
}
}
data : {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"id" : 1 ,
"status" : {
"state" : "completed" ,
"timestamp" : "2025-04-02T16:59:35.331844"
} ,
"final" : true
}
}
Non-text media
The following is an example interaction between a client and a proxy using non-text data.
// Request - Sequence 1
{
"jsonrpc" : "2.0" ,
"id" : 9 ,
"method" : "tasks/send" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"message" : {
"role" : "user" ,
"parts" : [ {
"type" : "text" ,
"text" : "Analyzes the attached report and generates a high-level overview"
} , {
"type" : "file" ,
"file" : {
"mimeType" : "application/pdf" ,
"data" : "<base64-encoded-content>"
}
} ]
} ,
"metadata" : { }
}
}
// Response - Sequence 2
{
"jsonrpc" : "2.0" ,
"id" : 9 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"status" : {
"state" : "working" ,
"message" : {
"role" : "agent" ,
"parts" : [ {
"type" : "text" ,
"text" : "Analysis in progress, please wait"
} ] ,
"metadata" : { }
}
} ,
"metadata" : { }
}
}
// Request - Sequence 3
{
"jsonrpc" : "2.0" ,
"id" : 10 ,
"method" : "tasks/get" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"metadata" : { }
}
}
// Response - Sequence 4
{
"jsonrpc" : "2.0" ,
"id" : 9 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"status" : {
"state" : "completed"
} ,
"artifacts" : [ {
"parts" : [ {
"type" : "text" ,
"text" : "<Generate analysis content>"
} ] ,
"metadata" : { }
} ] ,
"metadata" : { }
}
}
Structured output
Either the client or the proxy can request structured output from the other.
// ask
{
"jsonrpc" : "2.0" ,
"id" : 9 ,
"method" : "tasks/send" ,
"params" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"message" : {
"role" : "user" ,
"parts" : [ {
"type" : "text" ,
"text" : "Show me a list of unclosed IT tickets" ,
"metadata" : {
"mimeType" : "application/json" ,
"schema" : {
"type" : "array" ,
"items" : {
"type" : "object" ,
"properties" : {
"ticketNumber" : { "type" : "string" } ,
"description" : { "type" : "string" }
}
}
}
}
} ]
} ,
"metadata" : { }
}
}
// Response
{
"jsonrpc" : "2.0" ,
"id" : 9 ,
"result" : {
"id" : "de38c76d-d54c-436c-8b9f-4c2703648d64" ,
"sessionId" : "c295ea44-7543-4f78-b524-7a38915ad6e4" ,
"status" : {
"state" : "working" ,
"message" : {
"role" : "agent" ,
"parts" : [ {
"type" : "text" ,
"text" : "[{\"ticketNumber\":\"REQ12312\",\"description\":\"Request VPN access\"},{\"ticketNumber\":\"REQ23422\",\"description\":\"Add to DL - team-gcp-onboarding\"}]"
} ] ,
"metadata" : { }
}
} ,
"metadata" : { }
}
}
Error handling
The following is the error message format that the server responds to the client when it encounters an error while processing a client request.
interface ErrorMessage {
code : number ;
message : string ;
data ?: any ;
}
The following are standard JSON-RPC error codes that the server can respond to in error scenarios: