fix(core): strictify schemas inside tuple prefixItems - #4694
Closed
XuQuanxin04 wants to merge 1 commit into
Closed
Conversation
ensure_strict_json_schema recursed into items, anyOf, oneOf, allOf, properties, and $defs, but never into prefixItems. pydantic emits prefixItems for fixed-length tuple type hints, so a non-strict schema hidden inside a tuple element was passed through unchanged: for example a dict[str, int] parameter was rejected at the top level (its additionalProperties is a schema), but the same type wrapped in a tuple silently produced a non-strict schema that the OpenAI Structured Outputs API rejects. Recurse into each prefixItems entry exactly like array items, so tuple elements are strictified consistently. $defs are still strictified at the root, and variable-length tuples continue to use items. Co-Authored-By: Claude <noreply@anthropic.com>
seratch
requested changes
Aug 27, 2026
seratch
left a comment
Member
There was a problem hiding this comment.
The prefixItems recursion is the correct implementation direction. Please add one caller-visible regression that starts from an actual annotated function or Pydantic model, runs through function_schema(), and verifies that an object nested in a fixed tuple is strictified. The current hand-written schema tests prove the helper recursion but not the public schema-generation path that exposed the bug.
Member
|
Thanks for the focused strict-schema fix. #4696 now contains the same prefixItems traversal together with the originating fixed-tuple function-schema behavior and public-boundary regression coverage. We should merge only one source of truth for this change, so I am closing this PR as superseded by #4696. |
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.
Summary
ensure_strict_json_schemarecursed intoitems,anyOf,oneOf,allOf,properties, and$defs, but it never visitedprefixItems. pydantic emitsprefixItemsfor fixed-length tuple type hints, so a non-strict subschema hidden inside a tuple element was passed through unchanged.Concretely, a
dict[str, int]parameter is rejected at the top level because itsadditionalPropertiesis a schema rather thanfalse:But the same type wrapped in a tuple —
def f(data: tuple[dict[str, int], str])— silently produced:That schema is not valid for OpenAI Structured Outputs, so the tool/structured-output call is rejected by the API at request time.
Fix
Recurse into each
prefixItemsentry exactly like arrayitems, so tuple elements are strictified consistently.$defsare still strictified at the root, variable-length tuples (tuple[int, ...]) already useitemsand were already handled, and primitive/model tuples remain valid.Test plan
Added two tests to
tests/test_strict_schema.py:test_prefix_items_entries_are_strictified— an object entry insideprefixItemsgetsadditionalProperties: falseand arequiredlist.test_open_object_inside_prefix_items_is_rejected_like_top_level— anadditionalPropertiesschema inside a tuple element raises the sameUserErroras the top-level case.Verified directly with
function_schema:tuple[dict[str, int], str]now raises the sameUserError(before: silently non-strict).tuple[Coord, str],tuple[str, int, bool],tuple[Pt, Pt], andtuple[int, ...]all produce valid strict schemas.pytest tests/test_strict_schema.py tests/test_function_schema.py tests/test_function_tool.py— 172 passedpytest tests/models/test_openai_responses.py tests/models/test_openai_chatcompletions.py tests/models/test_openai_chatcompletions_stream.py— 317 passedruff format --checkandruff checkclean on changed files.No issue number; self-contained strict-schema correctness fix.
Checks
.agents/skills/code-change-verification/scripts/run.sh— could not run the bash script end-to-end on this Windows/Git-Bash host (POSIX process-group management viasetsid/kill -PID); I ran its constituent steps directly (ruff format, ruff check, and the relevant pytest suites above).