Back to Blog

What is A2A (Agent-to-Agent)?

secretiveshell
a2a

What is the A2A protocol?

According to google, A2A is "An open protocol enabling communication and interoperability between opaque agentic applications.". This means that multiple agents distributed across different platforms, devices and organizations can communicate with each other, sharing information and performing tasks in a decentralized manner. It helps to bridge the gap between service providers and consumers by allowing agent handoff between different systems.

Overview

Actors

User

You are the user. You interact with a host agent via a chat system or some other human friendly interface.

Host Agent

The host agent is responsible for orchestrating the entire interaction between the agents. It receives requests from the user, delegates requests to remote agents (via agent handoff) and manages the communication between agents. In terms of the protocol, the host agent is implemented as an A2A client that connects to remote agents (A2A servers) via a transport layer.

Remote Agent

Remote agents are agents provided by external parties, and are accessed via the host agent. They are implemented as A2A servers that listen for requests from the host. These are typically designed to perform a specific task and are specialized for a particular domain or use case. For example google might implement a remote agent to perform research tasks.

Transports

Unlike MCP, A2A is exclusively standardized on HTTP SSE, with support for external extensions. This means that A2A servers can be implemented using any HTTP server framework, such as Express, Fastify, or NestJS.

Authentication

A2A has launch parity with openapi, meaning that any type of authentication supported by openapi can be used with A2A. This includes:

  • HTTP Basic authentication
  • HTTP Bearer authentication
  • API keys in headers, query strings or cookies
  • OAuth 2.0 authorization
  • OpenID Connect

This means that A2A servers can be plugged into any existing API gateway and utilize existing authentication and authorization mechanisms.

Agent Card

Agent cards document the capabilities of an agent. They allow for automated discovery and registration of agents.

export interface AgentCard {
  name: string;
  description?: string | null;
  url: string;
  provider?: AgentProvider | null;
  version: string;
  documentationUrl?: string | null;
  capabilities: AgentCapabilities;
  authentication?: AgentAuthentication | null;
  defaultInputModes?: string[];
  defaultOutputModes?: string[];
  skills: AgentSkill[];
}

The AgentCard object contains information about the agent, such as its name, description, URL, version, and capabilities. A single agent card can be exposed at the .well-known/agent.json endpoint to enable domain driven autodiscovery.

Core Objects

Task

A Task represents a unit of work that an agent processes. This might be a request like "Book a flight to New York", or a task like "Summarize the top reddit posts for the day".

export interface Task {
  id: string;
  sessionId?: string | null;
  status: TaskStatus;
  artifacts?: Artifact[] | null;
  history?: Message[] | null;
  metadata?: Metadata;
}

Each task has a unique ID, which can be used to identify and manage the task, and the session ID determines a single login session. The status is an object that contains information about the task.

export interface TaskStatus {
  state: TaskState;
  message?: Message | null;
  timestamp?: string; // ISO 8601 date-time string
}

The TaskState is an enum that represents the current state of the task. The message is an optional field that can be used to provide additional context or information about the task.

export type TaskState =
  | "submitted"
  | "working"
  | "input-required"
  | "completed"
  | "canceled"
  | "failed"
  | "unknown";

Artifacts

Artifacts are the output of a task. They can be files, text, or other types of data.

export interface Artifact {
  name?: string | null;
  description?: string | null;
  parts: Part[];
  index?: number;
  append?: boolean | null;
  lastChunk?: boolean | null;
  metadata?: Metadata;
}

Each artifact has a name, description, and parts. The name and description provide context for the artifact, allowing it to be used with search and retrieval (RAG) systems. The parts are the actual data, which can be text, files, or other types of data.

Parts

export type Part = TextPart | FilePart | DataPart;

export interface TextPart {
  type: "text";
  text: string;
  metadata?: Metadata;
}

The TextPart represents a piece of text. It has a type of 'text' and a text property containing the actual text.

export interface FilePart {
  type: "file";
  file: FileContent;
  metadata?: Metadata;
}

The FilePart represents a file. It has a type of 'file' and a file property containing the file content.

export interface FileContent {
  name?: string | null;
  mimeType?: string | null;
  bytes?: string | null;
  uri?: string | null;
}

The FileContent represents the content of a file. It has a name for the file name, mimeType for the MIME type, and bytes or uri for the file content.

export interface DataPart {
  type: "data";
  data: Record<string, any>;
  metadata?: Metadata;
}

The DataPart represents an unstructured piece of data. It has a type of 'data' and a data property containing a json object.

Messages

export interface Message {
  role: "user" | "agent";
  parts: Part[];
  metadata?: Metadata;
}

The Message represents a message exchanged between the agent and the user. It has a role of either 'user' or 'agent', and a parts array containing the actual message content. The user role is shared between the host agent and the end user, since both actors interact with the remote agent via the same interface. We have already covered the Part type in the previous section.

Push Notifications

Push notifications are a way for the agent to notify the user about the status of a task. They reuse the same response types as the requests but with a different method name.

Supported Frameworks

The A2A spec repo contains a number of examples for different frameworks and languages. These include:

Framework Language Example
Genkit JavaScript Movie Agent
Genkit JavaScript Coder Agent
Google ADK Python expense report agent
LangGraph Python Currency Converter Agent
CrewAI Python Image Generation Agent
LlamaIndex Python file parsing agent

Conclusion

A2A (Agent-to-Agent) represents a critical evolution in how autonomous agents interoperate across organizational and technical boundaries. By standardizing communication A2A enables robust, secure, and scalable interactions between distributed systems. Its core abstractions create a clear and extensible protocol for web scale agent orchestration and delegation.