Skip to content

Annotated parameters breaks _preprocess_args when using recursive type aliases or any unresolvable forward reference#6878

Description

@MarlzRana

馃敶 Required Information

Describe the Bug:
Annotated parameters breaks _preprocess_args when using recursive type aliases or any unresolvable forward reference on the fallback path when we are unable to get_type_hints() in src/google/adk/tools/function_tool.py, fixed by PR: #6879

Steps to Reproduce:

  1. Declare a tool containing parameter with a recursive type:
Recursive = Union[int, str, list["Recursive"]]

def fn(
    user: Annotated[UserModel, Field(description="A user")],
    data: Recursive = None,
) -> dict:
  return {"name": user.name, "type": type(user).__name__}
  1. Try and call the tool

Expected Behavior:

user is converted to a UserModel instance before the function runs (as it is on the normal path where get_type_hints() succeeds and strips the Annotated wrapper). The tool executes and returns:

{"name": "Alice", "type": "UserModel"}

Observed Behavior:

get_type_hints() raises NameError, so _preprocess_args falls back to the raw param.annotation, which is still Annotated[UserModel, ...]wrapped. None of the conversion branches recognise the wrapper, so the dict is passed through unconverted:

# tool._preprocess_args({"user": {"name": "Alice", "age": 30}})
{'user': {'name': 'Alice', 'age': 30}}   # still a dict, not a UserModel

When the tool body then accesses user.name, it raises:

Traceback (most recent call last):
  ...
  File "src/google/adk/tools/function_tool.py", line 353, in run_async
    return await self._invoke_callable(self.func, args_to_call)
  File "src/google/adk/tools/function_tool.py", line 378, in _invoke_callable
    return target(**args_to_call)
  File ".../your_tool.py", line 19, in fn
    return {"name": user.name, "type": type(user).__name__}
           ^^^^^^^^^
AttributeError: 'dict' object has no attribute 'name'

(The line numbers in function_tool.py are relative to the current main.)

Environment Details:

  • ADK Library Version: 2.7.1
  • Desktop OS: MacOS
  • Python Version: 3.13

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: gemini-3.7-flash

馃煛 Optional Information

Regression:
Not a regression.

How often has this issue occurred?:

  • Always (100%)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions