# A2A Protocol

> Enable agent-to-agent communication with Google's A2A protocol, agent cards, JSON-RPC messaging, and task lifecycle management.

Source: https://0.0.0.0:8080/docs/a2a-protocol

PromptRails implements the **Agent-to-Agent (A2A) protocol**, an open standard by Google for inter-agent communication. A2A enables agents to discover each other, exchange messages, and coordinate on tasks across different systems and platforms.

## What is A2A?

The A2A protocol defines a standard way for AI agents to:

- **Discover** other agents through agent cards
- **Communicate** using JSON-RPC messages
- **Coordinate** work through a task lifecycle
- **Exchange results** via task artifacts

This enables multi-agent architectures where specialized agents collaborate to solve complex problems, even when running on different platforms.

## Agent Cards

An agent card is a machine-readable description of an agent's capabilities. It includes:

- Agent name and description
- Supported input/output formats
- Available skills and capabilities
- Authentication requirements
- Endpoint URL

Agent cards enable automated discovery -- one agent can find and evaluate other agents based on their published capabilities.

```python
# Get an agent's A2A card
card = client.a2a.get_agent_card("your-agent-id")

print(f"Name: {card.name}")
print(f"Description: {card.description}")
print(f"Skills: {[skill.name for skill in card.skills]}")
```

## JSON-RPC Messaging

A2A communication uses JSON-RPC 2.0 as the transport format. Messages include:

```json
{
  "jsonrpc": "2.0",
  "method": "tasks/send",
  "params": {
    "id": "task-id",
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "Analyze this dataset and generate a report"
        }
      ]
    }
  }
}
```

## Task Lifecycle

A2A tasks follow a defined lifecycle:

```
submitted -> working -> completed
                     -> failed
                     -> canceled
                     -> rejected
          -> input_required -> (user provides input) -> working
```

### Task Statuses

| Status           | Description                                              |
| ---------------- | -------------------------------------------------------- |
| `submitted`      | Task has been submitted to the agent                     |
| `working`        | Agent is actively processing the task                    |
| `input_required` | Agent needs additional input to continue                 |
| `completed`      | Task finished successfully                               |
| `failed`         | Task encountered an error                                |
| `canceled`       | Task was cancelled by the requester                      |
| `rejected`       | Agent rejected the task (e.g., outside its capabilities) |

## Creating and Managing Tasks

### Send a Task

```python
task = client.a2a.send_message(
    "your-agent-id",
    "Summarize the Q4 sales report",
    context_id="optional-conversation-context"
)

print(f"Task ID: {task.id}")
print(f"Status: {task.status.state}")
```

### Get Task Status

```python
task = client.a2a.get_task("task-id")

print(f"Status: {task.status.state}")
print(f"Messages: {len(task.messages)}")
print(f"Artifacts: {len(task.artifacts)}")
```

### Cancel a Task

```python
client.a2a.cancel_task("task-id")
```

## Task Artifacts

When a task completes, the agent may produce artifacts -- structured outputs that represent the work product:

```json
{
  "artifacts": [
    {
      "type": "text",
      "text": "The Q4 sales report shows a 15% increase..."
    },
    {
      "type": "file",
      "name": "report.pdf",
      "mimeType": "application/pdf",
      "data": "base64-encoded-content"
    }
  ]
}
```

## Multi-Agent Coordination

A2A enables patterns like:

### Sequential Processing

Agent A processes data, then passes results to Agent B for further analysis:

```python
# Agent A: Data extraction
task_a = client.a2a.send_message(
    "data-extractor-agent",
    "Extract sales data from Q4"
)

# Wait for completion, then pass to Agent B
# Agent B: Analysis
task_b = client.a2a.send_message(
    "analyst-agent",
    f"Analyze: {task_a_result}",
    context_id=task_a.context_id
)
```

### Parallel Processing

Multiple agents work on different aspects simultaneously:

```python
import asyncio

async def multi_agent_analysis():
    async with AsyncPromptRails(api_key="your-key") as client:
        tasks = await asyncio.gather(
            client.a2a.send_message("sentiment-agent", "Analyze sentiment"),
            client.a2a.send_message("topic-agent", "Extract key topics"),
            client.a2a.send_message("summary-agent", "Summarize the conversation"),
        )
        return tasks
```

### Input-Required Flow

An agent can request additional input during processing:

```python
task = client.a2a.send_message("agent-id", initial_message)

# Check if the agent needs more input
if task.status and task.status.state == "input_required":
    # Provide additional input
    task = client.a2a.send_message(
        "agent-id",
        "Additional context...",
        task_id=task.id,
    )
```

## Task Fields

| Field        | Type      | Description                     |
| ------------ | --------- | ------------------------------- |
| `id`         | KSUID     | Unique task identifier          |
| `context_id` | string    | Conversation context identifier |
| `status`     | object    | Current task status payload     |
| `messages`   | array     | Message history                 |
| `artifacts`  | array     | Task outputs                    |
| `metadata`   | JSON      | Custom metadata                 |
| `created_at` | timestamp | Creation time                   |
| `updated_at` | timestamp | Last update time                |

## Related Topics

- [Agents](/docs/agents) -- Agents that participate in A2A
- [Executions](/docs/executions) -- A2A tasks create executions
- [Python SDK](/docs/python-sdk) -- Python A2A client
- [JavaScript SDK](/docs/javascript-sdk) -- JavaScript A2A client
