> ## Documentation Index
> Fetch the complete documentation index at: https://docs.evo-ai.co/llms.txt
> Use this file to discover all available pages before exploring further.

# A2A Protocol

> Integrate agents using the Agent-to-Agent protocol for standardized communication between AI agents

## Overview

The **Agent-to-Agent Protocol (A2A)** is a standardized protocol developed by Google to enable structured communication between independent AI agents. Using JSON-RPC 2.0 over HTTP/HTTPS, A2A facilitates interoperability between different agent systems, allowing them to work together efficiently.

<Note>
  **Official Protocol**: A2A is maintained by Google and is available at [google.github.io/A2A](https://google.github.io/A2A/specification/).
  The source code can be found in the [GitHub repository](https://github.com/google/A2A).
</Note>

## Key Features

<CardGroup cols={2}>
  <Card title="JSON-RPC 2.0" icon="code">
    Protocol based on JSON-RPC 2.0 for structured and standardized communication
  </Card>

  <Card title="Multi-turn" icon="comments">
    Native support for multi-turn conversations using contextId
  </Card>

  <Card title="File Upload" icon="upload">
    File transfer via Base64 with support for different MIME types
  </Card>

  <Card title="Streaming" icon="bolt">
    Asynchronous communication via Server-Sent Events (SSE) for real-time responses
  </Card>
</CardGroup>

## Quick Overview

| Key Point                | Summary                                                                                                                                                                                                       |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Objective**            | Standardize conversation between AI agents (regardless of vendor) using JSON-RPC 2.0                                                                                                                          |
| **Base format**          | Each call is a JSON object with `jsonrpc:"2.0"`, `id`, `method` and `params`                                                                                                                                  |
| **Main methods**         | `message/send` • `message/stream` • `tasks/get` • `tasks/cancel` • `tasks/pushNotificationConfig/{set\|get}` • `tasks/resubscribe` • `agent/authenticatedExtendedCard`                                        |
| **Required IDs**         | `messageId` (UUID v4) within each message and `id`/`taskId`/`callId` to track request and task                                                                                                                |
| **First-class features** | Multi-turn conversations (`contextId`) • File upload (`parts[]` type `file` with Base64 + MIME) • Push notifications via `pushNotificationConfig` • Authentication via `x-api-key` or `Authorization: Bearer` |
| **Task lifecycle**       | `submitted → working → completed / failed / canceled`, reported in `result.status.state`                                                                                                                      |

## Protocol Methods

### message/send (Synchronous HTTP)

The main method for sending messages synchronously.

<AccordionGroup>
  <Accordion icon="paper-plane" title="Request Structure">
    ```json theme={null}
    POST /api/v1/a2a/AGENT-ID
    Content-Type: application/json
    x-api-key: YOUR_API_KEY

    {
      "jsonrpc": "2.0",
      "id": "req-001",
      "method": "message/send",
      "params": {
        "message": {
          "role": "user",
          "parts": [{ "type": "text", "text": "Hello, who are you?" }],
          "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
        },
        "sessionId": "session-789",    // optional, for multi-turn
        "id": "task-456"               // optional taskId
      }
    }
    ```
  </Accordion>

  <Accordion icon="reply" title="Typical Response">
    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "result": {
        "id": "task-456",
        "status": {
          "state": "completed",
          "message": {
            "role": "agent",
            "parts": [{ "type": "text", "text": "I'm an A2A agent ready to help!" }]
          }
        },
        "final": true
      },
      "id": "req-001"
    }
    ```
  </Accordion>
</AccordionGroup>

### message/stream (Asynchronous SSE)

For real-time communication with streaming responses.

<AccordionGroup>
  <Accordion icon="bolt" title="Initial Request">
    ```json theme={null}
    POST /api/v1/a2a/AGENT-ID
    Content-Type: application/json
    Accept: text/event-stream
    x-api-key: YOUR_API_KEY

    {
      "jsonrpc": "2.0",
      "id": "req-002",
      "method": "message/stream",
      "params": {
        "message": {
          "role": "user",
          "parts": [{ "type": "text", "text": "Generate a detailed report" }],
          "messageId": "uuid-here"
        }
      }
    }
    ```
  </Accordion>

  <Accordion icon="wifi" title="SSE Events">
    ```
    data: {"jsonrpc":"2.0","id":"req-002",
           "result":{"id":"task-789",
                     "status":{"state":"working"},
                     "final":false}}

    data: {"jsonrpc":"2.0","id":"req-002",
           "result":{"id":"task-789",
                     "status":{"state":"completed",
                               "message":{"role":"agent",
                                          "parts":[{"type":"text","text":"Here's your report..."}]}},
                     "final":true}}
    ```
  </Accordion>
</AccordionGroup>

## Implementation Examples

### cURL

<CodeGroup>
  ```bash message/send theme={null}
  curl -X POST http://localhost:8000/api/v1/a2a/AGENT-ID \
    -H 'Content-Type: application/json' \
    -H 'x-api-key: YOUR_API_KEY' \
    -d '{
      "jsonrpc": "2.0",
      "id": "req-001",
      "method": "message/send",
      "params": {
        "message": {
          "role": "user",
          "parts": [{"type": "text", "text": "Hello!"}],
          "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
        }
      }
    }'
  ```

  ```bash message/stream theme={null}
  curl -X POST http://localhost:8000/api/v1/a2a/AGENT-ID \
    -H 'Content-Type: application/json' \
    -H 'Accept: text/event-stream' \
    -H 'x-api-key: YOUR_API_KEY' \
    -d '{
      "jsonrpc": "2.0",
      "id": "req-002",
      "method": "message/stream",
      "params": {
        "message": {
          "role": "user",
          "parts": [{"type": "text", "text": "Streaming test"}],
          "messageId": "uuid-here"
        }
      }
    }'
  ```
</CodeGroup>

### JavaScript / Fetch

<CodeGroup>
  ```javascript message/send theme={null}
  const payload = {
    "jsonrpc": "2.0",
    "id": "req-001",
    "method": "message/send",
    "params": {
      "message": {
        "role": "user",
        "parts": [{"type": "text", "text": "Explain the A2A protocol"}],
        "messageId": crypto.randomUUID()
      }
    }
  };

  const response = await fetch('/api/v1/a2a/AGENT-ID', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': 'YOUR_API_KEY'
    },
    body: JSON.stringify(payload)
  });

  const result = await response.json();
  console.log(result);
  ```

  ```javascript message/stream theme={null}
  const payload = {
    "jsonrpc": "2.0",
    "id": "req-002",
    "method": "message/stream",
    "params": {
      "message": {
        "role": "user",
        "parts": [{"type": "text", "text": "Streaming response"}],
        "messageId": crypto.randomUUID()
      }
    }
  };

  const response = await fetch('/api/v1/a2a/AGENT-ID', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'text/event-stream',
      'x-api-key': 'YOUR_API_KEY'
    },
    body: JSON.stringify(payload)
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    const chunk = decoder.decode(value);
    const lines = chunk.split('\n');
    
    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const data = JSON.parse(line.slice(6));
        console.log(data);
        
        if (data.result?.final) {
          return; // End stream
        }
      }
    }
  }
  ```
</CodeGroup>

### Python

<CodeGroup>
  ```python message/send theme={null}
  import requests
  import uuid
  import json

  payload = {
      "jsonrpc": "2.0",
      "id": str(uuid.uuid4()),
      "method": "message/send",
      "params": {
          "message": {
              "role": "user",
              "parts": [{"type": "text", "text": "Explain the A2A protocol"}],
              "messageId": str(uuid.uuid4())
          }
      }
  }

  response = requests.post(
      "http://localhost:8000/api/v1/a2a/AGENT-ID",
      headers={"x-api-key": "YOUR_API_KEY"},
      json=payload
  )

  print(json.dumps(response.json(), indent=2, ensure_ascii=False))
  ```

  ```python message/stream theme={null}
  import requests
  import uuid
  import json

  payload = {
      "jsonrpc": "2.0",
      "id": str(uuid.uuid4()),
      "method": "message/stream",
      "params": {
          "message": {
              "role": "user",
              "parts": [{"type": "text", "text": "Streaming response"}],
              "messageId": str(uuid.uuid4())
          }
      }
  }

  response = requests.post(
      "http://localhost:8000/api/v1/a2a/AGENT-ID",
      headers={
          "x-api-key": "YOUR_API_KEY",
          "Accept": "text/event-stream"
      },
      json=payload,
      stream=True
  )

  for line in response.iter_lines():
      if line:
          line_str = line.decode('utf-8')
          if line_str.startswith('data: '):
              data = json.loads(line_str[6:])
              print(json.dumps(data, indent=2, ensure_ascii=False))
              
              if data.get('result', {}).get('final'):
                  break
  ```
</CodeGroup>

## File Upload

The A2A protocol supports file upload through the `file` type in `parts`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "req-003",
  "method": "message/send",
  "params": {
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "Analyze this image"
        },
        {
          "type": "file",
          "file": {
            "name": "image.png",
            "mimeType": "image/png",
            "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAUA..." // Base64 without header
          }
        }
      ],
      "messageId": "uuid-here"
    }
  }
}
```

<Warning>
  **Base64 Format**: Files must be encoded in Base64 **without** the `data:mime/type;base64,` header.
  Only the pure Base64 content should be included in the `bytes` field.
</Warning>

## Multi-turn Conversations

To maintain context between multiple messages, use the `contextId`:

<AccordionGroup>
  <Accordion icon="message" title="First message">
    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "id": "req-001",
      "method": "message/send",
      "params": {
        "message": {
          "role": "user",
          "parts": [{"type": "text", "text": "My name is John"}],
          "messageId": "msg-001"
        }
      }
    }
    ```

    **Response:**

    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "result": {
        "id": "task-001",
        "contextId": "ctx-abc123", // Save this ID
        "status": {
          "state": "completed",
          "message": {
            "role": "agent",
            "parts": [{"type": "text", "text": "Hello John! How can I help you?"}]
          }
        }
      }
    }
    ```
  </Accordion>

  <Accordion icon="reply" title="Subsequent message">
    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "id": "req-002",
      "method": "message/send",
      "params": {
        "contextId": "ctx-abc123", // Use the previous contextId
        "message": {
          "role": "user",
          "parts": [{"type": "text", "text": "What is my name?"}],
          "messageId": "msg-002"
        }
      }
    }
    ```

    **Response:**

    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "result": {
        "id": "task-002",
        "contextId": "ctx-abc123",
        "status": {
          "state": "completed",
          "message": {
            "role": "agent",
            "parts": [{"type": "text", "text": "Your name is John!"}]
          }
        }
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Task States

The A2A protocol defines specific states for the task lifecycle:

| State       | Description                                |
| ----------- | ------------------------------------------ |
| `submitted` | Task has been received and is in the queue |
| `working`   | Task is being processed                    |
| `completed` | Task completed successfully                |
| `failed`    | Task failed during processing              |
| `canceled`  | Task was canceled by the user              |

## Authentication

The protocol supports different authentication methods:

<Tabs>
  <Tab title="API Key">
    ```http theme={null}
    x-api-key: YOUR_API_KEY
    ```
  </Tab>

  <Tab title="Bearer Token">
    ```http theme={null}
    Authorization: Bearer YOUR_TOKEN
    ```
  </Tab>
</Tabs>

## Tips and Best Practices

<AccordionGroup>
  <Accordion icon="lightbulb" title="Unique IDs">
    * Use **UUID v4** for all required IDs (`messageId`, `id`, etc.)
    * Maintain consistency in IDs for proper tracking
  </Accordion>

  <Accordion icon="comments" title="Multi-turn">
    * Always save the returned `contextId` for continuous conversations
    * Send the `contextId` in all subsequent messages of the same conversation
  </Accordion>

  <Accordion icon="file" title="Files">
    * Use Base64 **without header** in the `bytes` field
    * Always specify the correct `mimeType`
    * Consider the maximum size supported by the server
  </Accordion>

  <Accordion icon="bolt" title="Streaming">
    * Handle ping events (`: ping`) appropriately
    * Close the `EventSource` connection when `final: true`
    * Implement reconnection handling for robustness
  </Accordion>

  <Accordion icon="globe" title="CORS">
    * Configure CORS on the server (`Access-Control-Allow-Origin: *`) for browser testing
    * Use appropriate headers for production
  </Accordion>
</AccordionGroup>

## Additional Resources

<CardGroup cols={2}>
  <Card title="Official Specification" icon="book" href="https://google.github.io/A2A/specification/">
    Complete A2A protocol documentation maintained by Google
  </Card>

  <Card title="GitHub Repository" icon="github" href="https://github.com/google/A2A">
    Source code, examples and issues for the A2A project
  </Card>

  <Card title="Quick Start Guide" icon="rocket" href="/quickstart">
    Set up your first agent in less than 2 minutes
  </Card>

  <Card title="Agent Types" icon="users" href="/agents/index">
    Explore different types of agents compatible with A2A
  </Card>
</CardGroup>

***

With the A2A protocol, you can quickly integrate any agent or front-end application into the Evo AI ecosystem, ensuring interoperability and standardized communication between different AI agent systems.
