Part
Every piece of content in A2A is a Part that holds exactly one of text, raw, url, or data, and its mediaType says how to read it.
Your planner asks code-reviewer to review a diff. The request carries an instruction and the diff as a file, and the answer carries findings that the planner's own code will parse. A2A carries all three in one container shape, the part, and labels each one with a media type.
When you finish this section, you can build all four kinds of part and predict whether an agent will accept them.
One container, four contents
Part: the smallest unit of content in a message or an artifact. In the proto, Part declares its content as a oneof with four members:
textholds a string.rawholds the bytes of a file. In JSON, the bytes are a base64 string.urlholds a URL that points to the content of the file.dataholds any structured value as JSON: an object, an array, a string, a number, a boolean, or null.
Beside the content sit three optional fields, mediaType, filename, and metadata, and mediaType works for every kind of part. The kit's review request sends two kinds in one message:
"parts": [
{
"text": "Review this diff of payments-api."
},
{
"raw": "LS0tIGEvcGF5bWVudHMvcmVmdW5kcy5weQor…",
"filename": "refunds.diff",
"mediaType": "text/x-diff"
}
]Base64 costs size: the 175-byte diff of payments/refunds.py becomes 236 characters in the JSON body. A url part keeps the message small and leaves the download, with its risk, to the receiver.
No kind, no nesting
In version 0.3, a part named its type in a kind field and wrapped a file in a nested file object. Version 1.0 removed both. The kind field is no longer part of the protocol, and a sender should not write it.
A file part is flat: raw or url sits next to filename and mediaType. The specification's own file-part sample has that shape but is not valid JSON (conflict D24). Copy part shapes from the proto, never from the samples.
Read a part by testing which content member is present, and never send two of them. The reference SDK refuses a part with two members as invalid parameters, -32602, before any agent code runs. It ignores a stray kind, as the specification asks: an implementation should ignore fields that it does not recognize.
image/png part fails, because code-reviewer does not accept that media type. The top row is the shape of every part. Each row below is one captured part, in the order the captures sent them. Its content member is on the left, its media type in green, and its sender underneath. The review.json artifact holds a text part for a person and a data part for code.Who declares media types
Media types are declared in four places, and a skill's modes override the card's defaults:
| Field | Lives in | Set by | code-reviewer in the kit |
|---|---|---|---|
defaultInputModes | the agent card | the agent | text/plain, text/x-diff |
defaultOutputModes | the agent card | the agent | text/plain, application/json |
inputModes, outputModes | each skill on the card | the agent | review-diff takes text/x-diff and text/plain |
acceptedOutputModes | configuration of a send | the client | not sent anywhere in the kit |
mediaType | each part | whoever sends the part | text/x-diff on refunds.diff |
The client's one field is acceptedOutputModes, and the rule on the agent is a SHOULD. The agent should use the field to shape its output. The SDK's request handler never reads the field, so check the mediaType of every part you receive.
When the media type does not fit
ContentTypeNotSupportedError: the agent or the called skill does not support a media type that the message parts give or that an artifact implies. Its JSON-RPC code is -32005, and errors gives its other forms.
In the kit, the planner sends code-reviewer a screenshot as a url part labelled image/png, and the agent refuses before it creates a task:
"parts": [
{
"url": "https://example.com/screenshot.png",
"mediaType": "image/png"
}
]
…
"error": {
"code": -32005,
"message": "Content type not supported",
"data": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "CONTENT_TYPE_NOT_SUPPORTED",
"domain": "a2a-protocol.org",
"metadata": {
"mediaType": "image/png"
}Servers check differently, because the specification gives an unlabelled part no default type. The SDK checks only when the server turns the check on, and then it skips every part with no mediaType. The kit gives such a part a default type and checks it against the card's defaultInputModes, as the kit README lists. The same unlabelled part can pass one server and fail the other.
The security rules ask agents to reject media types that they do not expect. A url part must be checked against server-side request forgery, as security requirements explains.
A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10