Skip to content

Conversation

@mikeas1
Copy link
Contributor

@mikeas1 mikeas1 commented Jul 21, 2025

Description

This adds PR adds support for reading requested extensions from a client, via the X-A2A-Extensions header, and plumbing that through the ServerCallContext.

Here's my rough thinking on the design choices:

  1. Requests to activate extensions are specified in a transport-specific manner. For HTTP, it's using headers. For gRPC, it's using side-channel metadata (which are also HTTP headers).
  2. However, indicating that an extension was requested is a transport-independent concept. So, it should be passed to the transport-independent layers of the SDK.
  3. We already have a means of extracting relevant information from the transport layer (and others) and passing down to the independent layers: the ServerCallContext.
  4. So, we can put the list of requested extensions here. The transport layers are responsible for pulling out the list of requested extensions in whatever transport specific means they are communicated, and passing these down via the ServerCallContext.
  5. Returning the list of extensions that were activated is slightly more annoying. I didn't want to have to refactor every layer to plumb both the request-specific response type (such as SendMessageResponse) AND the list of extensions activated. That's just too intrusive.
  6. So, I need some way to communicate the list of activated extension from the independent layers back "up" to the transport layers via something other than the return value. I'm not thrilled with the decision here, but the answer is to use interior mutability: I put a mutable set in the ServerCallContext, and allow lower levels to modify it to add the activated extensions.
  7. The transport layers then need to read the list of activated extensions from the ServerCallContext and pass those back in the response in the transport-defined method.

The result is that we have full stack plumbing of requested and activated extensions by way of the ServerCallContext.

mikeas1 added 2 commits July 21, 2025 19:13
This commit adds support for extracting extensions requested by a
client, and marking an extension as activated, which causes it to be
returned to clients in a header.

This is purely plumbing, no particular support for actually using
extensions.
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.

Summary of Changes

Hello @mikeas1, 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 new feature that enables the server-side plumbing of client-requested and server-activated extensions. It establishes a standardized mechanism, primarily leveraging the ServerCallContext, to communicate extension identifiers throughout the request-response lifecycle, supporting both HTTP (JSON-RPC) and gRPC transports. This change allows agents to dynamically understand and respond to client-specific extension requirements.

Highlights

  • Core Extension Plumbing: Introduced requested_extensions and activated_extensions sets to the ServerCallContext to serve as the central, transport-agnostic mechanism for managing extension identifiers throughout the request-response lifecycle.
  • HTTP (JSON-RPC) Transport Integration: Modified the JSON-RPC application to read client-requested extensions from the X-A2A-Extensions HTTP header in incoming requests and to write server-activated extensions back into the same header in outgoing responses.
  • gRPC Transport Integration: Updated the gRPC handler to extract requested extensions from gRPC invocation metadata and to set activated extensions as trailing metadata in gRPC responses, ensuring consistent behavior across transports.
  • Extension Management Utilities: Added a new common module for extensions, including a utility function find_extension_by_uri to facilitate locating specific extensions within an AgentCard.
  • RequestContext Enhancement: Enhanced the RequestContext with new methods to access requested extensions and to add activated extensions, providing a convenient interface for downstream handlers to interact with extension data.
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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 or fill out our survey to provide feedback.

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 introduces server-side support for plumbing requested and activated extensions via the ServerCallContext, a valuable feature for extensibility. The changes span both HTTP/JSON-RPC and gRPC transport layers. The overall design is well-thought-out. My review has identified a critical issue regarding the use of mutable default arguments in a Pydantic model, which could lead to state being shared across requests. I've also noted a high-severity issue with header parsing logic that could fail in some cases, and a medium-severity issue with potentially flaky tests. Addressing these points will significantly improve the robustness and correctness of this new feature.

mikeas1 and others added 3 commits July 21, 2025 19:29
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@mikeas1
Copy link
Contributor Author

mikeas1 commented Jul 21, 2025

/gemini review

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 introduces server-side support for requested and activated extensions, plumbing them through the ServerCallContext. The implementation correctly handles this for both JSON-RPC and gRPC transports. The changes are well-structured and include corresponding tests. I've identified one issue in the gRPC metadata parsing that could lead to incorrect behavior with comma-separated extension values, and I've also suggested improvements to the gRPC tests to cover this parsing logic.

@mikeas1
Copy link
Contributor Author

mikeas1 commented Jul 21, 2025

/gemini review

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 introduces server-side support for handling requested and activated extensions, plumbing the information through the ServerCallContext. The implementation is clean and well-tested across both JSON-RPC and gRPC transports. My feedback focuses on improving code maintainability by reducing duplication and ensuring deterministic behavior by sorting extension lists before they are sent in responses.

@mikeas1
Copy link
Contributor Author

mikeas1 commented Jul 21, 2025

/gemini review

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 introduces server-side support for plumbing requested and activated extensions using the ServerCallContext. The implementation is consistent across JSON-RPC and gRPC, with comprehensive tests. The use of interior mutability for activated extensions is a pragmatic choice. Minor suggestions have been offered to improve code style and robustness.

@mikeas1 mikeas1 marked this pull request as ready for review July 21, 2025 21:08
@kthota-g kthota-g self-assigned this Jul 22, 2025
@kthota-g kthota-g self-requested a review July 22, 2025 16:38
@mikeas1 mikeas1 requested a review from a team as a code owner July 22, 2025 19:27
@mikeas1 mikeas1 enabled auto-merge (squash) July 22, 2025 19:27
@mikeas1 mikeas1 merged commit 4d5b92c into a2aproject:main Jul 22, 2025
5 checks passed
holtskinner pushed a commit that referenced this pull request Jul 31, 2025
🤖 I have created a release *beep* *boop*
---


##
[0.3.0](v0.2.16...v0.3.0)
(2025-07-31)


### ⚠ BREAKING CHANGES

* **deps:** Make opentelemetry an optional dependency
([#369](#369))
* **spec:** Update Agent Card Well-Known Path to
`/.well-known/agent-card.json`
([#320](#320))
* Remove custom `__getattr__` and `__setattr__` for `camelCase` fields
in `types.py`
([#335](#335))
* Add mTLS to SecuritySchemes, add oauth2 metadata url field, allow
Skills to specify Security
([#362](#362))
* Support for serving agent card at deprecated path
([#352](#352))

### Features

* Add `metadata` as parameter to `TaskUpdater.update_status()`
([#371](#371))
([9444ed6](9444ed6))
* Add mTLS to SecuritySchemes, add oauth2 metadata url field, allow
Skills to specify Security
([#362](#362))
([be6c517](be6c517))
* Add RESTful API Serving
([#348](#348))
([82a6b7c](82a6b7c))
* Add server-side support for plumbing requested and activated
extensions ([#333](#333))
([4d5b92c](4d5b92c))
* Allow agent cards (default and extended) to be dynamic
([#365](#365))
([ee92aab](ee92aab))
* Support for serving agent card at deprecated path
([#352](#352))
([2444034](2444034))
* support non-blocking `sendMessage`
([#349](#349))
([70b4999](70b4999))
* Type update to support fetching extended card
([#361](#361))
([83304bb](83304bb))


### Bug Fixes

* Add Input Validation for Task Context IDs in new_task Function
([#340](#340))
([a7ed7ef](a7ed7ef))
* **deps:** Reduce FastAPI library required version to `0.95.0`
([#372](#372))
([a319334](a319334))
* Remove `DeprecationWarning` for regular properties
([#345](#345))
([2806f3e](2806f3e))
* **spec:** Add `SendMessageRequest.request` `json_name` mapping to
`message` proto
([bc97cba](bc97cba))
* **spec:** Add Transport enum to specification
(a2aproject/A2A#909)
([d9e463c](d9e463c))


### Documentation

* Address typos in docstrings and docs.
([#370](#370))
([ee48d68](ee48d68))


### Miscellaneous Chores

* Add support for authenticated extended card method
([#356](#356))
([b567e80](b567e80))


### Code Refactoring

* **deps:** Make opentelemetry an optional dependency
([#369](#369))
([9ad8b96](9ad8b96))
* Remove custom `__getattr__` and `__setattr__` for `camelCase` fields
in `types.py`
([#335](#335))
([cd94167](cd94167))
* **spec:** Update Agent Card Well-Known Path to
`/.well-known/agent-card.json`
([#320](#320))
([270ea9b](270ea9b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
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