A2A Protocol Adapter
Connect to any agent implementing Google's Agent-to-Agent (A2A) protocol : a standard for agent interoperability using JSON-RPC 2.0 over HTTP.
Configuration
1const llmConfig: LocalLLMConfig = {
2 provider: "a2a",
3 baseUrl: "https://your-a2a-agent.example.com/a2a",
4 model: "mental-coach-agent", // agent identifier: sent as metadata
5 apiKey: "bearer-token", // optional
6 timeoutMs: 60_000,
7};Key differences from other adapters
Stateful: server manages history
Unlike Ollama/OpenAI which receive the full message history on every turn, A2A agents track conversation state server-side via a contextId. The adapter only sends the latest user message each turn.
No system prompt suffix needed
A2A agents are pre-configured on the server. Skip systemPromptSuffix when using this provider.
Structured output via DataPart
A2A agents return wireai-rn JSON in a DataPart (data field). The adapter extracts DataPart first, then falls back to TextPart.
Async task polling
If the agent returns SUBMITTED or WORKING state, the adapter polls tasks/get every 1 second, up to 30 polls.
WireAIProvider setup for A2A
1// Skip system prompt suffix for A2A: agent is pre-configured server-side
2const systemPromptSuffix = config.provider === "a2a" ? undefined : MY_APP_PROMPT;
3
4<WireAIProvider
5 key={`${config.provider}:${config.baseUrl}:${config.model}`}
6 llm={config}
7 components={components}
8 systemPromptSuffix={systemPromptSuffix}
9>
10 {children}
11</WireAIProvider>Wire format
The adapter sends message/send JSON-RPC 2.0:
1POST https://your-agent.com/a2a
2Content-Type: application/json
3
4{
5 "jsonrpc": "2.0",
6 "id": 1,
7 "method": "message/send",
8 "params": {
9 "message": {
10 "role": "user",
11 "parts": [{ "text": "Start my check-in" }]
12 },
13 "contextId": "ctx-abc123",
14 "metadata": { "model": "mental-coach-agent" }
15 }
16}1{
2 "jsonrpc": "2.0",
3 "id": 1,
4 "result": {
5 "id": "task-xyz",
6 "contextId": "ctx-abc123",
7 "status": { "state": "COMPLETED" },
8 "messages": [
9 {
10 "role": "agent",
11 "parts": [
12 {
13 "data": {
14 "action": "render",
15 "component": "SelectionCard",
16 "props": { "title": "How are you feeling?", "options": ["Great", "OK", "Stressed"] }
17 }
18 }
19 ]
20 }
21 ]
22 }
23}Task lifecycle
| State | Behavior |
|---|---|
| SUBMITTED / WORKING | Adapter polls tasks/get every 1s (max 30 polls) |
| COMPLETED | Content extracted from DataPart โ TextPart โ artifacts |
| INPUT_REQUIRED | Content extracted and rendered (interactive component) |
| FAILED / CANCELED / REJECTED | Throws an error with the status message |
Advertise your components to A2A agents
Use buildAgentCard() to tell your A2A agent server which components your mobile client can render:
1import { buildAgentCard, createComponentRegistry } from "wireai-rn";
2import { defaultComponents } from "wireai-rn/components";
3
4const registry = createComponentRegistry(defaultComponents);
5
6const card = buildAgentCard(registry, {
7 name: "My App Client",
8 url: "https://bff.myapp.com/a2a/client",
9 version: "1.0.0",
10});
11
12// Send this card to your agent server so it knows which components to use
13// POST https://your-agent.com/register-client
14await fetch("https://your-agent.com/register-client", {
15 method: "POST",
16 headers: { "Content-Type": "application/json" },
17 body: JSON.stringify(card),
18});For a deep dive into the A2A protocol and the full buildAgentCard format, see the A2A Deep Dive page.