JSON-RPC format
The wire protocol is A2A (Agent-to-Agent) JSON-RPC 2.0, protocol version 0.3.0.
Request
{
"jsonrpc": "2.0",
"method": "message/send",
"id": "unique-request-id",
"params": {
"message": {
"role": "user",
"parts": [
{ "kind": "text", "text": "Your question here" }
]
}
}
}
| Method | Behavior |
|---|---|
message/send |
Runs to completion and returns one response |
message/stream |
Returns Server-Sent Events as the run progresses, ending with a terminal frame |
Parameters
| Parameter | Type | Purpose |
|---|---|---|
params.message.parts |
array | The message content. At least one part required |
params.message.role |
string | user. Defaults to user when omitted |
params.contextId |
string | Conversation context, for multi-turn sessions |
params.message.contextId |
string | Same purpose, accepted on the message |
params.catalog_context |
object | Merchant catalog context supplied by a trusted caller |
Part kinds
{ "kind": "text", "text": "Where are the gaps in outdoor furniture?" }
{
"kind": "file",
"file": {
"bytes": "<base64>",
"mimeType": "text/csv",
"name": "catalog.csv"
}
}
A file part must carry inline bytes and be CSV, by mimeType or by a .csv filename. A file part that is a URI reference, or any other type, is reported back as unreadable rather than silently dropped.
Response
{
"jsonrpc": "2.0",
"result": {
"id": "task-id",
"contextId": "context-id",
"status": { "state": "completed" },
"artifacts": [
{
"parts": [
{ "kind": "text", "text": "The analysis, followed by its evidence footer." }
]
}
]
},
"id": "unique-request-id"
}
The answer text is at result.artifacts[0].parts[0].text. When your client declares the A2UI extension, additional parts on the artifact carry the structured interface, and a multi-skill run attaches one artifact per skill.
Task lifecycle
| State | Meaning |
|---|---|
submitted |
Received and queued |
working |
Running. Querying data and reasoning |
completed |
Finished successfully |
failed |
An error occurred |
cancelled |
The run was cancelled |
Streaming
message/stream returns Server-Sent Events. Status frames arrive as the run progresses, artifacts arrive as they are produced, and the run ends with a terminal frame.
Note for interface rendering: some clients, Gemini Enterprise among them, paint text on arrival but do not draw structured interface parts until the turn terminates. A payload sent early is necessary but not sufficient for it to appear early.
Errors
{
"jsonrpc": "2.0",
"error": {
"code": -32603,
"message": "The analysis service encountered an error. Please try again."
},
"id": "unique-request-id"
}
| Code | Meaning |
|---|---|
| -32700 | Parse error. Invalid JSON |
| -32600 | Invalid request. Missing required fields |
| -32601 | Method not found |
| -32602 | Invalid params. Missing message or parts |
| -32603 | Internal error |
Messages are sanitized. Internal detail is logged, never returned.
Evidence
Every successful answer carries an evidence footer naming each source, the rows read, and the snapshot date, plus a freshness line. The format is shown in Read an answer. Dates are read from the data at query time; none is ever inferred.