fix(spec): Refactor Part object to remove the need for FilePart and DataPart#1363
fix(spec): Refactor Part object to remove the need for FilePart and DataPart#1363darrelmiller wants to merge 2 commits intomainfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a significant and beneficial refactoring of the Part message in the A2A protocol, simplifying the structure by flattening FilePart and DataPart. This makes the message more flexible and easier to use. The changes are well-designed, for instance by moving media_type to the top level to apply to all content types. My review includes a couple of minor suggestions to improve the clarity of comments for the new fields. The broader changes to clarify the versioning strategy in the specification document are also a welcome and necessary addition, especially given the breaking change in the Part message.
| // from the file_with_uri source. | ||
| message FilePart { | ||
| oneof file { | ||
| // The base64-encoded content of a file. |
There was a problem hiding this comment.
The comment for the bytes field could be more precise. While bytes fields are base64-encoded in JSON representations, they are transmitted as raw bytes in Protobuf's binary format (like in gRPC). Clarifying this distinction will help developers working with different protocol bindings.
| // The base64-encoded content of a file. | |
| // The byte content of a file. In JSON representations, this is base64-encoded. |
| string media_type = 3; | ||
| // Optional metadata associated with this part. | ||
| google.protobuf.Struct metadata = 5; | ||
| // An optional name for the file (e.g., "document.pdf"). |
There was a problem hiding this comment.
The filename field is useful not just for file-based parts (bytes, url) but could also be relevant for data parts (e.g., to name a JSON structure like config.json). The current comment limits its scope to files. A more general comment would better reflect its potential use cases.
| // An optional name for the file (e.g., "document.pdf"). | |
| // An optional name for the content, often used as a filename (e.g., "document.pdf"). |
| ```proto { .no-copy } | ||
| --8<-- "specification/grpc/a2a.proto:{{ region_tag }}" | ||
| ``` | ||
|
|
There was a problem hiding this comment.
| The operation MUST return only tasks visible to the authenticated client and MUST use cursor-based pagination for performance and consistency. Tasks MUST be sorted by last update time in descending order. Implementations MUST implement appropriate authorization scoping to ensure clients can only access authorized tasks. See [Section 13.1 Data Access and Authorization Scoping](#131-data-access-and-authorization-scoping) for detailed security requirements. | ||
|
|
||
| ***Pagination Strategy:*** | ||
| **_Pagination Strategy:_** |
There was a problem hiding this comment.
| **_Pagination Strategy:_** | |
| ***Pagination Strategy:*** |
| This method uses cursor-based pagination (via `pageToken`/`nextPageToken`) rather than offset-based pagination for better performance and consistency, especially with large datasets. Cursor-based pagination avoids the "deep pagination problem" where skipping large numbers of records becomes inefficient for databases. This approach is consistent with the gRPC specification, which also uses cursor-based pagination (page_token/next_page_token). | ||
|
|
||
| ***Ordering:*** | ||
| **_Ordering:_** |
There was a problem hiding this comment.
| **_Ordering:_** | |
| ***Ordering:*** |
| The operation MUST establish a webhook endpoint for task update notifications. When task updates occur, the agent will send HTTP POST requests to the configured webhook URL with [`StreamResponse`](#323-stream-response) payloads (see [Push Notification Payload](#433-push-notification-payload) for details). This operation is only available if the agent supports push notifications capability. The configuration MUST persist until task completion or explicit deletion. | ||
|
|
||
| <span id="tasks-push-notification-config-operations"></span><span id="grpc-push-notification-operations"></span><span id="push-notification-operations"></span> | ||
| <span id="tasks-push-notification-config-operations"></span><span id="grpc-push-notification-operations"></span><span id="push-notification-operations"></span> |
There was a problem hiding this comment.
| <span id="tasks-push-notification-config-operations"></span><span id="grpc-push-notification-operations"></span><span id="push-notification-operations"></span> | |
| <span id="tasks-push-notification-config-operations"></span><span id="grpc-push-notification-operations"></span><span id="push-notification-operations"></span> |
| **Standard A2A Service Parameters:** | ||
|
|
||
| | Name | Description | Example Value | | ||
| | Name | Description | Example Value | |
There was a problem hiding this comment.
| | Name | Description | Example Value | | |
| | Name | Description | Example Value | |
| | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------- | | ||
| | `A2A-Extensions` | Comma-separated list of extension URIs that the client wants to use for the request | `https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1` | | ||
| | `A2A-Version` | The A2A protocol version that the client is using. If the version is not supported, the agent returns [`VersionNotSupportedError`](#332-error-handling) | `0.3` | | ||
| | `A2A-Extensions` | Comma-separated list of extension URIs that the client wants to use for the request | `https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1` | |
There was a problem hiding this comment.
| | `A2A-Extensions` | Comma-separated list of extension URIs that the client wants to use for the request | `https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1` | | |
| | `A2A-Extensions` | Comma-separated list of extension URIs that the client wants to use for the request | `https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1` | |
| | `A2A-Extensions` | Comma-separated list of extension URIs that the client wants to use for the request | `https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1` | | ||
| | `A2A-Version` | The A2A protocol version that the client is using. If the version is not supported, the agent returns [`VersionNotSupportedError`](#332-error-handling) | `0.3` | | ||
| | `A2A-Extensions` | Comma-separated list of extension URIs that the client wants to use for the request | `https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1` | | ||
| | `A2A-Version` | The A2A protocol version that the client is using. If the version is not supported, the agent returns [`VersionNotSupportedError`](#332-error-handling) | `0.3` | |
There was a problem hiding this comment.
| | `A2A-Version` | The A2A protocol version that the client is using. If the version is not supported, the agent returns [`VersionNotSupportedError`](#332-error-handling) | `0.3` | | |
| | `A2A-Version` | The A2A protocol version that the client is using. If the version is not supported, the agent returns [`VersionNotSupportedError`](#332-error-handling) | `0.3` | |
| **Error Categories and Server Requirements:** | ||
|
|
||
| - **Authentication Errors**: Invalid or missing credentials | ||
|
|
There was a problem hiding this comment.
| - Example scenarios: Missing bearer token, expired API key, invalid OAuth token | ||
|
|
||
| - **Authorization Errors**: Insufficient permissions for requested operation | ||
|
|
There was a problem hiding this comment.
| - Example scenarios: Attempting to access a task created by another user, insufficient OAuth scopes | ||
|
|
||
| - **Validation Errors**: Invalid input parameters or message format | ||
|
|
There was a problem hiding this comment.
| - Example scenarios: Invalid task ID format, missing required message parts, unsupported content type | ||
|
|
||
| - **Resource Errors**: Requested task not found or not accessible | ||
|
|
There was a problem hiding this comment.
| - **`signatures`** (optional, array of [`AgentCardSignature`](#447-agentcardsignature)): JSON Web Signatures computed for this AgentCard. | ||
| - **`iconUrl`** (optional, string): An optional URL to an icon for the agent. | ||
| <a id="AgentProvider"></a> | ||
| <a id="AgentProvider"></a> |
There was a problem hiding this comment.
| <a id="AgentProvider"></a> | |
| <a id="AgentProvider"></a> |
| Agents declare their supported extensions in the [`AgentCard`](#441-agentcard) using the `extensions` field, which contains an array of [`AgentExtension`](#444-agentextension) objects. | ||
|
|
||
| *Example: Agent declaring extension support in AgentCard:* | ||
| _Example: Agent declaring extension support in AgentCard:_ |
There was a problem hiding this comment.
| _Example: Agent declaring extension support in AgentCard:_ | |
| *Example: Agent declaring extension support in AgentCard:* |
| Clients indicate their desire to opt into the use of specific extensions through binding-specific mechanisms such as HTTP headers, gRPC metadata, or JSON-RPC request parameters that identify the extension identifiers they wish to utilize during the interaction. | ||
|
|
||
| *Example: HTTP client opting into extensions using headers:* | ||
| _Example: HTTP client opting into extensions using headers:_ |
There was a problem hiding this comment.
| _Example: HTTP client opting into extensions using headers:_ | |
| *Example: HTTP client opting into extensions using headers:* |
| Messages can be extended to allow clients to provide additional strongly typed context or parameters relevant to the message being sent, or TaskStatus Messages to include extra information about the task's progress. | ||
|
|
||
| *Example: A location extension using the extensions and metadata arrays:* | ||
| _Example: A location extension using the extensions and metadata arrays:_ |
There was a problem hiding this comment.
| _Example: A location extension using the extensions and metadata arrays:_ | |
| *Example: A location extension using the extensions and metadata arrays:* |
| Artifacts can include extension data to provide strongly typed context or metadata about the generated content. | ||
|
|
||
| *Example: An artifact with citation extension for research sources:* | ||
| _Example: An artifact with citation extension for research sources:_ |
There was a problem hiding this comment.
| _Example: An artifact with citation extension for research sources:_ | |
| *Example: An artifact with citation extension for research sources:* |
| **Canonicalization Rules:** | ||
|
|
||
| 1. **Field Presence and Default Value Handling**: Before canonicalization, the JSON representation **MUST** respect Protocol Buffer field presence semantics as defined in [Section 5.7](#57-field-presence-and-optionality). This ensures that the canonical form accurately reflects which fields were explicitly provided versus which were omitted, enabling signature verification when Agent Cards are reconstructed: | ||
|
|
There was a problem hiding this comment.
| - **Default values**: Fields with default values **MUST** be omitted unless the field is marked as `REQUIRED` or has the `optional` keyword. | ||
|
|
||
| 2. **RFC 8785 Compliance**: The Agent Card JSON **MUST** be canonicalized according to RFC 8785, which specifies: | ||
|
|
There was a problem hiding this comment.
| **Signature Generation Process:** | ||
|
|
||
| 1. **Prepare the payload:** | ||
|
|
There was a problem hiding this comment.
| - Canonicalize the resulting JSON using RFC 8785 to produce the canonical payload | ||
|
|
||
| 2. **Create the protected header:** | ||
|
|
There was a problem hiding this comment.
| - Base64url-encode the serialized header to produce the `protected` field value | ||
|
|
||
| 3. **Compute the signature:** | ||
|
|
There was a problem hiding this comment.
|
Closing this PR as it has been replaced by PR #1411 that does not have all the formatting changes in it. |
…art (#1411) This change simplifies the Part message design by: - Renaming oneof 'part' to 'content' for clarity - Flattening FilePart fields (file_with_uri -> url, file_with_bytes -> bytes) directly into Part - Flattening DataPart by using google.protobuf.Value instead of Struct - Moving media_type and filename to Part level (available for all content types) - Removing separate FilePart and DataPart messages Also updated migration guidance documentation to reference ancillary documents instead of requiring an in-spec appendix. Related to issue #1255 Replaces PR #1363 --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Luca Muscariello <muscariello@ieee.org>
Uh oh!
There was an error while loading. Please reload this page.