Skip to content

feat: support OpenAI Responses phase on assistant messages#5229

Merged
DouweM merged 4 commits intomainfrom
openai-phase
Apr 28, 2026
Merged

feat: support OpenAI Responses phase on assistant messages#5229
DouweM merged 4 commits intomainfrom
openai-phase

Conversation

@DouweM
Copy link
Copy Markdown
Collaborator

@DouweM DouweM commented Apr 28, 2026

  • Closes #

Summary

GPT-5.3-codex / GPT-5.4+ label assistant messages with a new phase field on the OpenAI Responses API (commentary for preambles before tool calls, final_answer for the completed answer). OpenAI recommends preserving and round-tripping it on every follow-up request — dropping it can cause preambles to be interpreted as final answers and degrade behavior in long-running or tool-heavy flows.

This PR captures phase into TextPart.provider_details['phase'] (non-streamed and streamed) and sends it back on the assistant ResponseOutputMessageParam / EasyInputMessageParam when the model profile opts in via a new OpenAIModelProfile.openai_supports_phase flag. The flag is enabled for gpt-5.3-codex, gpt-5.4*, and gpt-5.5* and defaults to False everywhere else, so unverified OpenAI-compatible APIs (vLLM, Bifrost, …) never see the field. Empirically the official OpenAI API silently ignores phase on older models (gpt-5.2, gpt-4o), so the flag is an extra guard for non-OpenAI providers rather than a hard requirement.

Test plan

  • tests/models/test_openai_responses.py::test_openai_responses_phase_live — real cassette against gpt-5.5 with a tool call, captures commentary preamble and final_answer, and (visible in the cassette) verifies pydantic-ai sends phase: commentary back to the API on the follow-up turn.
  • test_openai_responses_phase_non_streamed — non-streamed read into provider_details.
  • test_openai_responses_phase_streamed — streamed read via output_item.addedoutput_text.done.
  • test_openai_responses_phase_round_trip — supporting model preserves both commentary and final_answer on subsequent requests.
  • test_openai_responses_phase_skipped_when_profile_unsupportedgpt-5.2 (flag off) does NOT send the field even when it's in history.
  • test_openai_responses_phase_profile_flag — flag tracks the documented model list.

Checklist

  • Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
  • No breaking changes in accordance with the version policy.
  • PR title is fit for the release changelog.

GPT-5.3-codex / GPT-5.4+ label assistant messages with `phase`
(`commentary` for preambles, `final_answer` for the answer); OpenAI
recommends preserving and round-tripping it on every follow-up request to
avoid preambles being mistaken for final answers in tool-heavy flows. Capture
`phase` into `TextPart.provider_details` (non-streamed and streamed) and send
it back when `OpenAIModelProfile.openai_supports_phase` is on; default off so
unverified OpenAI-compatible APIs (vLLM, Bifrost, ...) never see the field.
@github-actions github-actions Bot added the size: M Medium PR (101-500 weighted lines) label Apr 28, 2026
@github-actions github-actions Bot added the feature New feature request, or PR implementing a feature (enhancement) label Apr 28, 2026
Comment on lines +2840 to +2842
# Track `phase` (commentary | final_answer) on assistant message items, captured
# from the `output_item.added`/`output_item.done` events and merged into the
# corresponding `TextPart.provider_details` on `output_text.done`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: this comment says phase is captured "from the output_item.added/output_item.done events" but the code only captures it from output_item.added (line 2908). The ResponseOutputItemDoneEvent handler doesn't have a branch for ResponseOutputMessage to update _phase_by_item. Consider updating to just "from the output_item.added event".

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

@DouweM DouweM merged commit 0f091cf into main Apr 28, 2026
48 checks passed
@DouweM DouweM deleted the openai-phase branch April 28, 2026 20:23
Alex-Resch pushed a commit to Alex-Resch/pydantic-ai that referenced this pull request Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature request, or PR implementing a feature (enhancement) size: M Medium PR (101-500 weighted lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant