Description
🔴 Required Information
Describe the Bug:
With LiteLlm, an LlmAgent whose output_schema is not a BaseModel class (for example list[Item], int, dict[str, int] or Literal["yes", "no"]) gets no structured output at all. _to_litellm_response_format only converts dicts and BaseModel classes or instances. For any other type it logs Unsupported response_schema type ... for LiteLLM structured outputs and returns None, so no response_format is sent and the model answers unconstrained. schema_to_json_schema in utils/_schema_utils.py already converts these types, and the native Anthropic adapter already supports them by nesting non-object roots under a response property.
Steps to Reproduce:
pip install google-adk litellm(reproduced on currentmain, bc0b418, version 2.13.0)- Run:
from typing import Literal
from pydantic import BaseModel
from google.adk.models.lite_llm import _to_litellm_response_format
from google.adk.models.llm_request import LlmRequest
class Item(BaseModel):
name: str
for schema in (list[Item], int, dict[str, int], Literal["yes", "no"], Item):
request = LlmRequest()
request.set_output_schema(schema)
print(schema, "->", _to_litellm_response_format(request.config.response_schema, model="openai/gpt-4o") is not None)Expected Behavior:
Every schema that LlmAgent.output_schema accepts produces a response_format, as Item does. For OpenAI-style strict json_schema, which requires an object root, a non-object schema would be nested as {"type": "object", "properties": {"response": <schema>}, "required": ["response"]} and unwrapped from the reply, the same way the Anthropic adapter's structured-output tool does it.
Observed Behavior:
Unsupported response_schema type <class 'types.GenericAlias'> for LiteLLM structured outputs.
...
list[__main__.Item] -> False
<class 'int'> -> False
dict[str, int] -> False
typing.Literal['yes', 'no'] -> False
<class '__main__.Item'> -> True
Environment Details:
- ADK Library Version: main @ bc0b418 (2.13.0)
- Desktop OS: macOS
- Python Version: 3.11
Model Information:
- Are you using LiteLLM: Yes
- Which model is being used: openai/gpt-4o (request building only, no API call)
🟡 Optional Information
Proposed fix (I'm working on it):
- In
_to_litellm_response_format, convert the remaining schema types withschema_to_json_schema. - For strict
json_schematargets, nest non-object roots underresponse, keeping$defsat the root, and unwrap that value in the response. Gemini models through LiteLLM keep their current path.
This is related to #7927 / #7928, whose description notes this LiteLLM gap. The change does not touch _enforce_strict_openai_schema, so it doesn't overlap #7806. Maintainers: does nesting under response (mirroring the Anthropic adapter) sound right to you?
Activity