Skip to content

Conversation

@muscariello
Copy link
Member

@muscariello muscariello commented Feb 2, 2026

Updates the Python SDK to match Protocol v1.0.0-rc specifications.

Changes include:

  • Renamed 'name' fields to 'id' and 'task_id'
  • Updated PushNotificationConfig structure used in requests
  • Fixed unit and integration tests to align with proto changes
  • Removed 'final' field from TaskStatusUpdateEvent

@muscariello muscariello requested review from a team and a2a-bot as code owners February 2, 2026 15:52
@muscariello muscariello changed the base branch from main to 1.0-a2a_proto_refactor February 2, 2026 15:53
@muscariello muscariello marked this pull request as draft February 2, 2026 15:57
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @muscariello, 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 a significant refactoring of the Python SDK to align with Protocol V1 specifications. The core change involves migrating from Pydantic-based data models to native Protobuf message objects for all A2A types, which improves performance and consistency. This transition necessitated updates to field names, data structures like PushNotificationConfig, and the underlying serialization/deserialization logic across both client and server components. Additionally, the PR streamlines the code generation process and removes outdated legacy client implementations, ensuring the SDK is modern and fully compliant with the latest protocol standards.

Highlights

  • Protocol V1 Alignment: The Python SDK has been updated to fully comply with Protocol V1 specifications, ensuring compatibility with the latest protocol standards.
  • Pydantic to Protobuf Transition: A major refactor has been implemented to transition from Pydantic-based data models to direct usage of Protobuf message objects for A2A types. This impacts client and server serialization, deserialization, and data handling.
  • Field Renaming: Key fields across various structures have been renamed for clarity and consistency, specifically changing 'name' fields to 'id' and 'task_id'.
  • Updated PushNotificationConfig: The internal structure and handling of the PushNotificationConfig used in requests have been updated to reflect the new protocol specifications.
  • Code Generation Streamlining: The code generation process has been improved, with buf.gen.yaml now directing Python type generation to src/a2a/types and including OpenAPI v2 spec generation. A new gen_proto.sh script manages these tasks.
  • Legacy Client Removal: Deprecated client components, specifically a2a.client.legacy.A2AClient and a2a.client.legacy_grpc.A2AGrpcClient, have been removed to streamline the codebase.
  • Database Model Updates: SQLAlchemy custom types (PydanticType, PydanticListType) have been enhanced to seamlessly handle both Pydantic models and Protobuf messages for robust data persistence.
Ignored Files
  • Ignored by pattern: .github/workflows/** (3)
    • .github/workflows/linter.yaml
    • .github/workflows/unit-tests.yml
    • .github/workflows/update-a2a-types.yml
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 is a substantial and well-executed pull request that refactors the Python SDK to align with Protocol V1. The changes are extensive, touching nearly every part of the codebase, and appear to be implemented correctly and consistently with the goals outlined in the description.

Key improvements include:

  • A shift from Pydantic models to using Protobuf-generated classes directly, which simplifies the code by removing the proto_utils conversion layer.
  • A new, clearer exception hierarchy defined in a2a.utils.errors.
  • The introduction of a robust signing and verification mechanism for Agent Cards.
  • Renaming of fields and methods (e.g., resubscribe to subscribe, get_card to get_extended_agent_card) for better clarity and consistency with the protocol.
  • Comprehensive updates to tests to cover the new protocol version and features.

The overall quality of the refactoring is high. I have only one minor stylistic suggestion.

Comment on lines 285 to 286

)
Copy link
Contributor

Choose a reason for hiding this comment

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

low

This empty line and the indentation of the closing parenthesis seem a bit off. For better readability and consistency, I suggest removing the empty line and adjusting the indentation.

    )

@muscariello muscariello force-pushed the spec-update-rc1 branch 2 times, most recently from 7d64a4a to d1b8162 Compare February 2, 2026 21:25
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
@muscariello muscariello marked this pull request as ready for review February 2, 2026 21:36
@muscariello muscariello changed the title refactor: Update to Protocol V1 and fix all tests refactor!: Update to Protocol V1 and fix all tests Feb 2, 2026
@muscariello muscariello changed the title refactor!: Update to Protocol V1 and fix all tests refactor!: Update to Protocol v1.0.0-rc and fix all tests Feb 2, 2026
params: SubscribeToTaskRequest,
context: ServerCallContext | None = None,
) -> AsyncGenerator[StreamResponse]:
) -> AsyncGenerator[Event, None]:
Copy link

Choose a reason for hiding this comment

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

I'm not sure we want to revert this change

Requires the task and its queue to still be active.
"""
task_id = _extract_task_id(params.name)
task_id = _extract_task_id(params.id)
Copy link

Choose a reason for hiding this comment

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

Not need for _extract_task_id(params.id) any longer, task.id is the ID.

raise ServerError(error=UnsupportedOperationError())

task_id = _extract_task_id(params.parent)
task_id = _extract_task_id(params.task_id)
Copy link

Choose a reason for hiding this comment

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

ditto

@@ -476,7 +476,7 @@ async def _cleanup_producer(

async def on_set_task_push_notification_config(
Copy link

Choose a reason for hiding this comment

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

We should rename "on_set" to "on_create" to align with the protocol.

push_id = request.path_params['push_id']
params = GetTaskPushNotificationConfigRequest(
name=f'tasks/{task_id}/pushNotificationConfigs/{push_id}'
task_id=f'tasks/{task_id}',
Copy link

Choose a reason for hiding this comment

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

task_id should just be the task_id

Parse(body, params)
# Set the parent to the task resource name format
params.parent = f'tasks/{task_id}'
params.task_id = f'tasks/{task_id}'
Copy link

Choose a reason for hiding this comment

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

ditto

return MessageToDict(value, preserving_proto_field_name=False)
if isinstance(value, BaseModel):
return value.model_dump(mode='json')
return cast('BaseModel', value).model_dump(mode='json')
Copy link

Choose a reason for hiding this comment

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

I don't think you need a cast here normally mypy is happy with just the isinstance(...) check.

return [
MessageToDict(part.data.data) for part in parts if part.HasField('data')
]
return [MessageToDict(part.data) for part in parts if part.HasField('data')]
Copy link

Choose a reason for hiding this comment

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

part.data is of type protobuf.Value which can contain any JSON compatible type, dict, string, array etc
So the return type list[dict[str, Any]] isn't correct, and also I don't think we want to use MessageToDict because part.data isn't a message type.

Honestly I think with the changes to Part, both get_data_parts and get_file_parts functions probably need refactoring out of the code because they don't mean what they used to mean.

"""Provides a sample TaskPushNotificationConfig object."""
return TaskPushNotificationConfig(
name='tasks/task-1',
task_id='tasks/task-1',
Copy link

Choose a reason for hiding this comment

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

Suggested change
task_id='tasks/task-1',
task_id='task-1',


# Use GetTaskRequest with name (AIP resource format)
params = GetTaskRequest(name=f'tasks/{GET_TASK_RESPONSE.id}')
params = GetTaskRequest(id=f'tasks/{GET_TASK_RESPONSE.id}')
Copy link

Choose a reason for hiding this comment

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

Suggested change
params = GetTaskRequest(id=f'tasks/{GET_TASK_RESPONSE.id}')
params = GetTaskRequest(id=GET_TASK_RESPONSE.id)


[tool.pyright]
include = ["src"]
ignore = ["src/a2a/types"]
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason this is ignore instead of exclude?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants