fix: Add required parameters with defaults if missing

Merge https://github.com/google/adk-python/pull/2054

fixes https://github.com/google/adk-python/issues/2053

Co-authored-by: Xuan Yang <xygoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2054 from jeffbryner:fix-required-params dd75a0b5798792dccb1ca0ac0240ce0c0b1fad14
PiperOrigin-RevId: 830251203
This commit is contained in:
Jeff Bryner
2025-11-09 20:46:15 -08:00
committed by Copybara-Service
parent f31226ee92
commit 352dd995e1
2 changed files with 64 additions and 0 deletions
@@ -23,6 +23,7 @@ from typing import Tuple
from typing import Union
from fastapi.openapi.models import Operation
from fastapi.openapi.models import Schema
from google.genai.types import FunctionDeclaration
import requests
from typing_extensions import override
@@ -392,6 +393,17 @@ class RestApiTool(BaseTool):
# Attach parameters from auth into main parameters list
api_params, api_args = self._operation_parser.get_parameters().copy(), args
# Add any required arguments that are missing and have defaults:
for api_param in api_params:
if api_param.py_name not in api_args:
if (
api_param.required
and isinstance(api_param.param_schema, Schema)
and api_param.param_schema.default is not None
):
api_args[api_param.py_name] = api_param.param_schema.default
if auth_credential:
# Attach parameters from auth into main parameters list
auth_param, auth_args = self._prepare_auth_request_params(
@@ -262,6 +262,58 @@ class TestRestApiTool:
"message": "Needs your authorization to access your data.",
}
@patch(
"google.adk.tools.openapi_tool.openapi_spec_parser.rest_api_tool.requests.request"
)
@pytest.mark.asyncio
async def test_call_with_required_param_defaults(
self,
mock_request,
mock_tool_context,
sample_endpoint,
sample_auth_scheme,
sample_auth_credential,
):
"""Test that required parameters with defaults are auto-filled."""
mock_response = MagicMock()
mock_response.json.return_value = {"result": "success"}
mock_request.return_value = mock_response
# Create operation with required parameter that has default
mock_operation = Operation(
operationId="test_op",
parameters=[
OpenAPIParameter(**{
"name": "userId",
"in": "path",
"required": True,
"schema": OpenAPISchema(type="string", default="me"),
})
],
)
tool = RestApiTool(
name="test_tool",
description="Test Tool",
endpoint=OperationEndpoint(
base_url="https://example.com",
path="/users/{userId}/messages",
method="GET",
),
operation=mock_operation,
auth_scheme=sample_auth_scheme,
auth_credential=sample_auth_credential,
)
# Call without providing userId - should use default "me"
result = await tool.call(args={}, tool_context=mock_tool_context)
# Verify the default was applied
assert mock_request.called
call_kwargs = mock_request.call_args[1]
assert call_kwargs["url"] == "https://example.com/users/me/messages"
assert result == {"result": "success"}
def test_prepare_request_params_query_body(
self, sample_endpoint, sample_auth_credential, sample_auth_scheme
):