Skip to content

Python: make Gemini honor declarative outputSchema, not just JSON mode#5893

Open
cooleryu wants to merge 1 commit into
microsoft:mainfrom
cooleryu:fix-gemini-output-schema-5888
Open

Python: make Gemini honor declarative outputSchema, not just JSON mode#5893
cooleryu wants to merge 1 commit into
microsoft:mainfrom
cooleryu:fix-gemini-output-schema-5888

Conversation

@cooleryu
Copy link
Copy Markdown

Summary

Fixes the Gemini structured-output path so declarative outputSchema is forwarded as an actual Gemini response_schema, not only as response_mime_type="application/json".

Motivation

Issue #5888 shows a subtle but important failure mode:

  • declarative agents correctly translate YAML outputSchema into response_format
  • the Gemini client sees response_format and switches the request into JSON mode
  • but the raw JSON schema mapping is not passed to Gemini as response_schema

That means Gemini is asked for JSON, but not constrained by the schema the agent author wrote. In practice, the model can return arbitrary JSON that satisfies neither the requested task nor the declarative schema.

Changes

  • Extract Gemini-compatible schemas from supported mapping-shaped response_format values:
    • raw JSON schema mappings
    • json_schema envelopes
    • format envelopes
    • direct schema mappings
  • Keep explicit response_schema as the highest-priority Gemini-specific option.
  • Avoid treating JSON mode envelopes such as {"type": "json_object"} as schemas.
  • Document that Gemini structured output supports Pydantic response_format, JSON schema response_format, and Gemini-specific response_schema.

Test Plan

Ran:

uv run --frozen --package agent-framework-gemini pytest packages/gemini/tests/test_gemini_client.py -q
uv run --frozen --package agent-framework-declarative pytest packages/declarative/tests/test_declarative_loader.py -k "outputSchema or response_format" -q
uv run --frozen --package agent-framework-gemini ruff check packages/gemini/agent_framework_gemini/_chat_client.py packages/gemini/tests/test_gemini_client.py
uv run --frozen --package agent-framework-gemini ruff format --check packages/gemini/agent_framework_gemini/_chat_client.py packages/gemini/tests/test_gemini_client.py
uv run --frozen --package agent-framework-gemini mypy --config-file packages/gemini/pyproject.toml packages/gemini/agent_framework_gemini
git diff --check

The new tests cover:

  • raw declarative-style JSON schema mappings
  • the Agent(default_options={"response_format": ...}) path used by declarative agents
  • nested schemas with arrays and additionalProperties
  • json_schema, format, and direct schema envelopes
  • anyOf, union type arrays, and empty schemas
  • tools plus structured output
  • streaming plus structured output
  • final response.value parsing for mapping response formats
  • negative cases where JSON mode should not be mistaken for a schema

Risk

The change is intentionally scoped to request config preparation for Gemini structured output.

Existing behavior is preserved for:

  • Pydantic model response_format
  • explicit Gemini response_schema
  • JSON mode without a schema
  • tool calling
  • streaming

The main behavioral change is that mapping-shaped schemas already accepted by the framework are now actually forwarded to Gemini.

Related Issue

Fixes #5888

Maintainer Context

This keeps the declarative-agent contract intact across the provider boundary:

outputSchema -> response_format -> Gemini response_schema

Without this, declarative schemas silently degrade into plain JSON mode for Gemini. The patch keeps the adapter behavior narrow, adds negative tests to avoid over-eager schema detection, and covers the tool/streaming paths where this kind of regression can be easy to miss.

Copilot AI review requested due to automatic review settings May 15, 2026 12:58
@moonbox3 moonbox3 added documentation Improvements or additions to documentation python labels May 15, 2026
@cooleryu cooleryu marked this pull request as ready for review May 15, 2026 12:59
@cooleryu
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Gemini structured output handling so declarative outputSchema (propagated as response_format) is forwarded to Gemini as an actual response_schema, not just enabling JSON mode via response_mime_type="application/json". This keeps declarative agents’ schema contracts intact across the provider adapter boundary.

Changes:

  • Add schema extraction for mapping-shaped response_format values (raw JSON Schema mappings and supported envelope shapes) and forward them as Gemini response_schema.
  • Preserve precedence for explicit Gemini response_schema over any schema inferred from response_format.
  • Expand Gemini client tests and provider README documentation to cover these structured-output behaviors (including streaming/tools and negative cases).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
python/packages/gemini/agent_framework_gemini/_chat_client.py Extracts/forwards JSON schemas from mapping response_format and correctly applies precedence/JSON mode behavior.
python/packages/gemini/tests/test_gemini_client.py Adds coverage ensuring schemas are forwarded and final parsed value works for mapping formats across non-streaming/streaming/tools.
python/packages/gemini/README.md Documents supported structured-output configuration options for Gemini (response_format and response_schema).

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

Labels

documentation Improvements or additions to documentation python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: Declarative agent: Adding outputSchema to agent YAML produces incorrect output

3 participants