What an A2A protocol LLM payload actually contains, how a React Native client parses it, and how Wire RN turns each agent message into a validated native component.
An A2A (Agent-to-Agent) payload is a structured JSON message a remote agent sends to a client. It carries a role, a list of typed parts (text, data, or file), and task metadata that tracks state across turns. On React Native, the client reads the data parts, validates them against a component registry, and renders native UI, no agent logic ships inside the app. Wire RN's A2A adapter does exactly this: it speaks the protocol, extracts the UI spec from each message, validates it with Zod, and mounts one native component per turn.
Most explanations of A2A stop at the handshake: agent A calls agent B, they exchange capabilities, done. That misses the part a mobile engineer actually cares about, which is what comes back in the message body and how you turn it into a screen. This post walks the payload itself, field by field, and shows how a React Native client consumes it.
What is the A2A protocol?
A2A is Google's open Agent-to-Agent protocol. It defines how two agents, or an agent and a client, exchange messages over a transport (typically HTTP with JSON-RPC, with streaming over Server-Sent Events). The protocol is deliberately UI-agnostic at the wire level: it standardizes the envelope (roles, message parts, task lifecycle) and leaves the meaning of the payload to the participants. That separation is the whole reason it works for mobile. The agent backend, a LangChain graph, a multi-step supervisor, a tool-using agent, lives on a server. The phone is a thin client that consumes messages and renders them. For the conceptual background on agent-driven interfaces, see what generative UI is.
A2A sits next to A2UI, not on top of it. A2A is the transport and task layer (how messages move and how a task progresses). A2UI is the UI description layer (how a component is described as data). Wire RN consumes both. The detail on the UI side is in Google's A2UI protocol on React Native.
What does an A2A payload actually contain?
An A2A message has three things that matter to a client: a role, an array of parts, and the surrounding task context. The role is agent or user. The parts array is where the content lives, and each part is typed. A TextPart carries prose. A DataPart carries structured JSON, which is where a UI spec rides. A FilePart carries a file reference or inline bytes.
// A single A2A message from the agent, carrying a UI spec in a DataPart
{
"role": "agent",
"parts": [
{
"kind": "data",
"data": {
"component": "ChipSelectCard",
"props": {
"title": "What are you optimizing for?",
"options": ["Focus", "Sleep", "Stress", "Energy"]
}
}
}
],
"messageId": "msg_8f21",
"taskId": "task_4c0a",
"contextId": "ctx_de91"
}The component name and props are not part of the A2A spec, they are the convention Wire RN expects inside a DataPart. A2A guarantees the envelope arrives intact and in order; the registry contract guarantees the data object names a real component. The taskId and contextId are what let the agent remember the conversation across turns without the client holding agent state.
How does the task lifecycle work?
A2A models a unit of work as a task with a status that moves through states: submitted, working, input-required, completed, and failure states. For a mobile flow this maps cleanly onto turns. The client sends the user's answer, the task goes to working, the agent reasons, and the next message arrives either with input-required (render a component and wait for a tap) or completed (render the final card and stop).
// A status-update event over the streaming channel
{
"kind": "status-update",
"taskId": "task_4c0a",
"status": {
"state": "input-required",
"message": {
"role": "agent",
"parts": [{ "kind": "data", "data": { "component": "...", "props": {} } }]
}
},
"final": false
}The final flag tells the client whether more is coming on this task. The streaming transport is Server-Sent Events, which is exactly where mobile gets interesting: Hermes does not implement the browser's ReadableStream, so you cannot consume an SSE stream the way a web client would. Wire RN reads the stream over XHR with a manual SSE parser. The full story of that workaround is in the Hermes ReadableStream problem.
How does Wire RN render an A2A payload?
The A2A adapter does four things on every agent message. It reads the parts array and pulls out the DataPart. It looks the component name up in the registry. It validates the props against that component's Zod schema. It mounts the matching native component, one per turn. If validation fails, the component is skipped and a fallback runs instead of crashing, with a dev-mode warning naming the bad prop.
import { WireAIProvider, A2AAdapter } from 'wireai-rn';
import { builtInComponents } from 'wireai-rn/components';
export default function App() {
return (
<WireAIProvider
adapter={new A2AAdapter({
// your A2A-compatible agent server (LangChain graph, supervisor, etc.)
agentUrl: 'https://agent.example.com/a2a',
})}
components={builtInComponents}
>
<AgentFlowScreen />
</WireAIProvider>
);
}The adapter normalizes the A2A message into the same internal shape Wire RN uses for a direct LLM call. That is the key design choice: whether the JSON came from a single Anthropic completion or a remote LangChain agent over A2A, the render path is identical. The app does not know or care which backend produced the component. For the full agentic stack behind this, see driving a React Native UI with LangChain agents.
Why validate the payload on the client?
A remote agent is a probabilistic system upstream of your UI. Even a well-behaved agent will occasionally emit a DataPart with a missing prop, a wrong type, or a component name that does not exist in your registry. Trusting that payload blindly means a malformed agent message can blank or crash a production screen. Wire RN treats the A2A data object as untrusted input and runs it through Zod before render, so the worst case is a graceful fallback, not a broken flow. This is the same defensive posture covered in how generative UI actually works on React Native.
FAQ
What is an A2A protocol LLM payload?
It is the JSON message a remote agent returns over the A2A protocol. It contains a role, an array of typed parts (text, data, file), and task identifiers. When the agent is driving UI, the structured UI spec, a component name and its props, rides inside a DataPart. The client reads that part and renders the named component.
How is A2A different from a normal LLM API call?
A direct LLM call returns a completion the client parses itself, and the client holds the conversation state. A2A adds a task lifecycle and stable task and context identifiers, so the agent server remembers the conversation across turns and can run multi-step reasoning. The client stays thin: it sends answers and renders the parts that come back.
Does Wire RN need agent logic in the app to use A2A?
No. The agent runs on a server. Wire RN's A2A adapter consumes the messages and renders them. The app ships zero agent logic, which keeps the bundle small and lets you change the backend agent without shipping a new app build.
Drive your React Native UI from an agent. Run npm install wireai-rn zod and read the A2A adapter docs.