Repository navigation
fix(agents): keep Literal and Annotated output schemas - #7928
Open
sumedh-aerram wants to merge 3 commits into
Open
sumedh-aerram wants to merge 3 commits into
sumedh-aerram wants to merge 3 commits into
Conversation
…rcing to empty Schema SchemaType is types.SchemaUnion, and types.Schema validates from attributes, so typing.Literal and typing.Annotated aliases were silently coerced into an empty Schema() on LlmAgent.output_schema, BaseNode.input_schema/output_schema and RequestInput.response_schema. Wrap SchemaType with a validator that keeps these aliases unchanged. Send them to Gemini as response_json_schema, since google-genai rejects them as response_schema. Unwrap Annotated in _is_schema_type so YAML agent configs still resolve output_schema references. Fixes google#7927
Literal and Annotated output schemas now reach the model request as response_json_schema. Make the native Anthropic adapter fall back to it when response_schema is unset, so these schemas still get the structured-output tool. response_schema keeps precedence. Fixes google#7927
This was referenced Nov 2, 2026
Open
Open
…nnotated-literal-v3 # Conflicts: # src/google/adk/models/anthropic_llm.py # src/google/adk/models/llm_request.py # src/google/adk/utils/_schema_utils.py # tests/unittests/agents/test_llm_agent_fields.py # tests/unittests/models/test_llm_request.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
validate_schema; not changed here)Problem:
SchemaTypeistypes.SchemaUnion. Atyping.Literal[...]ortyping.Annotated[...]alias matches none of its alias members, andtypes.Schemasetsfrom_attributes=True. So pydantic coerces the alias into an emptytypes.Schema(), with no error. This silently drops the schema forLlmAgent.output_schema,BaseNode.input_schema,BaseNode.output_schemaandRequestInput.response_schema.Solution:
utils/_schema_utils.py:SchemaTypeis nowAnnotated[types.SchemaUnion, WrapValidator(...)]. The validator returnsLiteral/Annotatedaliases unchanged and passes every other value to the existing union validation. All four fields are fixed in one place, and the generated JSON schema of the fields is unchanged.models/llm_request.py: google-genai raisesUnsupported schema typefor these aliases inresponse_schema. Soset_output_schemanow sends them asresponse_json_schema, built with the existingschema_to_json_schema(for exampleLiteral["yes", "no"]becomes{"type": "string", "enum": ["yes", "no"]}). Every other schema type is handled as before.agents/config_agent_utils.py:_is_schema_typeunwrapsAnnotated, so that YAML agent configs still resolveoutput_schemacode references now that the field annotation is wrapped.models/anthropic_llm.py: the native Anthropic adapter falls back toresponse_json_schemawhenresponse_schemais unset, so these schemas still get its structured-output tool. Scalar schemas are wrapped as{"response": ...}as before.response_schemakeeps precedence.Testing Plan
Unit Tests:
New tests:
LlmAgent,BaseNodeandRequestInput;set_output_schemasends the aliases asresponseJsonSchemathrough google-genai's real request converter;list[M],dict,types.Schema, unions,Optional) validates and produces the same JSON schema as rawtypes.SchemaUnion;output_schemareference works;response_json_schemaforLiteralandAnnotated[Model, Field(...)].The new regression cases fail on
mainand pass with the change. The YAML cases also fail if only theconfig_agent_utils.pychange is reverted.Python 3.11, macOS:
tests/unittests/agents tests/unittests/models tests/unittests/utils tests/unittests/workflowplustests/unittests/events/test_request_input.py): 4895 passed, 1 skipped, 2 xfailed.pytest tests/unittests -n auto(first commit) (in a sandboxed runner): 22543 passed, 47 failed, 3 errors. All failures are environment-related and reproduce on unchangedmain: telemetry goldens, A2A, macOS VMaaS, and sandbox restrictions on sockets/file writes (Teams runner, Apigee streaming, samples, dotenv, CrewAI collection). Two tests were flaky under parallel load: a CLI reload test and an eval stdio test. Both pass when run individually, with and without this change.pre-commiton the changed files: clean.Manual End-to-End (E2E) Tests:
Not run against a live model. Reproduction without a model call:
Checklist
Additional context
Known limitations, kept out of scope to keep this change small:
response_schema, so for these aliases it now sends noresponse_format. That matches what it already does forintandlist[Model]output schemas, which it treats as unsupported for structured output. Onmainit sent a strictjson_schemawith an empty schema{}. Supporting them properly needs root$refinlining and non-object roots in the strict OpenAI conversion, which is a separate change.Optional[Literal[...]]andLiteral[...] | Nonewere already preserved, and google-genai accepts them asresponse_schema, so they are unchanged.output_schemais aBaseModelclass,model_dump_json()on an agent with aLiteral/Annotatedoutput schema raises a serialization error. Onmainit returned the emptySchema().validate_schemastill does not enforceLiteralvalues orFieldconstraints (validate_schema skips validation for non-BaseModel schemas (list[str], dict[…], raw JSON Schema) #7280 / fix: validate non-BaseModel schemas in validate_schema #7285).