Skip to content

fix: keep __api_exclude__ fields out of async request bodies - #3925

Open
shoutoutuoadi325 wants to merge 1 commit into
openai:mainfrom
shoutoutuoadi325:fix-async-transform-api-exclude
Open

shoutoutuoadi325 wants to merge 1 commit into
openai:mainfrom
shoutoutuoadi325:fix-async-transform-api-exclude

Conversation

@shoutoutuoadi325

Copy link
Copy Markdown
  • I understand that this repository is auto-generated and my pull request may not be merged

Changes being requested

Pass __api_exclude__ to model_dump in _async_transform_recursive, the same way _transform_recursive already does.

Models can declare client-only fields with __api_exclude__; right now ParsedResponseFunctionToolCall is the only one using it for parsed_arguments. The sync transform omits those fields when it dumps a model, the async one doesn't, so a request sent through AsyncOpenAI carries fields the API never sees from OpenAI.

The way you run into this is multi-turn structured output: with responses.parse you hand the parsed output items back in as input on the next turn. Done synchronously the function tool calls serialize to id/call_id/type/name/arguments; done with the async client, every function call in that list also ships a parsed_arguments key.

from openai._utils import transform, async_transform
from openai.types.responses import ResponseInputParam
from openai.types.responses.parsed_response import ParsedResponseFunctionToolCall

call = ParsedResponseFunctionToolCall(
    id="fc_1",
    call_id="call_1",
    type="function_call",
    name="get_weather",
    arguments='{"city": "Paris"}',
    parsed_arguments={"city": "Paris"},
)

transform([call], ResponseInputParam)
# [{'id': 'fc_1', 'call_id': 'call_1', 'type': 'function_call',
#   'name': 'get_weather', 'arguments': '{"city": "Paris"}'}]

# await async_transform([call], ResponseInputParam)
# same list, plus 'parsed_arguments': {'city': 'Paris'}

Additional context & links

Added test_pydantic_model_api_exclude to tests/test_transform.py covering the bare-model and list-of-models paths in both lanes, since __api_exclude__ had no direct test in either.

_async_transform_recursive dumps pydantic models without the exclude=
argument, so fields declared in __api_exclude__ (e.g.
ParsedResponseFunctionToolCall.parsed_arguments) leak into request
bodies sent through AsyncOpenAI while OpenAI strips them. Mirror the
model_dump call from the sync path.
Copilot AI lite review requested due to automatic review settings September 21, 2026 06:02
@shoutoutuoadi325
shoutoutuoadi325 requested a review from a team as a code owner September 21, 2026 06:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

2 participants