# A2A Protocol
URL: /docs/runtimes/a2a
Connect to A2A (Agent-to-Agent) v1.0 protocol servers.
`@assistant-ui/react-a2a` provides a runtime adapter for the [A2A (Agent-to-Agent) v1.0 protocol](https://github.com/a2aproject/A2A), enabling your assistant-ui frontend to communicate with any A2A-compliant agent server.
Requirements \[#requirements]
* An A2A v1.0 compatible agent server
* React 18 or 19
Installation \[#installation]
Getting Started \[#getting-started]
Set up the Runtime Provider \[#set-up-the-runtime-provider]
Create a runtime provider component that connects to your A2A server.
```tsx title="app/MyRuntimeProvider.tsx"
"use client";
import { AssistantRuntimeProvider } from "@assistant-ui/react";
import { useA2ARuntime } from "@assistant-ui/react-a2a";
export function MyRuntimeProvider({
children,
}: {
children: React.ReactNode;
}) {
const runtime = useA2ARuntime({
baseUrl: "http://localhost:9999",
});
return (
{children}
);
}
```
Add the Thread component \[#add-the-thread-component]
```tsx title="app/page.tsx"
import { Thread } from "@assistant-ui/react";
import { MyRuntimeProvider } from "./MyRuntimeProvider";
export default function Page() {
return (
);
}
```
Setup UI Components \[#setup-ui-components]
Follow the [UI Setup](/docs/ui) guide to setup the UI components.
A2AClient \[#a2aclient]
The built-in `A2AClient` handles all communication with the A2A server, including JSON serialization, SSE streaming, ProtoJSON enum normalization, and structured error handling.
```ts
import { A2AClient } from "@assistant-ui/react-a2a";
const client = new A2AClient({
baseUrl: "https://my-agent.example.com",
headers: { Authorization: "Bearer " },
tenant: "my-org", // optional, for multi-tenant servers
extensions: ["urn:a2a:ext:my-extension"], // optional
});
```
You can pass a pre-built client to `useA2ARuntime`:
```tsx
const runtime = useA2ARuntime({ client });
```
Client Options \[#client-options]
| Option | Type | Description |
| ------------ | ---------------------------------------------------------- | ----------------------------------------------------------- |
| `baseUrl` | `string` | Base URL of the A2A server |
| `headers` | `Record` or `() => Record` | Static or dynamic headers (e.g. for auth tokens) |
| `tenant` | `string` | Tenant ID for multi-tenant servers (prepended to URL paths) |
| `extensions` | `string[]` | Extension URIs to negotiate via `A2A-Extensions` header |
Client Methods \[#client-methods]
| Method | Description |
| ---------------------------------------------------- | -------------------------------------------------------- |
| `sendMessage(message, configuration?, metadata?)` | Send a message (non-streaming) |
| `streamMessage(message, configuration?, metadata?)` | Send a message with SSE streaming |
| `getTask(taskId, historyLength?)` | Get a task by ID |
| `listTasks(request?)` | List tasks with filtering and pagination |
| `cancelTask(taskId, metadata?)` | Cancel an in-progress task |
| `subscribeToTask(taskId)` | Subscribe to SSE updates for a task |
| `getAgentCard()` | Fetch the agent card from `/.well-known/agent-card.json` |
| `getExtendedAgentCard()` | Fetch the extended (authenticated) agent card |
| `createTaskPushNotificationConfig(config)` | Create a push notification config |
| `getTaskPushNotificationConfig(taskId, configId)` | Get a push notification config |
| `listTaskPushNotificationConfigs(taskId)` | List push notification configs |
| `deleteTaskPushNotificationConfig(taskId, configId)` | Delete a push notification config |
useA2ARuntime Options \[#usea2aruntime-options]
| Option | Type | Description |
| ---------------------- | ----------------------------- | --------------------------------------------------------- |
| `client` | `A2AClient` | Pre-built A2A client instance (provide this OR `baseUrl`) |
| `baseUrl` | `string` | A2A server URL (creates a client automatically) |
| `headers` | see above | Headers for the auto-created client |
| `contextId` | `string` | Initial context ID for the conversation |
| `configuration` | `A2ASendMessageConfiguration` | Default send message configuration |
| `onError` | `(error: Error) => void` | Error callback |
| `onCancel` | `() => void` | Cancellation callback |
| `adapters.attachments` | `AttachmentAdapter` | Custom attachment handling |
| `adapters.speech` | `SpeechSynthesisAdapter` | Text-to-speech |
| `adapters.feedback` | `FeedbackAdapter` | Feedback collection |
| `adapters.history` | `ThreadHistoryAdapter` | Message persistence |
| `adapters.threadList` | `UseA2AThreadListAdapter` | Thread switching |
Hooks \[#hooks]
useA2ATask \[#usea2atask]
Returns the current A2A task object, including task state and status message.
```tsx
import { useA2ATask } from "@assistant-ui/react-a2a";
function TaskStatus() {
const task = useA2ATask();
if (!task) return null;
return
Task {task.id}: {task.status.state}
;
}
```
useA2AArtifacts \[#usea2aartifacts]
Returns the artifacts generated by the current task.
```tsx
import { useA2AArtifacts } from "@assistant-ui/react-a2a";
function ArtifactList() {
const artifacts = useA2AArtifacts();
return (
{artifacts.map((artifact) => (
{artifact.name}: {artifact.parts.length} parts
))}
);
}
```
useA2AAgentCard \[#usea2aagentcard]
Returns the agent card fetched from the server on initialization.
```tsx
import { useA2AAgentCard } from "@assistant-ui/react-a2a";
function AgentInfo() {
const card = useA2AAgentCard();
if (!card) return null;
return (