Skip to content

Tolerate OpenAI model schema drift in the agents payload converter#1563

Merged
brianstrauch merged 5 commits into
mainfrom
openai-lenient-converter
May 28, 2026
Merged

Tolerate OpenAI model schema drift in the agents payload converter#1563
brianstrauch merged 5 commits into
mainfrom
openai-lenient-converter

Conversation

@brianstrauch
Copy link
Copy Markdown
Member

What

The OpenAI agents integration deserializes ModelResponse across the activity boundary with strict pydantic validation. OpenAI's SDK response models can drift from what the live API actually returns — e.g. the web search search action no longer includes the deprecated-but-required ActionSearch.query field, sending only the newer plural queries. The SDK tolerates this when parsing responses (it builds models leniently), but strict TypeAdapter.validate_json on the workflow side does not, so any workflow using WebSearchTool fails with:

RuntimeError: Failed decoding arguments
  ... 98 validation errors for ModelResponse
  output.0.ResponseFunctionWebSearch.action.ActionSearch.query
    Field required [type=missing, ...]

This breaks the workflow durably (the activity result can never be decoded), and affects both directions — model output (ModelResponse) and the items fed back as model input (ActivityModelInput).

Fix

Add a lenient fallback to the OpenAI agents payload converter: try strict pydantic validation first and, only on ValidationError, rebuild via OpenAI's own construct_type (the same lenient builder the openai/openai-agents SDKs use), handling the agents dataclass wrapper around the OpenAI response types. The happy path is unchanged, and the fallback retires on its own once the field requiredness is fixed upstream (see openai/openai-python#3328).

Testing

  • Updated the research mock to emit the web-search action with queries (no query), matching the current API, so test_research_workflow[use_local_model=True] exercises the fallback without a live key.
  • Verified test_research_workflow[use_local_model=False] (live API) passes with the fix.

🤖 Generated with Claude Code

The OpenAI SDK response models can drift from live API payloads (e.g. a
deprecated-but-required field the API has stopped sending, such as
ActionSearch.query on web_search_call results). The SDK tolerates this
when parsing responses, but strict TypeAdapter.validate_json on the
workflow side does not, which breaks deserializing ModelResponse across
the activity boundary.

Add a lenient fallback to the OpenAI agents payload converter: try strict
pydantic validation first and, only on ValidationError, rebuild via
OpenAI's own construct_type (handling the agents dataclass wrapper). The
happy path is unchanged; the fallback retires once upstream fixes the
field requiredness.
Mirror the current OpenAI API, which returns the search action with the
plural `queries` and omits the deprecated singular `query`. Built via
model_construct so the required-but-unset `query` is excluded on
serialization, exercising the lenient converter fallback in the
use_local_model path without needing a live API key.
@brianstrauch brianstrauch requested review from a team as code owners May 28, 2026 20:08
Comment thread temporalio/contrib/openai_agents/_temporal_openai_agents.py Outdated
Build the converter tuple directly instead of mutating self.converters
after super().__init__().
@brianstrauch brianstrauch enabled auto-merge (squash) May 28, 2026 22:17
@brianstrauch brianstrauch merged commit 28243b9 into main May 28, 2026
26 of 27 checks passed
@brianstrauch brianstrauch deleted the openai-lenient-converter branch May 28, 2026 23:15
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