A2A Protocol
Let PromptRails agents discover and hand work to other agents when one workflow needs more than one specialist.
Best for
Engineers building against the API, SDKs, CLI, MCP, or local tooling
Use A2A when one agent should hand work to another specialist instead of trying to do everything itself. PromptRails publishes agent capabilities, accepts incoming agent tasks, and records the handoff so teams can see which agent did what.
What is A2A?
A2A gives agents a shared contract for collaboration:
- Discover other agents through agent cards
- Request work from an agent that owns a specific skill
- Track status while the other agent works
- Receive results in a predictable format
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.
# 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]}")Technical detailsProtocol message format
JSON-RPC messaging
A2A communication uses JSON-RPC 2.0 as the transport format. Messages include:
{
"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) |
Technical detailsSDK task operations
Creating and Managing Tasks
Send a Task
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
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
client.a2a.cancel_task("task-id")Task Artifacts
When a task completes, the agent may produce artifacts -- structured outputs that represent the work product:
{
"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:
# 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:
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 tasksInput-Required Flow
An agent can request additional input during processing:
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,
)Technical detailsTask field reference
Related Topics
- Agents -- Agents that participate in A2A
- Executions -- A2A tasks create executions
- Python SDK -- Python A2A client
- JavaScript SDK -- JavaScript A2A client