Skip to main content

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
  1. Agent A sends a task to Agent B
  2. Agent B processes the task
  3. Agent B returns results (or status updates)
  4. 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

LevelDescriptionVerification
unverifiedUnknown agentNone
verifiedIdentity confirmedDomain ownership
trustedTrusted partnerMutual agreement
internalSame organizationSame 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:

MethodDescription
task/sendSend task to agent
task/sendSubscribeSend with streaming
task/getGet task status
task/cancelCancel task
task/statusUpdatePush status update
task/artifactUpdatePush 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.