Skip to content

Draft: Migrate to a2a v1#2210

Draft
jezekra1 wants to merge 6 commits intomainfrom
migrate-to-a2a-v1
Draft

Draft: Migrate to a2a v1#2210
jezekra1 wants to merge 6 commits intomainfrom
migrate-to-a2a-v1

Conversation

@jezekra1
Copy link
Collaborator

Summary

Linked Issues

Documentation

  • No Docs Needed:

If this PR adds new feature or changes existing. Make sure documentation is adjusted accordingly. If the docs is not needed, please explain why.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jezekra1, 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 represents a significant architectural upgrade, transitioning the AgentStack SDK and CLI to version 1 of the A2A protocol. The core change involves replacing Pydantic models with Protobuf-based types for all inter-agent communication, leading to a more standardized and efficient data exchange. This migration necessitated widespread code adjustments, from dependency updates and internal data structures to how extensions are managed and how messages and artifacts are constructed and validated. The aim is to enhance protocol robustness and pave the way for future features and interoperability.

Highlights

  • A2A v1 Migration: The core A2A protocol implementation has been migrated from Pydantic-based data models to Protobuf-based types. This is a fundamental change affecting how messages, tasks, and agent metadata are structured and validated.
  • Protobuf Validation: New validation logic has been introduced for Protobuf messages, ensuring that fields marked as 'REQUIRED' in the A2A v1 .proto definition are properly set. This enhances data integrity and consistency across the protocol.
  • Dependency Management Updates: The uv.lock files in both agents/chat and apps/agentstack-cli have been extensively updated to reflect new dependency versions and introduce new packages like json-rpc, markdown-it-py, mdurl, and rich, aligning with the A2A v1 ecosystem.
  • Agent SDK Refactoring: The Agent class in the SDK has been refactored from a NamedTuple to a full class, providing more robust initialization, card management, and dependency injection capabilities. This includes handling implicit and required extensions more explicitly.
  • Extension Handling Improvements: The extension system (BaseExtensionSpec, BaseExtensionServer) has been updated to better integrate with Protobuf types, including using MessageToDict for metadata parsing and ContextVar for managing current extension instances.
  • CLI and Server API Adjustments: The AgentStack CLI and Server API routes have been adapted to work with the new A2A v1 Protobuf types, including changes to request/response parameters and internal data handling for agent cards, tasks, and messages.
  • File Handling Modernization: The way files are handled within messages and artifacts has been updated, moving from FilePart, FileWithBytes, FileWithUri, and TextPart to a more unified Part structure that leverages part.url, part.raw, and part.text fields directly.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • agents/chat/src/chat/agent.py
    • Updated imports to consolidate PlatformApiExtensionServer and PlatformApiExtensionSpec.
    • Modified metadata handling for trajectory content to use model_dump_json().
  • agents/chat/src/chat/tools/files/model.py
    • Updated Role enum references from Role.user and Role.agent to Role.ROLE_USER and Role.ROLE_AGENT.
    • Added arbitrary_types_allowed=True to FileChatInfo model definition.
  • agents/chat/src/chat/tools/files/utils.py
    • Removed FilePart and FileWithUri from a2a.types imports.
    • Updated message text extraction from part.root.text to part.text and part.root.kind to part.HasField('text').
    • Changed Role enum references to Role.ROLE_AGENT and Role.ROLE_USER.
    • Modified file extraction logic to check part.HasField('url') instead of part.root matching FilePart.
  • agents/chat/uv.lock
    • Updated a2a-sdk to a newer git version.
    • Added new dependencies: googleapis-common-protos, json-rpc, markdown-it-py, mdurl, rich, typing-extensions.
    • Updated versions for numerous packages including ruff, async-lru, authlib, cachetools, certifi, fastapi, filelock, google-api-core, grpcio and related, hf-xet, litellm, openai, openinference-instrumentation, opentelemetry-instrumentation-openai, opentelemetry-semantic-conventions-ai, primp, pydantic-settings, regex, typer, types-protobuf.
  • apps/agentstack-cli/.vscode/launch.json
    • Added a new VSCode debug configuration for agentstack cli.
  • apps/agentstack-cli/src/agentstack_cli/main.py
    • Added a new file to serve as the main entry point for the agentstack_cli application.
  • apps/agentstack-cli/src/agentstack_cli/api.py
    • Updated agent_card.model_dump to use pick(MessageToDict, agent_card(...)) for JSON serialization.
  • apps/agentstack-cli/src/agentstack_cli/commands/agent.py
    • Removed base64 and dedent imports.
    • Updated a2a.types imports, removing DataPart, FilePart, FileWithBytes, FileWithUri, Task, TaskArtifactUpdateEvent, TaskStatus, TaskStatusUpdateEvent, TextPart.
    • Added MessageToDict import from google.protobuf.json_format.
    • Modified ProviderUtils.detail to use MessageToDict for extension parameters.
    • Changed _run_agent input type from str | DataPart | FormResponse to str | Part | FormResponse.
    • Updated message part access from part.root.text to part.text and isinstance(part.root, TextPart) to part.HasField('text').
    • Changed Role.user to Role.ROLE_USER and Role.agent to Role.ROLE_AGENT.
    • Refactored TaskStatusUpdateEvent and TaskArtifactUpdateEvent handling to align with new protobuf structures.
    • Removed _render_examples function.
    • Updated agent.model_dump to MessageToDict(agent) for extra information display.
  • apps/agentstack-cli/src/agentstack_cli/utils.py
    • Added a new pick utility function to filter dictionary keys.
  • apps/agentstack-cli/uv.lock
    • Updated a2a-sdk to a newer git version.
    • Added new dependencies: json-rpc.
    • Updated ruff version.
  • apps/agentstack-sdk-py/.vscode/launch.json
    • Added a new VSCode debug configuration for Python files and tests.
  • apps/agentstack-sdk-py/a2a.proto
    • Added a new file defining the A2A v1 protobuf schema, including services, messages, enums, and security schemes.
  • apps/agentstack-sdk-py/examples/check_validation.py
    • Added a new example file demonstrating protobuf message validation.
  • apps/agentstack-sdk-py/examples/experiment.py
    • Added a new example file demonstrating MessageToDict usage with protobuf messages.
  • apps/agentstack-sdk-py/examples/mcp_client.py
    • Added noqa: ASYNC250 to input() call.
  • apps/agentstack-sdk-py/examples/tool_call_approval_client.py
    • Added noqa: ASYNC250 to input() call.
  • apps/agentstack-sdk-py/pyproject.toml
    • Updated ruff version.
    • Added a2a-sdk as a git source in [tool.uv.sources].
  • apps/agentstack-sdk-py/src/agentstack_sdk/init.py
    • Added conditional call to _inject_validation() from agentstack_sdk.a2a.types based on AGENTSTACK_DONT_INJECT_A2A_VALIDATION environment variable.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/auth/oauth/oauth.py
    • Changed TextPart import to Part.
    • Updated AgentMessage metadata assignment to use Metadata object.
    • Changed Role.user to Role.ROLE_USER for creating response messages.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/base.py
    • Added Self and ContextVar imports.
    • Added MessageToDict import.
    • Updated BaseExtensionSpec.from_agent_card to use MessageToDict for parsing extension parameters and to correctly set the required attribute.
    • Removed _dependencies attribute from BaseExtensionServer.
    • Added current() class method to BaseExtensionServer to get the current instance from ContextVar.
    • Updated parse_client_metadata and parse_server_metadata to use MessageToDict for accessing message metadata.
    • Modified BaseExtensionServer.__call__ signature, removing dependencies parameter and setting the instance to _context_var.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/services/mcp.py
    • Removed _get_oauth_server and _get_platform_server methods.
    • Updated _create_auth to retrieve PlatformApiExtensionServer and OAuthExtensionServer instances using their current() class methods.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/services/platform.py
    • Removed PlatformAuthenticatedUser import.
    • Updated lifespan method to check for self.data.auth_token before using the client.
    • Removed the ExtensionError raise when auth_token is missing in handle_incoming_message.
    • Added _PlatformSelfRegistrationExtensionServer class definition.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/ui/canvas.py
    • Removed TextPart import.
    • Added ParseDict import.
    • Modified CanvasEditRequest to allow arbitrary types and added a parse_artifact validator to convert dicts to Artifact.
    • Updated handle_incoming_message to clear and extend message parts based on part.HasField('text') instead of isinstance(part.root, TextPart).
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/ui/citation.py
    • Removed DataPart, FilePart, TextPart imports.
    • Changed the return type of message method from AgentMessage to Message.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/ui/error.py
    • Changed the return type of message method from AgentMessage to Message.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/extensions/ui/trajectory.py
    • Removed DataPart, FilePart, TextPart imports.
    • Changed the return type of message method from AgentMessage to Message.
  • apps/agentstack-sdk-py/src/agentstack_sdk/a2a/types.py
    • Removed Literal and various Part imports.
    • Added functools, sys, field_behavior_pb2, descriptor, _message imports.
    • Replaced Pydantic models AgentArtifact, ArtifactChunk, AgentMessage, InputRequired, AuthRequired with functions that construct and return a2a.types protobuf objects.
    • Introduced validate_message and _validate_message functions for comprehensive protobuf validation based on field_behavior_pb2.REQUIRED.
    • Added _inject_validation function (currently a no-op) for potential future validation injection.
  • apps/agentstack-sdk-py/src/agentstack_sdk/platform/context.py
    • Added Any, Self imports.
    • Added MessageToDict and ParseDict imports.
    • Modified ContextHistoryItem to allow arbitrary types and added a parse_data validator to convert dicts to Artifact or Message.
    • Updated add_history_item to use MessageToDict for serializing data.
  • apps/agentstack-sdk-py/src/agentstack_sdk/platform/file.py
    • Removed FilePart and FileWithUri imports.
    • Changed to_file_part method to to_part and updated its implementation to return a Part object directly.
    • Refactored load_file to accept a Part object and handle file content based on part.url or part.raw fields.
  • apps/agentstack-sdk-py/src/agentstack_sdk/platform/provider.py
    • Added Any, Self imports.
    • Added MessageToDict and ParseDict imports.
    • Modified Provider to allow arbitrary types and added a parse_card validator to convert dicts to AgentCard.
    • Updated create, patch, and preview methods to use MessageToDict for serializing agent_card.
  • apps/agentstack-sdk-py/src/agentstack_sdk/platform/provider_discovery.py
    • Added Any, Self imports.
    • Added ParseDict import.
    • Modified ProviderDiscovery to allow arbitrary types and added a parse_card validator to convert dicts to AgentCard.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/agent.py
    • Removed NamedTuple and cast imports.
    • Added Final import.
    • Updated a2a.types imports to include AgentCardSignature and SecurityRequirement from a2a_pb2.
    • Added _message import from google.protobuf.
    • Imported AgentDetailExtensionSpec and BaseExtensionServer from agentstack_sdk.a2a.extensions.
    • Imported validate_message from agentstack_sdk.a2a.types.
    • Imported _DEFAULT_AGENT_INTERFACE, _DEFAULT_AGENT_SKILL, DEFAULT_IMPLICIT_EXTENSIONS from agentstack_sdk.server.constants.
    • Imported A2ASecurity from agentstack_sdk.types.
    • Refactored Agent from a NamedTuple to a class, encapsulating initialization, card management, and dependency handling.
    • The agent decorator now constructs AgentCard using protobuf types directly and handles a2a_security, supported_interfaces, implicit_extensions, and required_extensions.
    • Updated _with_context to modify protobuf message fields in place.
    • Modified _run_agent_function to use validate_message for yielded protobuf messages, handle new Part types, and process Artifact metadata for _last_chunk.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/app.py
    • Added importlib_metadata and packaging.version imports.
    • Removed TransportProtocol import.
    • Added BaseExtensionServer import.
    • Updated create_app signature to include url, implicit_extensions, required_extensions, and auth_backend parameters.
    • Modified create_app to call agent.initialize() with the new parameters and construct AgentInterface objects with protocol_binding and protocol_version.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/constants.py
    • Added DEFAULT_IMPLICIT_EXTENSIONS dictionary containing default ErrorExtensionServer and PlatformApiExtensionServer instances.
    • Defined _DEFAULT_AGENT_INTERFACE and _DEFAULT_AGENT_SKILL constants using protobuf types.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/context.py
    • Removed MessageSendConfiguration import.
    • Removed configuration field from RunContext.
    • Modified RunContext constructor to require _store and updated store method to use Message.CopyFrom for message updates.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/dependencies.py
    • Updated Dependency type alias to remove dict[str, 'Dependency'] from the callable signature.
    • Modified Depends.__call__ signature, removing the dependencies parameter.
    • Updated lambda functions for Message and RunContext dependencies to match the new Depends.__call__ signature.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/middleware/platform_auth_backend.py
    • Removed AgentCard import.
    • Added SecurityRequirement and StringList imports.
    • Changed update_card_security_schemes method to get_card_security_schemes and updated its return type to A2ASecurity.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/server.py
    • Removed AnyUrl import.
    • Updated Server.agent method to directly assign the created Agent instance to self._agent.
    • Modified serve method to use Agent.initialize() and handle self-registration logic by dynamically adding _PlatformSelfRegistrationExtensionServer to implicit_extensions.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/store/context_store.py
    • Removed Dependency and Depends imports.
    • Added required_extensions property to ContextStore.
    • Updated create method signature to remove initialized_dependencies parameter.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/store/memory_context_store.py
    • Removed Dependency import.
    • Added MessageToDict import.
    • Updated load_history to yield item directly instead of item.model_copy(deep=True).
    • Updated store method to use MessageToDict for serializing data.
    • Updated create method signature to remove initialized_dependencies parameter.
  • apps/agentstack-sdk-py/src/agentstack_sdk/server/store/platform_context_store.py
    • Removed _IMPLICIT_DEPENDENCY_PREFIX, Depends, and Dependency imports.
    • Added asynccontextmanager import.
    • Added required_extensions property to return PlatformApiExtensionSpec.URI.
    • Updated create method signature to remove initialized_dependencies parameter.
    • Introduced a client async context manager to manage PlatformApiExtensionServer usage.
    • Modified load_history, store, and delete_history_from_id to use the new self.client() context manager.
  • apps/agentstack-sdk-py/src/agentstack_sdk/types.py
    • Added TypedDict import.
    • Defined A2ASecurity TypedDict for security requirements and schemes.
    • Changed SdkAuthenticationBackend.update_card_security_schemes to get_card_security_schemes with A2ASecurity return type.
  • apps/agentstack-sdk-py/src/agentstack_sdk/util/file.py
    • Removed base64 import.
    • Removed FilePart, FileWithBytes, FileWithUri imports.
    • Refactored load_file to accept a Part object and handle content based on part.url or part.raw fields.
  • apps/agentstack-sdk-py/tests/e2e/conftest.py
    • Added cli import from ddgs.cli.
    • Updated card = AgentCard.model_validate(card_resp.json()) to ParseDict(card_resp.json(), AgentCard(), ignore_unknown_fields=True).
    • Modified agent functions (echo, slow_echo, awaiter) to access message text directly from part.text.
    • Updated artifact_producer to use AgentArtifact with Part(text=...), Part(data=ParseDict(..., Value())), and Part(raw=..., media_type=...).
    • Updated chunked_artifact_producer to use ArtifactChunk with Part(text=...).
  • apps/agentstack-sdk-py/tests/e2e/test_extensions.py
    • Updated get_final_task_from_stream to match new stream response structure.
    • Modified test_extension_is_not_reused to use client._card instead of fetching it.
    • Updated assertions for message text to use part.text.
    • Modified test_error_extension_without_stacktrace and test_error_extension_exception_group_with_stacktrace to use client._card and MessageToDict(error_message.metadata).
    • Updated error_agent to check part.HasField('text') for message content.
    • Modified test_error_extension_context_isolation to use client._card.
  • apps/agentstack-sdk-py/tests/e2e/test_history.py
    • Updated get_final_task_from_stream to match new stream response structure.
    • Modified send_message_get_response to access message text directly from msg.parts[0].text.
    • Updated history_agent to use Role.ROLE_AGENT.
  • apps/agentstack-sdk-py/tests/e2e/test_runs.py
    • Updated imports for a2a.types, removing old parameter types and adding new request/response types.
    • Modified create_send_request_object to return SendMessageRequest directly.
    • Updated test_run_sync and other tests to use new TaskState enums (e.g., TaskState.TASK_STATE_COMPLETED) and Role.ROLE_AGENT.
    • Adjusted stream handling in test_run_stream, test_run_cancel_stream, test_run_resume_stream, test_artifact_streaming, test_chunked_artifacts to match StreamResponse structure.
    • Updated test_run_status, test_run_cancel_awaiter, test_run_timeout to use new GetTaskRequest and CancelTaskRequest types.
    • Modified artifact assertions in test_artifacts to use MessageToDict for data parts and image_part.raw for raw bytes.
  • apps/agentstack-sdk-py/tests/e2e/test_yields.py
    • Updated imports for a2a.types, removing old part types and adding Artifact, Part, StreamResponse.
    • Added MessageToDict, ParseDict, Value imports.
    • Modified get_final_task_from_stream to handle StreamResponse and new TaskState enums.
    • Updated create_send_request_object to return SendMessageRequest directly.
    • Modified agent functions to access message text directly from part.text and use Role.ROLE_AGENT.
    • Updated yielder_of_meta_data to use MessageToDict and ParseDict for metadata and data parts.
    • Updated yielder_of_all_types_agent to use Part for all content types and new TaskState enums, and removed final field from TaskStatusUpdateEvent.
  • apps/agentstack-sdk-py/tests/unit/a2a/test_types.py
    • Added a new unit test file for a2a.types validation, covering ArtifactChunk, Message, AgentMessage, Artifact, TaskStatus, and Struct fields.
  • apps/agentstack-server/Dockerfile
    • Changed base image from python:3.13-alpine3.22 to python:3.13.
    • Added apt-get update && apt-get install -y git nodejs npm for necessary build tools.
  • apps/agentstack-server/check_a2a.py
    • Added a new file to check a2a.types imports.
  • apps/agentstack-server/src/agentstack_server/api/routes/a2a.py
    • Added Any import.
    • Removed TransportProtocol import.
    • Added MessageToDict and ParseDict imports.
    • Modified create_proxy_agent_card to accept dict[str, Any] for agent_card and use ParseDict for conversion, and to handle supported_interfaces, security_requirements, security_schemes using protobuf methods.
    • Updated get_agent_card to return dict[str, Any] and use MessageToDict for serialization.
  • apps/agentstack-server/src/agentstack_server/api/routes/providers.py
    • Added Any import.
    • Added MessageToDict import.
    • Imported Configuration.
    • Renamed create_proxy_agent_card to create_proxy_agent_card_ and created a new create_proxy_agent_card function that returns a dict[str, Any].
  • apps/agentstack-server/src/agentstack_server/api/schema/provider.py
    • Changed type hints for agent_card fields from AgentCard to dict[str, Any].
  • apps/agentstack-server/src/agentstack_server/domain/models/context.py
    • Changed ContextHistoryItemData type alias to dict[str, Any].
    • Updated kind computed property to determine type based on artifact_id key in dictionary.
  • apps/agentstack-server/src/agentstack_server/domain/models/provider.py
    • Added ParseDict import.
    • Updated load_agent_card to return dict[str, Any] and use ParseDict for validation.
    • Modified NetworkProviderLocation.load_agent_card to handle extension parameters as dictionaries.
  • apps/agentstack-server/src/agentstack_server/domain/models/provider_discovery.py
    • Changed type hint for agent_card field from AgentCard to dict[str, Any].
  • apps/agentstack-server/src/agentstack_server/infrastructure/persistence/repositories/context.py
    • Updated add_history_item to use history_item.data directly.
  • apps/agentstack-server/src/agentstack_server/infrastructure/persistence/repositories/provider.py
    • Updated _to_row to use provider.agent_card directly.
  • apps/agentstack-server/src/agentstack_server/infrastructure/persistence/repositories/requests.py
    • Added explicit initialization for task_id, context_id, and trace_id to None.
  • apps/agentstack-server/src/agentstack_server/jobs/crons/provider.py
    • Removed AgentCard import.
    • Updated _check_provider to handle resp_card as dict[str, Any] and compare extension parameters as dictionaries.
  • apps/agentstack-server/src/agentstack_server/service_layer/services/a2a.py
    • Added override import.
    • Removed NamedTuple from A2AServerResponse.
    • Updated a2a.types imports to use new A2A v1 request/response types (e.g., SendMessageRequest, GetTaskRequest) and StreamResponse.
    • Added ParseDict import.
    • Updated _SUPPORTED_TRANSPORTS to use string literals for protocol bindings.
    • Refactored create_deployment_agent_card to accept dict[str, Any] and use AgentCard() for parsing and AgentInterface() for interface updates.
    • Introduced _response_to_event helper function to parse StreamResponse payload.
    • Updated all on_* methods to use the new A2A v1 request/response types and handle StreamResponse events.
  • apps/agentstack-server/src/agentstack_server/service_layer/services/contexts.py
    • Added Any import.
    • Modified _extract_content_for_title to accept dict[str, Any] and extract content from dictionary keys.
    • Updated add_history_item to check data.get('role') and data.get('metadata').
    • Modified generate_conversation_title to access file and raw message data as dictionaries.
  • apps/agentstack-server/src/agentstack_server/service_layer/services/providers.py
    • Added Any import.
    • Changed type hints for agent_card fields from AgentCard to dict[str, Any].
    • Updated _inject_default_agent_detail_extension to access agent_card as a dictionary.
  • apps/agentstack-server/src/agentstack_server/utils/a2a.py
    • Changed type hints for agent_card and AgentExtension to dict[str, Any].
    • Updated get_extension to access agent_card and its capabilities/extensions as dictionaries.
  • apps/agentstack-server/tests/e2e/agents/conftest.py
    • Updated a2a_client_factory call to pass providers[0].agent_card directly.
  • apps/agentstack-server/tests/e2e/agents/test_agent_builds.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/agents/test_agent_starts.py
    • Updated Role.agent to Role.ROLE_AGENT.
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/agents/test_context_store.py
    • Updated Role.agent to Role.ROLE_AGENT.
  • apps/agentstack-server/tests/e2e/agents/test_platform_extensions.py
    • Removed FilePart import.
    • Updated file_reader_writer to check part.HasField('file') and use file.to_part().
    • Updated test_platform_api_extension to use Role.ROLE_USER and file.to_part().
    • Updated TaskState enums to TaskState.TASK_STATE_FAILED and TaskState.TASK_STATE_COMPLETED.
    • Modified load_file call to use task.history[2].parts[0].file.
    • Updated test_self_registration_with_variables assertions to use part.text.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/agent-settings/test_basic_settings.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/canvas/test_canvas_with_llm.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/citations/test_citation_basic_usage.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/env-variables/test_basic_environment_variables.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/error/test_adding_error_context.py
    • Updated TaskState.failed to TaskState.TASK_STATE_FAILED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/error/test_advanced_error_reporting.py
    • Updated TaskState.failed to TaskState.TASK_STATE_FAILED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/error/test_multiple_errors_handling.py
    • Updated TaskState.failed to TaskState.TASK_STATE_FAILED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/error/test_standard_error_reporting.py
    • Updated TaskState.failed to TaskState.TASK_STATE_FAILED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/files/test_file_processing.py
    • Updated Role.user to Role.ROLE_USER.
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/forms/test_dynamic_form_requests.py
    • Updated TaskState.input_required to TaskState.TASK_STATE_INPUT_REQUIRED.
    • Updated Role.user to Role.ROLE_USER.
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/forms/test_initial_form_rendering.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/llm-proxy-service/test_llm_access.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/mcp/test_custom_mcp_client_with_oauth.py
    • Removed TextPart import.
    • Updated Role.user to Role.ROLE_USER.
    • Updated TaskState.auth_required to TaskState.TASK_STATE_AUTH_REQUIRED.
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/mcp/test_github_mcp_agent.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/multi-turn/test_advanced_history.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/multi-turn/test_basic_history.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/overview/test_advanced_server_wrapper.py
    • Updated TaskState.input_required to TaskState.TASK_STATE_INPUT_REQUIRED.
    • Updated Role.user to Role.ROLE_USER.
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/overview/test_dependency_injection.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/overview/test_server_wrapper.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/rag/test_conversation_rag_agent.py
    • Updated Role.user to Role.ROLE_USER.
    • Updated file.to_file_part() to file.to_part().
    • Updated TextPart to Part.
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/rag/test_simple_rag_agent.py
    • Updated Role.user to Role.ROLE_USER.
    • Updated file.to_file_part() to file.to_part().
    • Updated TextPart to Part.
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/secrets/test_basic_secrets.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
    • Updated TaskState.auth_required to TaskState.TASK_STATE_AUTH_REQUIRED.
    • Updated Role.user to Role.ROLE_USER.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/tool-calls/test_basic_approve.py
    • Updated TaskState.input_required to TaskState.TASK_STATE_INPUT_REQUIRED.
    • Updated Role.user to Role.ROLE_USER.
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
    • Updated TaskState.failed to TaskState.TASK_STATE_FAILED.
  • apps/agentstack-server/tests/e2e/examples/agent-integration/trajectory/test_trajectory_basic_usage.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/examples/deploy-agents/building-agents/test_implement_your_agent_logic.py
    • Updated TaskState.completed to TaskState.TASK_STATE_COMPLETED.
  • apps/agentstack-server/tests/e2e/routes/test_a2a_proxy.py
    • Updated imports for a2a.server.jsonrpc_models, a2a.types, a2a.types.a2a_pb2.
    • Removed SendMessageResponse, SendMessageSuccessResponse, TaskNotFoundError imports.
    • Added ServerCallContext, AgentInterface, AgentSkill, Struct, Value, TestClient imports.
    • Refactored test data (MINIMAL_AGENT_SKILL, AGENT_CAPS, MINIMAL_AGENT_CARD_DATA, EXTENDED_AGENT_SKILL, EXTENDED_AGENT_CARD_DATA, TEXT_PART_DATA, DATA_PART, MINIMAL_MESSAGE_USER, MINIMAL_TASK_STATUS, FULL_TASK_STATUS) to use protobuf types directly.
    • Updated handler.on_resubscribe_to_task to handler.on_subscribe_to_task.
    • Skipped several tests related to custom URLs and dynamic card modifiers due to proxy limitations.
    • Updated test_send_message to use new method names and check data["result"]["task"]["id"].
    • Updated test_cancel_task to use new method names and check data["result"]["status"]["state"].
    • Updated test_get_task to use new method names.
    • Updated test_set_push_notification_config to use new method names and parameters.
    • Updated test_get_push_notification_config to use new method names and parameters.
    • Modified test_server_auth to use new method names and check data["result"]["message"]["parts"][0]["text"].
    • Updated test_message_send_stream to use new method names and check for artifact-0 in content.
    • Updated test_task_resubscription to use new method names and check for artifact-0 in content.
    • Modified test_invalid_request_structure to check for MethodNotFoundError().code.
    • Updated test_method_not_implemented to check for specific error code -32004.
    • Updated test_validation_error to use new method name.
    • Updated test_unhandled_exception to use new method name.
    • Modified test_task_ownership_different_user_cannot_access_task to use new method name and check for specific error code -32001.
    • Updated test_unknown_task_raises_error to use new method name and check for specific error code -32001.
    • Modified test_task_ownership_new_task_creation_via_message_send to use new method name and check data["result"]["task"]["id"].
    • Updated test_task_and_context_both_specified_single_query to use new method name.
    • Modified test_invalid_request_raises_a2a_error to use new method name.
Activity
  • This is a draft pull request, indicating it is still under active development and not yet ready for final review or merge.
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 migrates the codebase to a new version of the A2A protocol, which appears to be based on protobuf v1 instead of a previous version. The changes are extensive, touching many files to adapt to the new data types and API contracts. The core logic seems to be preserved, but refactored to work with protobuf messages. I've found a few critical issues related to incorrect handling of the new protobuf message objects, which will cause runtime errors. Overall, the migration is a significant undertaking and these fixes should help ensure its stability.

except A2AClientHTTPError as ex:
card_data = json.dumps(
agent_card.model_dump(include={"url", "additional_interfaces", "preferred_transport"}), indent=2
pick(MessageToDict, agent_card(include={"url", "additional_interfaces", "preferred_transport"})),
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 arguments to the pick function seem to be incorrect. The pick utility expects a dictionary as its first argument, but MessageToDict is being passed, which is a function. Additionally, agent_card is a protobuf message and is not callable with an include keyword argument.

The intention seems to be to convert the agent_card to a dictionary and then select specific keys. The correct implementation should be to first call MessageToDict(agent_card) and then use pick on the resulting dictionary.

Suggested change
pick(MessageToDict, agent_card(include={"url", "additional_interfaces", "preferred_transport"})),
pick(MessageToDict(agent_card, preserving_proto_field_name=True), {"url", "additional_interfaces", "preferred_transport"}),

if message.metadata and self.spec.URI in message.metadata and message.parts:
message.parts = [part for part in message.parts if not isinstance(part.root, TextPart)]
message.parts.clear()
message.parts.extend([part for part in message.parts if "text" not in part])
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 expression if "text" not in part is not a valid way to check for the presence of a field in a protobuf message. This will likely raise a TypeError. You should use the HasField() method instead.

Suggested change
message.parts.extend([part for part in message.parts if "text" not in part])
message.parts.extend([part for part in message.parts if not part.HasField("text")])

case FileWithBytes(bytes=content, name=filename, mime_type=content_type):
yield LoadedFileWithBytes(content=base64.b64decode(content), filename=filename, content_type=content_type)

elif "raw" in part: # pyrefly: ignore [not-iterable]
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 expression if "raw" in part: is not a valid way to check for the presence of a field in a protobuf message. This will likely raise a TypeError. You should use the HasField() method instead.

Suggested change
elif "raw" in part: # pyrefly: ignore [not-iterable]
elif part.HasField("raw"): # pyrefly: ignore [not-iterable]

@jezekra1 jezekra1 force-pushed the migrate-to-a2a-v1 branch 8 times, most recently from 81d7482 to fd6dcc8 Compare February 27, 2026 09:10
jezekra1 added 4 commits March 5, 2026 13:46
Signed-off-by: Radek Ježek <radek.jezek@ibm.com>
Signed-off-by: Radek Ježek <radek.jezek@ibm.com>
Signed-off-by: Radek Ježek <radek.jezek@ibm.com>
@jezekra1 jezekra1 force-pushed the migrate-to-a2a-v1 branch 5 times, most recently from 8ee9850 to 9051f33 Compare March 5, 2026 13:35
- Remove ServerError wrapper (class removed in new SDK)
- Replace A2AClientJSONRPCError with A2AClientError
- Replace A2AClientHTTPError with A2AClientError
- Replace MethodNotImplementedError with UnsupportedOperationError
- Remove ERROR_CODE_MAP usage (SDK now raises typed errors directly)
- Remove unused fastapi.responses import
@jezekra1 jezekra1 force-pushed the migrate-to-a2a-v1 branch 3 times, most recently from 2cf2742 to 0760d24 Compare March 6, 2026 09:01
- Add ignore_unknown_fields=True to ParseDict calls to handle compat
  layer fields like preferredTransport
- Rename transport methods for push notification config (v1 API change)
- Fix display_name assertion in PlatformAuthBackend when JWT has no
  name claim (falls back to sub)
- Pass call_context to TaskManager in scheduled cleanup
- Update test imports for removed a2a-sdk constants

Signed-off-by: Radek Ježek <radek.jezek@ibm.com>
@jezekra1 jezekra1 force-pushed the migrate-to-a2a-v1 branch from 0760d24 to 00c9d5c Compare March 6, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant