Skip to content

SetModelResponseTool crashes with TypeError when output_schema is a raw dict #5469

@harche

Description

@harche

Bug Description

When passing a raw dict schema as output_schema to an LlmAgent, the SetModelResponseTool crashes with TypeError: unhashable type: 'dict' during function declaration generation.

Steps to Reproduce

from google.adk.agents import Agent

agent = Agent(
    name="test",
    model="gemini-2.5-flash",
    instruction="You are a helpful agent.",
    output_schema={"type": "object", "properties": {"result": {"type": "string"}}},
)

Running a query with this agent produces:

TypeError: unhashable type: 'dict'

Root Cause

In src/google/adk/tools/set_model_response_tool.py, the else branch (lines 90-99) handles non-BaseModel, non-list schemas by setting annotation=output_schema — i.e., the dict instance itself:

else:
    params = [
        inspect.Parameter(
            'response',
            inspect.Parameter.KEYWORD_ONLY,
            annotation=output_schema,  # <-- dict INSTANCE, e.g. {"type": "object", ...}
        )
    ]

Later, in _function_parameter_parse_util.py line 140, _is_builtin_primitive_or_compound does:

return annotation in _py_builtin_type_to_schema_type.keys()

This calls __hash__ on the annotation, but dict instances aren't hashable, so it raises TypeError.

Expected Behavior

Raw dict schemas should work — SchemaType = types.SchemaUnion explicitly includes dict[Any, Any], and _schema_utils.py documents support for "Raw dict schemas".

Suggested Fix

Add an isinstance(output_schema, dict) branch in SetModelResponseTool.__init__ before the else fallthrough:

elif isinstance(output_schema, dict):
    params = [
        inspect.Parameter(
            'response',
            inspect.Parameter.KEYWORD_ONLY,
            annotation=dict,  # the TYPE, not the instance
        )
    ]

This way _is_builtin_primitive_or_compound sees dict (the type, which is hashable and already mapped to types.Type.OBJECT in _py_builtin_type_to_schema_type).

Full Stack Trace

File "google/adk/flows/llm_flows/_output_schema_processor.py", line 54, in run_async
    llm_request.append_tools([set_response_tool])
File "google/adk/models/llm_request.py", line 256, in append_tools
    declaration = tool._get_declaration()
File "google/adk/tools/set_model_response_tool.py", line 116, in _get_declaration
    build_function_declaration(
File "google/adk/tools/_automatic_function_calling_util.py", line 259, in build_function_declaration
    from_function_with_options(func, variant)
File "google/adk/tools/_automatic_function_calling_util.py", line 340, in from_function_with_options
    schema = _function_parameter_parse_util._parse_schema_from_parameter(
File "google/adk/tools/_function_parameter_parse_util.py", line 227, in _parse_schema_from_parameter
    if _is_builtin_primitive_or_compound(param.annotation):
File "google/adk/tools/_function_parameter_parse_util.py", line 140, in _is_builtin_primitive_or_compound
    return annotation in _py_builtin_type_to_schema_type.keys()
TypeError: unhashable type: 'dict'

Environment

  • google-adk version: 1.31.1
  • Python: 3.12

Metadata

Metadata

Assignees

Labels

tools[Component] This issue is related to tools

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions