Skip to content

Conversation

Prhmma
Copy link

@Prhmma Prhmma commented Oct 16, 2025

Allow Google API toolsets to accept optional per-request headers
#3105

Testing Plan

Unit Tests

  • ✅ Added test_init_with_additional_headers in test_google_api_tool.py to verify headers are passed to RestApiTool
  • ✅ Added test_prepare_request_params_merges_default_headers in test_rest_api_tool.py to verify custom headers are merged into requests
  • ✅ Added test_prepare_request_params_preserves_existing_headers in test_rest_api_tool.py to verify critical headers (Content-Type, User-Agent) are not overridden by additional_headers
  • ✅ Updated test_init and test_get_tools in test_google_api_toolset.py to verify the parameter is properly stored and passed through

Manual Testing

Tested with Google Ads API scenario (the original use case from issue #3105):

import os
from google.adk.tools.google_api_tool import GoogleApiToolset

# Create toolset with developer-token header required by Google Ads API
google_ads_toolset = GoogleApiToolset(
    client_id=os.environ["CLIENT_ID"],
    client_secret=os.environ["CLIENT_SECRET"],
    api_name="googleads",
    api_version="v21",
    additional_headers={"developer-token": os.environ["GOOGLE_ADS_DEV_TOKEN"]}
)

# Verify headers are included in API requests
tools = await google_ads_toolset.get_tools()
# Successfully made requests with the developer-token header

Copy link

google-cla bot commented Oct 16, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link

Summary of Changes

Hello @Prhmma, 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 allows users to specify optional per-request HTTP headers for Google API toolsets and individual Google API tools. This enhancement provides greater flexibility for integrating with APIs that require custom headers for authentication, tracing, or other specific functionalities. The changes involve modifying the constructors of relevant classes to accept these headers, storing them, and ensuring they are correctly applied to all outgoing API requests, with careful consideration for merging logic to prevent unintended overwrites.

Highlights

  • GoogleApiTool Initialization: The GoogleApiTool constructor now accepts an additional_headers parameter, which is used to set default headers on the underlying _rest_api_tool instance. The authentication logic has also been refined to use an elif condition for client ID and secret.
  • GoogleApiToolset Header Support: The GoogleApiToolset now supports an additional_headers parameter in its constructor. These headers are stored and subsequently passed down to each GoogleApiTool instance created by the toolset, ensuring consistent header application across all tools within the set.
  • RestApiTool Default Headers: The RestApiTool has been enhanced with a _default_headers attribute and a set_default_headers method. The _prepare_request_params method now merges these default headers into outgoing requests, prioritizing any headers explicitly provided in the request to avoid overwriting.
  • Comprehensive Test Coverage: New unit tests have been added across test_google_api_tool.py, test_google_api_toolset.py, and test_rest_api_tool.py to validate the correct handling, merging, and preservation of additional_headers in various scenarios, ensuring the new functionality works as expected.
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

@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 effectively introduces support for additional headers in the Google API toolset, which is a valuable feature enhancement. The implementation is solid, with appropriate changes across the tool and toolset classes, and the logic for merging headers using setdefault correctly prioritizes more specific headers over the new default ones. The accompanying tests are thorough and cover the new functionality well. I have a few minor suggestions regarding type hint consistency to improve maintainability, but overall, this is a great contribution.

@boyangsvl
Copy link
Collaborator

@seanzhou1023 could you help with the review?

@boyangsvl boyangsvl requested review from xuanyang15 and removed request for seanzhou1023 October 16, 2025 18:52
@boyangsvl boyangsvl assigned xuanyang15 and unassigned seanzhou1023 Oct 16, 2025
@adk-bot adk-bot added the tools [Component] This issue is related to tools label Oct 17, 2025
@adk-bot adk-bot requested a review from seanzhou1023 October 17, 2025 00:44
@adk-bot
Copy link
Collaborator

adk-bot commented Oct 17, 2025

Response from ADK Triaging Agent

Hello @Prhmma, thank you for your contribution!

To help us review your PR, could you please add a testing plan section to your PR description? This will help reviewers understand how you have tested your changes.

Also, it looks like some of the automated checks are failing (pyink-check and test (3.9)). Could you please fix these issues?

You can find more information about our contribution guidelines here: https://github.com/google/adk-python/blob/main/CONTRIBUTING.md

Thank you!

@xuanyang15 xuanyang15 removed the request for review from seanzhou1023 October 17, 2025 00:44
@Prhmma Prhmma force-pushed the feature/google-api-toolset-additional-headers-3105 branch from 7aa5dde to d0ea308 Compare October 17, 2025 12:03
@Prhmma Prhmma force-pushed the feature/google-api-toolset-additional-headers-3105 branch from 1c4c464 to 78e4d81 Compare October 17, 2025 15:23
else operation
)
self.auth_credential, self.auth_scheme = None, None
self._default_headers: Dict[str, str] = {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since we are defining it as a private data member, probably better to move it after line 136 (the Private properties section)?


def set_default_headers(self, headers: Dict[str, str]):
"""Sets default headers that are merged into every request."""
self._default_headers = dict(headers)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need this dict cast here?

is_long_running=rest_api_tool.is_long_running,
)
self._rest_api_tool = rest_api_tool
self._rest_api_tool.set_default_headers(additional_headers or {})
Copy link
Collaborator

Choose a reason for hiding this comment

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

May be if additional_headers: self._rest_api_tool.set_default_headers(additional_headers) works better? To avoid accidentally clean up default_headers when user not set additional_headers in GoogleApiTool.

self._client_id = client_id
self._client_secret = client_secret
self._service_account = service_account
self._additional_headers = dict(additional_headers or {})
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we just do self._additional_headers = additional_headers here?

Copy link
Author

Choose a reason for hiding this comment

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

good catch, thanks, I had to change the the type mid way, and I forgot that I already changed it to dict.

@xuanyang15
Copy link
Collaborator

@Prhmma Thank you so much for creating this PR! I left some minor comments, please kindly let me know if they sound good to you!

@Prhmma
Copy link
Author

Prhmma commented Oct 20, 2025

Thanks @xuanyang15
I made some new changes based on your review.

@xuanyang15 xuanyang15 added the ready to pull [Status] This PR is ready to be importing back to Google label Oct 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready to pull [Status] This PR is ready to be importing back to Google tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants