Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add structured output with tools support for models with limited structured output#2071

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
devv-shayan wants to merge2 commits intoopenai:main
base:main
Choose a base branch
Loading
fromdevv-shayan:feat/structured-output-with-tools

Conversation

@devv-shayan
Copy link

Add structured output with tools support for models with limited structured output

Summary

Adds an opt-in structured output with tools feature to enable using tools and structured outputs simultaneously on models that don't natively support both (specifically Google Gemini via LiteLLM).

Problem: Models like Gemini returnBadRequestError: Function calling with a response mime type 'application/json' is unsupported when trying to use tools with structured outputs (viaresponse_schema).

Solution: Newenable_structured_output_with_tools parameter on theAgent class that:

  • Injects JSON formatting instructions into the system prompt
  • Disables nativeresponse_format to avoid API errors
  • Parses the model's JSON response into the specified Pydantic model
  • Defaults toFalse for backward compatibility
  • Only actively used byLitellmModel (OpenAI models ignore it as they have native support)

Test plan

Unit tests (13 tests added):

  • tests/utils/test_prompts.py - Tests for prompt generation and injection logic
    • Validates JSON schema extraction from Pydantic models
    • Tests conditional injection based on tools/output_schema presence
    • Verifies opt-in behavior (only injects when explicitly enabled)

Integration test:

  • tests/test_gemini_local.py - Manual test script for Gemini (requires API key)
    • Tests actual Gemini integration with tools + structured output
    • Verifies structured output with tools works end-to-end

Verification performed:

make lint# ✅ All checks passedmake format# ✅ 359 files formatted correctlymake mypy# ✅ No type errorsmake tests# ✅ 995 passed, 3 skipped, 20 failed*

*20 failures are pre-existing Windows-specific SQLite file locking issues in temporary directory cleanup (not related to this PR). All 13 new tests pass.

Test coverage:

  • Updated all existing test mock models to acceptenable_structured_output_with_tools parameter
  • Verified backward compatibility (parameter is optional with defaultFalse)
  • Tested with and without the feature enabled
  • Validated structured output parsing with nested Pydantic models

Issue number

#2032

Checks

  • I've added new tests (if relevant)
  • I've added/updated the relevant documentation
  • I've runmake lint andmake format
  • I've made sure tests pass

Documentation

Added comprehensive documentation:

  • docs/models/structured_output_with_tools.md - Complete guide with examples
    • Problem explanation with error messages
    • Step-by-step solution with code examples
    • "When to Use" table for different model providers
    • Debugging tips and best practices
  • docs/agents.md - Added section on using structured outputs with tools
  • docs/models/litellm.md - Added example for Gemini integration
  • mkdocs.yml - Added new doc page to navigation

Files Changed

Source code:

  • src/agents/agent.py - Addedenable_structured_output_with_tools parameter
  • src/agents/util/_prompts.py - New utility for JSON prompt generation
  • src/agents/models/interface.py - Added parameter toModel interface
  • src/agents/models/openai_chatcompletions.py - Pass-through (ignores parameter)
  • src/agents/models/openai_responses.py - Pass-through (ignores parameter)
  • src/agents/extensions/models/litellm_model.py - Active implementation
  • src/agents/run.py - Passes parameter to model calls

Tests:

  • tests/utils/test_prompts.py - 13 new unit tests
  • tests/test_gemini_local.py - Integration test
  • Updated 5 test mock models to match new interface

Documentation:

  • docs/models/structured_output_with_tools.md - New comprehensive guide
  • docs/agents.md - Added usage section
  • docs/models/litellm.md - Added Gemini example
  • mkdocs.yml - Updated navigation

Implementation Details

Design decisions:

  1. Opt-in by default -enable_structured_output_with_tools=False ensures no impact on existing code
  2. LiteLLM-focused - OnlyLitellmModel actively uses this; OpenAI models ignore it
  3. Interface consistency - All models accept the parameter for uniform signatures
  4. User control - Users explicitly enable based on their model's requirements

How it works:

  1. User setsenable_structured_output_with_tools=True on Agent
  2. LitellmModel checks if both tools and output_schema are present
  3. If yes, generates JSON instructions from Pydantic model schema
  4. Injects instructions into system prompt
  5. Disablesresponse_format to avoid API errors
  6. Model returns JSON in text response
  7. SDK parses and validates against Pydantic model

Example Usage

fromagentsimportAgent,function_toolfromagents.extensions.models.litellm_modelimportLitellmModelfrompydanticimportBaseModel,FieldclassWeatherReport(BaseModel):city:str=Field(description="City name")temperature:float=Field(description="Temperature in Celsius")@function_tooldefget_weather(city:str)->dict:return {"city":city,"temperature":22.5}# This now works with Gemini!agent=Agent(name="WeatherBot",model=LitellmModel("gemini/gemini-1.5-flash"),tools=[get_weather],output_type=WeatherReport,enable_structured_output_with_tools=True,# Required for Gemini)

Backward Compatibility

Fully backward compatible - All changes are additive:

  • New parameter has default value (False)
  • Existing code works without modification
  • OpenAI models ignore the parameter (use native support)
  • Only affects users who explicitly enable it

support for tools on limited models (e.g., Gemini)Enable using tools and structured outputs together on models (e.g., Gemini) that don't nativelysupport both simultaneously. Introduce an opt-in parameter enable_structured_output_with_toolsto the Agent class, which injects JSON formatting instructions into the system prompt forLitellmModel as a workaround.Changes:- Add enable_structured_output_with_tools parameter to Agent (default: False)- Implement prompt injection utilities in src/agents/util/_prompts.py- Update LitellmModel to inject JSON instructions when enabled- Extend model interfaces to accept enable_structured_output_with_tools- Add comprehensive unit tests (13 total) and one integration test- Add documentation in docs/models/structured_output_with_tools.md- Update docs/agents.md and docs/models/litellm.md with usage examples
Copy link

@chatgpt-codex-connectorchatgpt-codex-connectorbot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When yousign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@devv-shayandevv-shayan changed the titlefeat(agent): add structured outputAdd structured output with tools support for models with limited structured outputNov 10, 2025
 when enabledMaintain backward compatibility with third-party Model implementations byonly passing the enable_structured_output_with_tools parameter when it'sexplicitly enabled (True). This prevents TypeErrors in custom Model classesthat don't support the new parameter yet.- Built-in models have default False, so they work either way- Third-party models without the parameter won't crash- Feature still works when explicitly enabledFixes backward compatibility issue raised in code review.
@seratch
Copy link
Member

@devv-shayan Thanks for looking into this. However, as I mentioned at#2032 (comment), we prefer resolving this only by the changes on the LiteLLM or our LiteLLM adapter side. So, we don't accept this large diff for this.

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

Reviewers

@chatgpt-codex-connectorchatgpt-codex-connector[bot]chatgpt-codex-connector[bot] left review comments

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

2 participants

@devv-shayan@seratch

[8]ページ先頭

©2009-2025 Movatter.jp