Detailed explanation of AI Agent protocol A2A interaction details

Written by
Caleb Hayes
Updated on:June-19th-2025
Recommendation

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

Yang Fangxian
Founder of 53A/Most Valuable Expert of Tencent Cloud (TVP)


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  { 
  codenumber ;
  messagestring ;
  data ?:  any ;
}

The following are standard JSON-RPC error codes that the server can respond to in error scenarios:

Error Code
information
describe
-32700
JSON parsing error
Invalid JSON was sent
-32600
Invalid request
Invalid JSON-RPC validation error
-32601
Can't find a method
Not an effective method
-32602
Invalid parameters
Invalid method parameter
-32603
Internal Error
Internal JSON-RPC error
-32000 to -32099
Server Error
Reserved for implementation specific error codes
-32001
Task not found
A task with the specified ID could not be found
-32002
The task cannot be canceled
The task cannot be canceled by the remote agent
-32003
Push notifications not supported
Push notifications are not supported
-32004
Unsupported Operation
Unsupported Operation
-32005
Incompatible content type
Incompatible content types between client and proxy