🔴 Required Information
Describe the Bug:
With JSON_SCHEMA_FOR_FUNC_DECL disabled, a FunctionTool whose context parameter is typed with a TYPE_CHECKING-only import fails to build its declaration:
NameError: name 'ToolContext' is not defined
This is the same pattern #6488 reported, and 2ecb3fb fixed it on the JSON-schema path. The legacy path still fails, for a different reason. build_function_declaration removes the ignored params (tool_context) from the signature, then copies all of the original __annotations__ onto the new function:
https://github.com/google/adk-python/blob/77d4dcd0/src/google/adk/tools/_automatic_function_calling_util.py#L275
from_function_with_options then calls typing.get_type_hints(new_func), which resolves every annotation, including the one for the param that was just removed.
Steps to Reproduce:
- Install google-adk 2.11.0 (or
main @ 77d4dcd).
- Save the two files below.
- Run
ADK_DISABLE_JSON_SCHEMA_FOR_FUNC_DECL=1 python repro.py.
weather_tools.py
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from google.adk.tools.tool_context import ToolContext
def get_weather(city: str, tool_context: ToolContext) -> str:
"""Returns the weather for a city."""
tool_context.state['last_city'] = city
return f'Sunny in {city}'
repro.py
from google.adk.tools.function_tool import FunctionTool
from weather_tools import get_weather
print(FunctionTool(get_weather)._get_declaration())
Expected Behavior:
The declaration builds with a single city parameter, as it does on the default JSON-schema path. tool_context is excluded from the schema, so its annotation never needs to resolve.
Observed Behavior:
File ".../google/adk/tools/_automatic_function_calling_util.py", line 350, in from_function_with_options
annotation_under_future = typing.get_type_hints(func)
...
NameError: name 'ToolContext' is not defined
An agent using this tool fails on its first model request.
Environment Details:
- ADK Library Version (pip show google-adk): 2.11.0 (
main @ 77d4dcd)
- Desktop OS: macOS 26.5
- Python Version (python -V): 3.12.13
Model Information:
- Are you using LiteLLM: No
- Which model is being used: N/A (the failure happens while building the tool declaration, before any model call)
🟡 Optional Information
Additional Context:
The fix doesn't need to catch NameError. The comment above that get_type_hints call says leaving it uncaught is deliberate, and an unresolvable annotation on a param that is declared should still raise. It's enough to copy only the kept params' annotations (and return) onto the stripped function. I have a PR ready that does that, with tests for both declaration paths. The JSON-schema-path test also pins 2ecb3fb, which has no test today (noted in #6488 (comment)).
How often has this issue occurred?:
- Always (100%) with
JSON_SCHEMA_FOR_FUNC_DECL disabled.
🔴 Required Information
Describe the Bug:
With
JSON_SCHEMA_FOR_FUNC_DECLdisabled, aFunctionToolwhose context parameter is typed with aTYPE_CHECKING-only import fails to build its declaration:This is the same pattern #6488 reported, and 2ecb3fb fixed it on the JSON-schema path. The legacy path still fails, for a different reason.
build_function_declarationremoves the ignored params (tool_context) from the signature, then copies all of the original__annotations__onto the new function:https://github.com/google/adk-python/blob/77d4dcd0/src/google/adk/tools/_automatic_function_calling_util.py#L275
from_function_with_optionsthen callstyping.get_type_hints(new_func), which resolves every annotation, including the one for the param that was just removed.Steps to Reproduce:
main@ 77d4dcd).ADK_DISABLE_JSON_SCHEMA_FOR_FUNC_DECL=1 python repro.py.weather_tools.pyrepro.pyExpected Behavior:
The declaration builds with a single
cityparameter, as it does on the default JSON-schema path.tool_contextis excluded from the schema, so its annotation never needs to resolve.Observed Behavior:
An agent using this tool fails on its first model request.
Environment Details:
main@ 77d4dcd)Model Information:
🟡 Optional Information
Additional Context:
The fix doesn't need to catch
NameError. The comment above thatget_type_hintscall says leaving it uncaught is deliberate, and an unresolvable annotation on a param that is declared should still raise. It's enough to copy only the kept params' annotations (andreturn) onto the stripped function. I have a PR ready that does that, with tests for both declaration paths. The JSON-schema-path test also pins 2ecb3fb, which has no test today (noted in #6488 (comment)).How often has this issue occurred?:
JSON_SCHEMA_FOR_FUNC_DECLdisabled.