docs: clarify strict Zod function schemas#1988
Conversation
OkTest Summary❌ Failed for Node SDK PR #1988. SDK merge ( |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a63f7e7766
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| `zodFunction()` always creates a strict function tool, use a regular non-strict | ||
| tool and parse its arguments with Zod yourself when you need these behaviors. |
There was a problem hiding this comment.
Clarify the non-strict tool path
Because this section documents chat.completions.parse(), this recommendation can lead users to pass a regular non-strict tool back to parse(). That path calls validateInputTools before sending the request and rejects any tool whose function.strict !== true, so the documented workaround fails locally instead of letting users parse the arguments themselves. Please make explicit that this workaround requires .create()/manual tool handling or another non-auto-parsing path rather than .parse().
Useful? React with 👍 / 👎.
| Custom refinements and transforms still run when the SDK parses the response, but | ||
| some schemas that cannot be converted, including bare transforms in Zod v4, cause | ||
| the helper to throw before a request is made. | ||
| - `.default()` emits the unsupported `default` keyword, and string `.min()` or |
There was a problem hiding this comment.
This is no longer accurate for the current API. The Structured Outputs guide now documents string length constraints as unsupported only for fine-tuned models, and live calls with the exact schema generated by both Zod v3 and v4 were accepted by gpt-4.1-mini, gpt-4o-2024-08-06, and gpt-4o-mini-2024-07-18 (including default, minLength, and maxLength). The original 2024 rejection is therefore not reproducible today. Please avoid categorically labeling these keywords unsupported or recommending a non-strict tool; at minimum this needs to distinguish fine-tuned models and explain that .default() does not make the field optional because the strict conversion adds it to required. Current reference: https://developers.openai.com/api/docs/guides/structured-outputs#some-type-specific-keywords-are-not-yet-supported
jbeckwith-oai
left a comment
There was a problem hiding this comment.
I reproduced the schema generation and tested the proposed diagnosis against the current API. Both zod/v3 and zod/v4 generate strict function schemas containing default, minLength, and maxLength, with defaulted fields added to required. However, the original 2024 API rejection is no longer reproducible: live forced-tool calls using that exact generated schema succeeded on gpt-4.1-mini, gpt-4o-2024-08-06, and gpt-4o-mini-2024-07-18. I also tested default and minLength/maxLength separately on gpt-4.1-mini; all were accepted.
The current Structured Outputs guide likewise lists minLength/maxLength as unsupported only for fine-tuned models, not standard models: https://developers.openai.com/api/docs/guides/structured-outputs#some-type-specific-keywords-are-not-yet-supported. As written, this PR would tell users that a working strict schema is unsupported and direct them to give up strict tool calling. It also conflates .default() being emitted/accepted with optionality: strict conversion makes the property required, so a default generally cannot be exercised by a conforming model-generated call.
Local validation: ./node_modules/.bin/jest tests/helpers/zod.test.ts --runInBand (22/22 passed), ./node_modules/.bin/prettier --check helpers.md (passed), and git diff --check origin/main...HEAD (passed). The patch is docs-only and introduces no runtime/type ABI break, but the behavioral guidance is materially incorrect and should be revised before merge. The original issue should likely be closed as no longer reproducible, or any docs should narrowly describe fine-tuned-model limitations and default semantics.
Summary
zodFunction()always creates a strict function tool.default()and string.min()/.max()emit keywords outside the strict schema subsetWhy
The report in #1119 compared
zodFunction()with a custom helper that appeared to work. The difference is that the custom helper sends a non-strict tool, whilezodFunction()deliberately opts into strict Structured Outputs. In strict mode,default,minLength, andmaxLengthcan be rejected by the API.Impact
Users now get an actionable explanation before reaching the API error and can choose the non-strict tool path when their Zod schema depends on defaults or string length constraints. This avoids silently stripping constraints from the model-facing schema while preserving the existing strict helper behavior.
Validation
pnpm run formatpnpm run lintgit diff --checkResolves #1119