From 7fe60641e37d184d0646b07e6757dbd28eec2d5d Mon Sep 17 00:00:00 2001 From: rcsantana777 Date: Fri, 22 Aug 2025 09:10:37 -0700 Subject: [PATCH] feat: Add custom User-Agent header to RestApiTool requests Merge https://github.com/google/adk-python/pull/2641 This PR adds a custom `User-Agent` header to all requests made via `RestApiTool`. This allows backend services to identify traffic originating from the ADK. The header format is `google-adk/ (tool: )`, where `` is the current version of the `google-adk` package, fetched dynamically from `google.adk.version`, and `` is the name of the specific `RestApiTool` instance. **Associated Issue** Fixes #2676 **Testing Plan** **Unit Tests** I ran the full suite of unit tests locally to ensure the changes did not introduce any regressions. All tests passed successfully. ```bash $ pytest ./tests/unittests ================================= 4202 passed, 2459 warnings in 44.68s ==================== ``` The warnings are related to existing experimental features and are not affected by this change. **Manual End-to-End (E2E) Test** I performed a manual test to ensure the integrated flow works as expected. * **Setup:** Created a clean virtual environment (`~/venvs/adk-e2e-test`) and installed the locally built `google-adk` package using `uv venv --seed` and `pip install dist/google_adk-*.whl`. Ran a custom `mock_server.py` script (using Flask) in one terminal to listen for requests and print headers. Ran a custom `run_test_tool.py` script in a second terminal to send a request using the modified `RestApiTool`. * **Execution:** The `run_test_tool.py` script successfully sent a POST request to the mock server's `/test` endpoint. The mock server received the request and printed the headers. **`run_test_tool.py` Output:** ```json { "message": "Request received successfully!" } ``` **`mock_server.py` Output (Headers):** ```text --- Request Received --- Headers: Host: 127.0.0.1:8000 User-Agent: google-adk/1.12.0 (tool: TestTool) Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive Content-Type: application/json Content-Length: 2 ------------------------ ``` The `User-Agent: google-adk/1.12.0 (tool: TestTool)` header confirms the change is working as intended, dynamically fetching the package version and including the tool name. **Checklist** * [x] Associated issue linked * [x] Unit tests passed * [x] End-to-end test performed and results documented * [x] Code formatted with `./autoformat.sh` --- COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2641 from rcsantana777:feat/add-user-agent a9a9375306c18bb7ba501276cbf76693e70a87ad PiperOrigin-RevId: 798232385 --- .../openapi_tool/openapi_spec_parser/rest_api_tool.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py b/src/google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py index 0df9461b..2c02d555 100644 --- a/src/google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +++ b/src/google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py @@ -245,6 +245,7 @@ class RestApiTool(BaseTool): Example: self._prepare_request_params({"input_id": "test-id"}) """ + method = self.endpoint.method.lower() if not method: raise ValueError("Operation method not found.") @@ -254,6 +255,12 @@ class RestApiTool(BaseTool): header_params: Dict[str, Any] = {} cookie_params: Dict[str, Any] = {} + from ....version import __version__ as adk_version + + # Set the custom User-Agent header + user_agent = f"google-adk/{adk_version} (tool: {self.name})" + header_params["User-Agent"] = user_agent + params_map: Dict[str, ApiParameter] = {p.py_name: p for p in parameters} # Fill in path, query, header and cookie parameters to the request