Skip to content

LiteLlm sends no response_format for non-BaseModel output schemas (list, int, dict, Literal) #7946

Open

Description

@sumedh-aerram

🔴 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:

  1. pip install google-adk litellm (reproduced on current main, bc0b418, version 2.13.0)
  2. 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 with schema_to_json_schema.
  • For strict json_schema targets, nest non-object roots under response, keeping $defs at 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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

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