Add Annotated[T, Field(...)] syntax for tool arguments (@function_tool)#2428
Add Annotated[T, Field(...)] syntax for tool arguments (@function_tool)#2428georg-wolflein wants to merge 4 commits intoopenai:mainfrom
Annotated[T, Field(...)] syntax for tool arguments (@function_tool)#2428Conversation
…rameters - Preserve per-parameter Annotated metadata and extract FieldInfo when building fields - Add _extract_field_info_from_metadata() helper; use it in normal-parameter branch - Merge annotated Field with docstring description and optional signature default - Add tests for required/optional constraints, string constraints, and multiple params
Document both default-based and Annotated forms for constraining and describing function-tool arguments (addresses review request in PR openai#1124).
|
|
||
| Tools let agents take actions: things like fetching data, running code, calling external APIs, and even using a computer. The SDK supports five categories: | ||
|
|
||
| - Hosted OpenAI tools: run alongside the model on OpenAI servers. |
There was a problem hiding this comment.
these may be fine, but can you apply these unrelated changes separately?
There was a problem hiding this comment.
Absolutely, removed this from the PR
docs/tools.md
Outdated
|
|
||
| The code for the schema extraction lives in [`agents.function_schema`][]. | ||
|
|
||
| ### Constraining argument values |
There was a problem hiding this comment.
Having the document change in this PR requires us to immediately release a new version when merging it. Can you create a separate PR for doc chnages?
There was a problem hiding this comment.
Makes sense. I removed the documentation changes from this PR. @haasonsaas already opened #2436 so the documentation changes can be merged in a separate PR.
|
I can’t push updates to the fork branch from here, so I opened split PRs instead per the review request to keep docs separate:
If you prefer updating this PR directly, the minimal change is to revert |
|
Thanks for the feedback @seratch. I removed the docs changes from this PR, so it should be ready to merge. @haasonsaas kindly created a separate PR (#2436) for the docs change, which can be merged at the next release. |
777aeb7 to
ec1831e
Compare
ec1831e to
556a372
Compare
|
Closing this in favor of #2435 |
Summary
This PR adds support for
Annotated[T, Field(...)]on tool parameters in addition to the existing= Field(...)syntax. The original= Field(...)support was introduced in #1124.Why add this variant?
Pydantic supports it. Pydantic allows
Fieldeither as the default (x: int = Field(ge=1)) or insideAnnotated(x: Annotated[int, Field(ge=1)]). Supporting both infunction_schemakeeps the SDK aligned with how users define constrained fields in Pydantic models.Parameter ordering in Python. A parameter like
x: int = Field(..., ge=1)still has a default value as far as Python is concerned (the default is theField(...)object). So you cannot put another parameter without a default after it — that would be a SyntaxError:With
Annotated, the constrained parameter has no default in the signature, so you can have multiple required arguments (some withFieldconstraints) in any order:Examples
Required argument with constraints:
Optional argument with default and constraints:
Multiple required arguments where one has constraints (only possible without SyntaxError using
Annotated):Implementation: we preserve per-parameter
Annotatedmetadata infunction_schema, detectFieldInfoin that metadata, and use it when building the Pydantic model and JSON schema so that constraints, defaults, and descriptions are applied the same way as for= Field(...).Test plan
Documentation: the Pydantic
Fieldfeature for tool arguments was not documented before. As requested in the PR #1124 review, a new subsection "Constraining and describing arguments with Pydantic Field" indocs/tools.mdnow documents both forms (default-based= Field(...)andAnnotated[T, Field(...)]) with example code for each.The new unit tests mirror the existing tests for the
= Field(...)format: required constraints (test_function_with_field_required_constraints→test_function_with_annotated_field_required_constraints), optional with default and constraints, string constraints (min/max length, pattern), and multiple parameters with mixed constraints. Each new test uses the same assertions (JSON schema shape, valid input round-trip, invalid input raisesValidationError) as its counterpart, so both syntaxes are covered consistently.Checks
make lintandmake format