Skip to content

fix(openai): align text.format with tool schema to prevent empty {} args in RESPONSES_TOOLS#2304

Open
ayushh0110 wants to merge 3 commits into
567-labs:mainfrom
ayushh0110:fix/responses-tools-empty-args
Open

fix(openai): align text.format with tool schema to prevent empty {} args in RESPONSES_TOOLS#2304
ayushh0110 wants to merge 3 commits into
567-labs:mainfrom
ayushh0110:fix/responses-tools-empty-args

Conversation

@ayushh0110
Copy link
Copy Markdown
Contributor

Summary

Fixes #2300

When RESPONSES_TOOLS mode forces a tool call alongside a mismatched text.format json_schema, the model receives competing output constraints and may deprioritize tool arguments to '{}'. This is especially common with low-reasoning models (e.g. gpt-5-nano).

Per OpenAI's Responses API migration guide §6, text.format is the Responses API equivalent of response_format for structured outputs. Rather than stripping the text config, this PR aligns text.format with the tool schema so both output paths use the same json_schema, giving the model a single consistent signal.

Changes

instructor/providers/openai/utils.py

  • Added _ensure_text_format_config() — Sets text.format to a json_schema matching the tool definition's parameters schema (from pydantic_function_tool). If a user provides a matching text config, it's preserved; if conflicting, it's overridden with a debug log.
  • Updated handle_responses_tools() — Calls _ensure_text_format_config() after building the tool definition to align both output paths.
  • Updated handle_responses_tools_with_inbuilt_tools() — Same treatment for consistency.
  • Improved reask_responses_tools() — Detects empty '{}' arguments and sends a targeted retry message ("You MUST populate ALL required fields") instead of the generic "fix the errors with {}".

instructor/processing/function_calls.py

  • Added diagnostic logging in parse_responses_tools() — Logs a WARNING when tool arguments are empty, helping users identify text.format/tool_choice conflicts or insufficient reasoning budget.

tests/test_openai_responses_tools.py

Added 8 unit tests covering:

  • text.format is auto-set with correct json_schema (including additionalProperties: false)
  • Conflicting user-provided text.format is overridden
  • Matching user-provided text.format is preserved
  • response_model=None doesn't crash or set text config
  • Inbuilt tools handler also sets text.format
  • Empty-args retry uses targeted message
  • Non-empty-args retry uses standard message

Why parameters_schema instead of model_json_schema()?

OpenAI's strict mode requires additionalProperties: false in the schema. Pydantic's model_json_schema() doesn't include this, but pydantic_function_tool() does. By reusing the tool's parameters schema, both text.format and the tool definition share the exact same schema — correctly formatted for strict mode.

Test Results

151 passed, 5 skipped, 0 failures

ayushh0110 added 3 commits May 6, 2026 08:06
When using Mode.RESPONSES_TOOLS with create_partial streaming, the OpenAI
Responses API emits ResponseReasoningSummaryTextDeltaEvent and
ResponseReasoningSummaryTextDoneEvent events that were silently dropped.

Add an on_event callback parameter that forwards these non-JSON events to
the caller instead of discarding them. The callback is threaded through
the full pipeline: patch -> retry -> process_response -> extract_json.

- Support both sync and async callbacks in the async streaming path
- Pop on_event from kwargs early to prevent it leaking to the OpenAI API
- Add 7 unit tests (no API key required) with zero regressions

Closes 567-labs#2291
…rgs in RESPONSES_TOOLS

When RESPONSES_TOOLS mode forces a tool call alongside a mismatched
text.format json_schema, the model receives competing output constraints
and may deprioritize tool arguments to '{}'. This is especially common
with low-reasoning models like gpt-5-nano.

Changes:
- Add _ensure_text_format_config() that sets text.format to a json_schema
  matching the tool definition's parameters schema (from pydantic_function_tool),
  aligning both output paths per OpenAI's Responses API migration guide.
- Apply to both handle_responses_tools and handle_responses_tools_with_inbuilt_tools.
- Add targeted retry message in reask_responses_tools when empty arguments
  are detected, explicitly instructing the model to populate required fields.
- Add diagnostic logger.warning in parse_responses_tools when empty tool
  arguments are returned.

Closes 567-labs#2300
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Responses API migration pain: RESPONSES_TOOLS can ignore structured text format and return empty {} tool args

1 participant