Skip to main content
OpenFang implements the Agent-to-Agent (A2A) Protocol for cross-system agent communication. This allows OpenFang agents to discover and communicate with external agents on remote systems.

Agent Card Discovery

The A2A protocol uses .well-known discovery to expose agent capabilities.

GET /.well-known/agent.json

Retrieve this OpenFang instance’s A2A agent card.
curl http://127.0.0.1:4200/.well-known/agent.json
name
string
Agent system name
description
string
System description
url
string
Base URL for this agent system
version
string
OpenFang version
capabilities
object
System capabilities
skills
array
Available agent skills/capabilities
{
  "name": "OpenFang",
  "description": "OpenFang Agent Operating System",
  "url": "http://127.0.0.1:4200",
  "version": "0.1.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false
  },
  "skills": [
    {
      "id": "chat",
      "name": "Chat",
      "description": "General-purpose chat with any agent"
    },
    {
      "id": "code-review",
      "name": "Code Review",
      "description": "Review code and suggest improvements"
    }
  ]
}

List A2A Agents

List agents available via the A2A protocol on this OpenFang instance.
curl http://127.0.0.1:4200/a2a/agents
agents
array
{
  "agents": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "coder",
      "description": "Expert coding assistant",
      "skills": ["code-review", "debugging", "refactoring"]
    }
  ]
}

Send Task

Send a task to an agent via the A2A protocol.
curl -X POST http://127.0.0.1:4200/a2a/tasks/send \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "message": {
      "role": "user",
      "parts": [
        {"text": "Review this code for security issues"}
      ]
    }
  }'
agent_id
string
required
Target agent UUID
message
object
required
A2A message object
task_id
string
Task UUID
status
string
Task status: pending, running, completed, failed, cancelled
result
object
Task result (if completed)
{
  "task_id": "task-1234-5678-90ab-cdef12345678",
  "status": "completed",
  "result": {
    "role": "agent",
    "parts": [
      {"text": "I found 2 potential security issues..."}
    ]
  }
}

Get Task Status

Check the status and result of an A2A task.
curl http://127.0.0.1:4200/a2a/tasks/{id}
id
string
required
Task UUID
task_id
string
Task UUID
status
string
Task status
created_at
string
Task creation timestamp
completed_at
string
Task completion timestamp (null if not completed)
result
object
Task result (if completed)
{
  "task_id": "task-1234-5678-90ab-cdef12345678",
  "status": "completed",
  "created_at": "2025-01-15T10:30:00Z",
  "completed_at": "2025-01-15T10:30:05Z",
  "result": {
    "role": "agent",
    "parts": [
      {"text": "Analysis complete..."}
    ]
  }
}

Cancel Task

Cancel a running A2A task.
curl -X POST http://127.0.0.1:4200/a2a/tasks/{id}/cancel
id
string
required
Task UUID
{
  "task_id": "task-1234-5678-90ab-cdef12345678",
  "status": "cancelled"
}

Discover External Agents

Discover A2A agents on remote systems.
curl -X POST http://127.0.0.1:4200/api/a2a/discover \
  -H "Content-Type: application/json" \
  -d '{"url": "https://agent-system.example.com"}'
url
string
required
Base URL of the external agent system
status
string
Discovery status: success or failed
agent_card
object
Discovered agent card (same structure as /.well-known/agent.json)
{
  "status": "success",
  "agent_card": {
    "name": "RemoteAgentSystem",
    "description": "Remote agent system",
    "url": "https://agent-system.example.com",
    "version": "1.0.0",
    "capabilities": {
      "streaming": true,
      "pushNotifications": false
    },
    "skills": [
      {"id": "research", "name": "Research", "description": "Research tasks"}
    ]
  }
}

List External Agents

List all discovered external A2A agents.
curl http://127.0.0.1:4200/api/a2a/agents
agents
array

Send Task to External Agent

Send a task to an external A2A agent.
curl -X POST http://127.0.0.1:4200/api/a2a/send \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://agent-system.example.com",
    "agent_id": "external-agent-id",
    "message": "Research quantum computing advancements"
  }'
url
string
required
External agent system base URL
agent_id
string
required
External agent ID
message
string
required
Message text
task_id
string
External task ID
status
string
Task status
{
  "task_id": "ext-task-1234",
  "status": "pending"
}

Check External Task Status

Check the status of a task sent to an external agent.
curl http://127.0.0.1:4200/api/a2a/tasks/{id}/status
id
string
required
External task ID
task_id
string
Task ID
status
string
Task status
result
string
Task result (if completed)

AgentCard Format

The A2A protocol uses a standardized AgentCard format for agent discovery:
{
  "name": "Agent System Name",
  "description": "System description",
  "url": "https://agent-system.example.com",
  "version": "1.0.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false,
    "webSockets": true,
    "longPolling": false
  },
  "skills": [
    {
      "id": "skill-id",
      "name": "Human-readable skill name",
      "description": "What this skill does",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {"type": "string"}
        }
      }
    }
  ],
  "auth": {
    "methods": ["bearer", "apiKey"],
    "bearer": {
      "headerName": "Authorization",
      "prefix": "Bearer"
    }
  }
}

Best Practices

Store discovered agent cards locally to avoid repeated discovery:
# Discover once
curl -X POST http://127.0.0.1:4200/api/a2a/discover \
  -d '{"url": "https://agent-system.example.com"}'

# Re-use cached card for subsequent tasks
curl -X POST http://127.0.0.1:4200/api/a2a/send \
  -d '{"url": "https://agent-system.example.com", ...}'
For long-running tasks, poll for completion:
# Send task
TASK_ID=$(curl -X POST http://127.0.0.1:4200/api/a2a/send \
  -d '{...}' | jq -r '.task_id')

# Poll for completion
while [ "$(curl http://127.0.0.1:4200/api/a2a/tasks/$TASK_ID/status | jq -r '.status')" != "completed" ]; do
  sleep 5
done
Always check task status and handle failures:
const response = await fetch('http://127.0.0.1:4200/a2a/tasks/send', {
  method: 'POST',
  body: JSON.stringify({agent_id, message})
})
const {task_id, status} = await response.json()

if (status === 'failed') {
  console.error('Task failed:', result.error)
} else if (status === 'completed') {
  console.log('Result:', result)
}
Update /.well-known/agent.json to advertise your agents’ capabilities:
{
  "skills": [
    {
      "id": "code-review",
      "name": "Code Review",
      "description": "Review code for bugs and security issues"
    },
    {
      "id": "research",
      "name": "Research",
      "description": "Research topics and summarize findings"
    }
  ]
}

Next Steps

Agents API

Manage local agents

Workflows API

Orchestrate multi-agent tasks

A2A Specification

Learn about A2A protocol

Security

Secure A2A communication

Build docs developers (and LLMs) love