Skip to content

Conversation

@a2a-bot
Copy link
Collaborator

@a2a-bot a2a-bot commented Jan 14, 2026

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @a2a-bot, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces significant updates to the A2A protocol specification, primarily focusing on enhancing multi-tenancy capabilities and refining the API surface. It includes the addition of new functionalities for task management and agent card retrieval, alongside a comprehensive restructuring and renaming of existing fields and RPC methods to improve clarity and adherence to best practices. The changes also involve a detailed adjustment of field optionality and requirements, ensuring a more robust and flexible protocol definition.

Highlights

  • API Evolution and Multi-Tenancy: Introduced a new tenant field across various request messages (e.g., SendMessageRequest, GetTaskRequest, CancelTaskRequest, SubscribeToTaskRequest, ListTasksRequest, SetTaskPushNotificationConfigRequest, GetExtendedAgentCardRequest, DeleteTaskPushNotificationConfigRequest, ListTaskPushNotificationConfigRequest), enabling multi-tenancy support for the A2A protocol.
  • New RPC Methods: Added new RPC methods: ListTasks for retrieving tasks with filtering and pagination, and GetExtendedAgentCard for fetching extended agent card information for authenticated agents.
  • RPC Method and Field Renames: Renamed several RPC methods and fields for improved clarity and consistency. Key renames include TaskSubscription to SubscribeToTask, CreateTaskPushNotificationConfig to SetTaskPushNotificationConfig, GetAgentCard to GetExtendedAgentCard, push_notification to push_notification_config in SendMessageConfiguration, update to message in TaskStatus, mime_type to media_type in FilePart, and content to parts in Message.
  • Field Optionality and Requirements: Updated field definitions to explicitly mark many fields as required (e.g., id, context_id, status in Task) and others as optional (e.g., history_length in SendMessageConfiguration and GetTaskRequest, streaming, push_notifications, state_transition_history in AgentCapabilities), providing more precise schema validation and flexibility.
  • AgentCard Structure Updates: Modified the AgentCard structure to use protocol_versions (repeated string) instead of a single protocol_version, replaced url, preferred_transport, and additional_interfaces with a new supported_interfaces field, and renamed supports_authenticated_extended_card to supports_extended_agent_card.
  • Docstring Refinements: Simplified docstrings for various identifier fields (e.g., id, context_id, task_id) by removing specific examples like '(e.g. UUID)' to make them more general.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the generated gRPC and Pydantic type files based on a new version of the A2A specification (v0.3.0). The changes introduce several breaking changes, including renaming RPC methods and message fields, and adding new methods.

While the generated files themselves seem correct, this pull request is incomplete and will likely break the build. The client and server implementations in src/a2a/client/transports/grpc.py and src/a2a/server/request_handlers/grpc_handler.py that consume this generated code have not been updated to reflect these breaking changes.

I've added specific comments highlighting some of the key breaking changes, such as:

  • RPC method renames (e.g., TaskSubscription to SubscribeToTask).
  • Addition of new RPC methods (e.g., ListTasks) that require implementation.
  • Renaming of message fields (e.g., Message.content to Message.parts).

Please update the consuming code to align with the new API definitions in this PR before merging.

Comment on lines +44 to 48
self.SubscribeToTask = channel.unary_stream(
'/a2a.v1.A2AService/SubscribeToTask',
request_serializer=a2a__pb2.SubscribeToTaskRequest.SerializeToString,
response_deserializer=a2a__pb2.StreamResponse.FromString,
_registered_method=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The RPC method TaskSubscription has been renamed to SubscribeToTask. The client and server implementations need to be updated to use the new method name.

Comment on lines +49 to 53
self.SetTaskPushNotificationConfig = channel.unary_unary(
'/a2a.v1.A2AService/SetTaskPushNotificationConfig',
request_serializer=a2a__pb2.SetTaskPushNotificationConfigRequest.SerializeToString,
response_deserializer=a2a__pb2.TaskPushNotificationConfig.FromString,
_registered_method=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The CreateTaskPushNotificationConfig RPC method has been renamed to SetTaskPushNotificationConfig. This breaking change requires updates in both client calls and server-side implementations.

Comment on lines +64 to 68
self.GetExtendedAgentCard = channel.unary_unary(
'/a2a.v1.A2AService/GetExtendedAgentCard',
request_serializer=a2a__pb2.GetExtendedAgentCardRequest.SerializeToString,
response_deserializer=a2a__pb2.AgentCard.FromString,
_registered_method=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The GetAgentCard RPC method has been renamed to GetExtendedAgentCard. All client code calling this method must be updated.

Comment on lines +34 to +38
self.ListTasks = channel.unary_unary(
'/a2a.v1.A2AService/ListTasks',
request_serializer=a2a__pb2.ListTasksRequest.SerializeToString,
response_deserializer=a2a__pb2.ListTasksResponse.FromString,
_registered_method=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

A new ListTasks RPC method has been added to the service. The server-side implementation in A2AServiceServicer needs to be updated to include a handler for this new method.

Comment on lines +49 to +58
__slots__ = ("accepted_output_modes", "push_notification_config", "history_length", "blocking")
ACCEPTED_OUTPUT_MODES_FIELD_NUMBER: _ClassVar[int]
PUSH_NOTIFICATION_FIELD_NUMBER: _ClassVar[int]
PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER: _ClassVar[int]
HISTORY_LENGTH_FIELD_NUMBER: _ClassVar[int]
BLOCKING_FIELD_NUMBER: _ClassVar[int]
accepted_output_modes: _containers.RepeatedScalarFieldContainer[str]
push_notification: PushNotificationConfig
push_notification_config: PushNotificationConfig
history_length: int
blocking: bool
def __init__(self, accepted_output_modes: _Optional[_Iterable[str]] = ..., push_notification: _Optional[_Union[PushNotificationConfig, _Mapping]] = ..., history_length: _Optional[int] = ..., blocking: _Optional[bool] = ...) -> None: ...
def __init__(self, accepted_output_modes: _Optional[_Iterable[str]] = ..., push_notification_config: _Optional[_Union[PushNotificationConfig, _Mapping]] = ..., history_length: _Optional[int] = ..., blocking: _Optional[bool] = ...) -> None: ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The push_notification field has been renamed to push_notification_config. This is a breaking change that will require updates in any code that constructs or accesses fields of the SendMessageConfiguration message.

Comment on lines +117 to +134
__slots__ = ("message_id", "context_id", "task_id", "role", "parts", "metadata", "extensions", "reference_task_ids")
MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
CONTEXT_ID_FIELD_NUMBER: _ClassVar[int]
TASK_ID_FIELD_NUMBER: _ClassVar[int]
ROLE_FIELD_NUMBER: _ClassVar[int]
CONTENT_FIELD_NUMBER: _ClassVar[int]
PARTS_FIELD_NUMBER: _ClassVar[int]
METADATA_FIELD_NUMBER: _ClassVar[int]
EXTENSIONS_FIELD_NUMBER: _ClassVar[int]
REFERENCE_TASK_IDS_FIELD_NUMBER: _ClassVar[int]
message_id: str
context_id: str
task_id: str
role: Role
content: _containers.RepeatedCompositeFieldContainer[Part]
parts: _containers.RepeatedCompositeFieldContainer[Part]
metadata: _struct_pb2.Struct
extensions: _containers.RepeatedScalarFieldContainer[str]
def __init__(self, message_id: _Optional[str] = ..., context_id: _Optional[str] = ..., task_id: _Optional[str] = ..., role: _Optional[_Union[Role, str]] = ..., content: _Optional[_Iterable[_Union[Part, _Mapping]]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., extensions: _Optional[_Iterable[str]] = ...) -> None: ...
reference_task_ids: _containers.RepeatedScalarFieldContainer[str]
def __init__(self, message_id: _Optional[str] = ..., context_id: _Optional[str] = ..., task_id: _Optional[str] = ..., role: _Optional[_Union[Role, str]] = ..., parts: _Optional[_Iterable[_Union[Part, _Mapping]]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., extensions: _Optional[_Iterable[str]] = ..., reference_task_ids: _Optional[_Iterable[str]] = ...) -> None: ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

In the Message class, the content field has been renamed to parts. Also, a new field reference_task_ids has been added. These are significant changes that will affect message creation and processing logic.

Comment on lines +485 to +494
__slots__ = ("tenant", "message", "configuration", "metadata")
TENANT_FIELD_NUMBER: _ClassVar[int]
MESSAGE_FIELD_NUMBER: _ClassVar[int]
CONFIGURATION_FIELD_NUMBER: _ClassVar[int]
METADATA_FIELD_NUMBER: _ClassVar[int]
request: Message
tenant: str
message: Message
configuration: SendMessageConfiguration
metadata: _struct_pb2.Struct
def __init__(self, request: _Optional[_Union[Message, _Mapping]] = ..., configuration: _Optional[_Union[SendMessageConfiguration, _Mapping]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ...
def __init__(self, tenant: _Optional[str] = ..., message: _Optional[_Union[Message, _Mapping]] = ..., configuration: _Optional[_Union[SendMessageConfiguration, _Mapping]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The request field in SendMessageRequest has been renamed to message. This is a breaking change that will require updates in any code that constructs this request.

Comment on lines +601 to +606
__slots__ = ("task", "message")
TASK_FIELD_NUMBER: _ClassVar[int]
MSG_FIELD_NUMBER: _ClassVar[int]
MESSAGE_FIELD_NUMBER: _ClassVar[int]
task: Task
msg: Message
def __init__(self, task: _Optional[_Union[Task, _Mapping]] = ..., msg: _Optional[_Union[Message, _Mapping]] = ...) -> None: ...
message: Message
def __init__(self, task: _Optional[_Union[Task, _Mapping]] = ..., message: _Optional[_Union[Message, _Mapping]] = ...) -> None: ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The msg field in SendMessageResponse has been renamed to message. This is a breaking change that will require updates in any code that processes this response.

Comment on lines +609 to +618
__slots__ = ("task", "message", "status_update", "artifact_update")
TASK_FIELD_NUMBER: _ClassVar[int]
MSG_FIELD_NUMBER: _ClassVar[int]
MESSAGE_FIELD_NUMBER: _ClassVar[int]
STATUS_UPDATE_FIELD_NUMBER: _ClassVar[int]
ARTIFACT_UPDATE_FIELD_NUMBER: _ClassVar[int]
task: Task
msg: Message
message: Message
status_update: TaskStatusUpdateEvent
artifact_update: TaskArtifactUpdateEvent
def __init__(self, task: _Optional[_Union[Task, _Mapping]] = ..., msg: _Optional[_Union[Message, _Mapping]] = ..., status_update: _Optional[_Union[TaskStatusUpdateEvent, _Mapping]] = ..., artifact_update: _Optional[_Union[TaskArtifactUpdateEvent, _Mapping]] = ...) -> None: ...
def __init__(self, task: _Optional[_Union[Task, _Mapping]] = ..., message: _Optional[_Union[Message, _Mapping]] = ..., status_update: _Optional[_Union[TaskStatusUpdateEvent, _Mapping]] = ..., artifact_update: _Optional[_Union[TaskArtifactUpdateEvent, _Mapping]] = ...) -> None: ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The msg field in StreamResponse has been renamed to message. This is a breaking change that will require updates in any code that processes this streaming response.

Comment on lines +99 to +108
__slots__ = ("file_with_uri", "file_with_bytes", "media_type", "name")
FILE_WITH_URI_FIELD_NUMBER: _ClassVar[int]
FILE_WITH_BYTES_FIELD_NUMBER: _ClassVar[int]
MIME_TYPE_FIELD_NUMBER: _ClassVar[int]
MEDIA_TYPE_FIELD_NUMBER: _ClassVar[int]
NAME_FIELD_NUMBER: _ClassVar[int]
file_with_uri: str
file_with_bytes: bytes
mime_type: str
media_type: str
name: str
def __init__(self, file_with_uri: _Optional[str] = ..., file_with_bytes: _Optional[bytes] = ..., mime_type: _Optional[str] = ..., name: _Optional[str] = ...) -> None: ...
def __init__(self, file_with_uri: _Optional[str] = ..., file_with_bytes: _Optional[bytes] = ..., media_type: _Optional[str] = ..., name: _Optional[str] = ...) -> None: ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The mime_type field has been renamed to media_type. This change needs to be propagated to all usages of the FilePart message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants