Agent-to-Agent Communication
Agent-to-Agent (A2A) enables agents to collaborate, delegate tasks, and communicate with each other—even across organizational boundaries.
Why A2A?
Complex problems often require specialized skills:
- Specialization: Let each agent focus on what it does best
- Delegation: Manager agents coordinate specialist agents
- Federation: Agents from different organizations collaborate
- Scalability: Distribute work across many agents
How A2A Works
Deeployd implements the A2A Protocol - an open standard for agent interoperability.
Agent A ──task/send──▶ Agent B ──executes──▶ Returns result
- Agent A sends a task to Agent B
- Agent B processes the task
- Agent B returns results (or status updates)
- Agent A continues with the results
A2A Protocol Basics
Agent Cards
Every A2A-capable agent has a discovery document:
GET /.well-known/agent-card.json
{
"name": "Data Analysis Agent",
"url": "https://api.deeployd.com/agents/agent-123",
"version": "1.0.0",
"protocolVersion": "1.0",
"description": "Analyzes data and generates insights",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": true
},
"skills": [
{
"id": "analyze-csv",
"name": "CSV Analysis",
"description": "Analyze CSV data files",
"inputModes": ["text", "file"],
"outputModes": ["text", "data"]
},
{
"id": "generate-report",
"name": "Report Generation",
"description": "Generate analysis reports",
"inputModes": ["data"],
"outputModes": ["text", "file"]
}
],
"authentication": {
"schemes": ["bearer"]
}
}
Task Lifecycle
submitted ──▶ working ──▶ completed
│
├──▶ input-required (needs more info)
│
├──▶ failed
│
└──▶ cancelled
Enabling A2A
Make Agent Discoverable
await client.agents.update('agent-123', {
a2a: {
enabled: true,
public: true, // Listed in registry
skills: [
{
id: 'data-analysis',
name: 'Data Analysis',
description: 'Analyze datasets and extract insights',
inputModes: ['text', 'file'],
outputModes: ['text', 'data']
}
]
}
});
Configure Authentication
await client.agents.update('agent-123', {
a2a: {
enabled: true,
authentication: {
schemes: ['bearer', 'api-key'],
allowedClients: ['agent-456', 'agent-789'] // Whitelist
}
}
});
Sending Tasks
Basic Task Send
const task = await client.a2a.sendTask({
targetAgent: 'agent-456',
message: {
role: 'user',
parts: [
{ type: 'text', text: 'Analyze this sales data and identify trends' },
{ type: 'file', uri: 'https://storage.example.com/sales-q4.csv' }
]
}
});
console.log(task.id); // task-789
console.log(task.status); // 'working'
With Streaming Updates
const stream = await client.a2a.sendTaskSubscribe({
targetAgent: 'agent-456',
message: {
role: 'user',
parts: [{ type: 'text', text: 'Generate a comprehensive analysis' }]
}
});
for await (const update of stream) {
if (update.type === 'status') {
console.log('Status:', update.status);
} else if (update.type === 'artifact') {
console.log('Artifact:', update.artifact.name);
}
}
Query Task Status
const task = await client.a2a.getTask('task-789');
console.log({
status: task.status,
history: task.history, // State transitions
artifacts: task.artifacts
});
Cancel Task
await client.a2a.cancelTask('task-789');
Message Parts
A2A messages can contain multiple parts:
Text Part
{ type: 'text', text: 'Analyze this data' }
File Part
{
type: 'file',
uri: 'https://storage.example.com/data.csv',
mimeType: 'text/csv',
name: 'sales-data.csv'
}
Data Part
{
type: 'data',
data: {
customers: [...],
orders: [...],
metrics: {...}
}
}
Artifacts
Agents return results as artifacts:
{
"artifacts": [
{
"name": "analysis-report",
"parts": [
{
"type": "text",
"text": "# Sales Analysis Report\n\n## Key Findings..."
}
],
"metadata": {
"format": "markdown",
"generatedAt": "2024-01-15T10:00:00Z"
}
},
{
"name": "chart-data",
"parts": [
{
"type": "data",
"data": {
"labels": ["Q1", "Q2", "Q3", "Q4"],
"values": [100, 150, 200, 250]
}
}
]
}
]
}
Agent Delegation
Manager-Worker Pattern
Create a manager agent that delegates to specialists:
// Manager agent's system prompt
const managerPrompt = `
You are a project manager agent that coordinates specialist agents.
Available specialists:
- data-analyst: Analyzes data, creates reports
- writer: Creates content, documentation
- coder: Writes and reviews code
- researcher: Researches topics, gathers information
When you receive a request:
1. Break it into subtasks
2. Delegate each subtask to the appropriate specialist
3. Combine their outputs into a final deliverable
Use the delegate_task tool to send work to specialists.
`;
// Manager can delegate via tool
const managerAgent = await client.agents.create({
name: 'Project Manager',
systemPrompt: managerPrompt,
tools: [
{
name: 'delegate_task',
description: 'Delegate a task to a specialist agent',
inputSchema: {
type: 'object',
properties: {
specialist: { type: 'string', enum: ['data-analyst', 'writer', 'coder', 'researcher'] },
task: { type: 'string', description: 'Task description' },
context: { type: 'object', description: 'Additional context' }
},
required: ['specialist', 'task']
}
}
],
a2a: {
enabled: true,
delegationTargets: ['data-analyst-agent', 'writer-agent', 'coder-agent', 'researcher-agent']
}
});
Hierarchical Delegation
┌──────────────────┐
│ Executive Agent │
└────────┬─────────┘
│
┌─────────┼─────────┐
▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐
│Sales │ │Tech │ │Support│
│Manager│ │Manager│ │Manager│
└───┬───┘ └───┬───┘ └───┬───┘
│ │ │
┌┴┐ ┌┴┐ ┌┴┐
│ │ │ │ │ │
Specialist Agents
Agent Discovery
Agent Registry
Find agents by capability:
const agents = await client.a2a.searchAgents({
skills: ['data-analysis'],
category: 'analytics',
rating: { min: 4.0 },
limit: 10
});
for (const agent of agents.data) {
console.log({
name: agent.name,
skills: agent.skills,
rating: agent.rating,
url: agent.url
});
}
Register External Agent
Connect to agents outside Deeployd:
await client.a2a.registerExternalAgent({
url: 'https://external-agent.example.com',
name: 'External Data Agent',
authentication: {
type: 'bearer',
token: 'external-api-key'
}
});
Federation
Cross-Organization A2A
Agents from different organizations can collaborate:
Organization A Organization B
┌──────────────┐ ┌──────────────┐
│ Agent A1 │◀─────▶│ Agent B1 │
└──────────────┘ └──────────────┘
A2A Protocol
Trust Levels
| Level | Description | Verification |
|---|---|---|
unverified | Unknown agent | None |
verified | Identity confirmed | Domain ownership |
trusted | Trusted partner | Mutual agreement |
internal | Same organization | Same tenant |
Configure Trust
await client.a2a.setTrustPolicy({
defaultTrust: 'verified',
trustedDomains: ['partner.com', 'subsidiary.com'],
blockedDomains: ['competitor.com']
});
A2A in Workflows
Use A2A within workflows:
{
id: 'external-analysis',
type: 'a2a-task',
targetAgent: 'external-data-agent',
message: {
parts: [
{ type: 'text', text: 'Analyze this dataset' },
{ type: 'data', data: '$.input.data' }
]
},
timeout: 300000, // 5 minute timeout
outputMapping: {
analysis: '$.artifacts[0].parts[0].text'
}
}
JSON-RPC Methods
A2A uses JSON-RPC 2.0:
| Method | Description |
|---|---|
task/send | Send task to agent |
task/sendSubscribe | Send with streaming |
task/get | Get task status |
task/cancel | Cancel task |
task/statusUpdate | Push status update |
task/artifactUpdate | Push artifact update |
Example Request
{
"jsonrpc": "2.0",
"method": "task/send",
"params": {
"message": {
"role": "user",
"parts": [{ "type": "text", "text": "Analyze sales data" }]
},
"metadata": {
"priority": "high"
}
},
"id": "req-123"
}
Example Response
{
"jsonrpc": "2.0",
"result": {
"id": "task-456",
"status": "working",
"createdAt": "2024-01-15T10:00:00Z"
},
"id": "req-123"
}
Best Practices
1. Define Clear Skills
skills: [
{
id: 'invoice-processing',
name: 'Invoice Processing',
description: 'Extracts data from invoices and validates against orders',
inputModes: ['file'],
outputModes: ['data']
}
]
2. Handle Failures Gracefully
try {
const task = await client.a2a.sendTask({ ... });
// Wait for completion
} catch (error) {
if (error.code === 'AGENT_UNAVAILABLE') {
// Try alternative agent or fallback
}
}
3. Set Appropriate Timeouts
const task = await client.a2a.sendTask({
targetAgent: 'slow-agent',
message: { ... },
timeout: 600000 // 10 minutes for complex tasks
});
4. Use Streaming for Long Tasks
// Better UX for tasks that take time
const stream = await client.a2a.sendTaskSubscribe({ ... });
5. Validate Agent Capabilities
// Check agent supports needed skill
const card = await client.a2a.getAgentCard('agent-456');
const hasSkill = card.skills.some(s => s.id === 'data-analysis');
Next: Learn about MCP Integration for connecting agents to external tools and resources.