Skip to content

feat(realtime): add typed create_response helper to RealtimeSession#3722

Open
Skyline-9 wants to merge 3 commits into
openai:mainfrom
Skyline-9:feat/realtime-create-response-helper
Open

feat(realtime): add typed create_response helper to RealtimeSession#3722
Skyline-9 wants to merge 3 commits into
openai:mainfrom
Skyline-9:feat/realtime-create-response-helper

Conversation

@Skyline-9

Copy link
Copy Markdown

Summary

Adds a typed RealtimeSession.create_response(*, instructions=None, metadata=None) helper so applications can request a model response with per-response overrides without hand-rolling a raw response.create message.

Today the only way to trigger a response with custom instructions/metadata is to send a raw protocol event through the low-level model escape hatch, which bypasses the SDK's response-create sequencing and is easy to get wrong (double response.create, "conversation already has an active response" errors). This adds a small, typed, well-sequenced entry point that mirrors the ergonomics of the rest of the realtime API (send_message, interrupt).

What changed:

  • New RealtimeSession.create_response(*, instructions, metadata) (keyword-only, appended after interrupt() so no existing API is reordered).
  • New RealtimeModelSendResponseCreate dataclass added to the RealtimeModelSendEvent union (optional fields, appended at the end of the union).
  • OpenAIRealtimeWebSocketModel.send_event routes it through the existing response-create sequencer (_reserve_response_create_request(manual=True) + _start_response_create(..., manual=True) -> wait_for_response_create_slot), so it cannot collide with an in-flight response and never emits a double response.create.
  • Only real protocol options are exposed (instructions, metadata). With no arguments it serializes to a bare response.create (no response object), via model_dump_json(exclude_unset=True).
  • Exported from agents.realtime.__init__ (__all__), consistent with RealtimeModelSendInterrupt; not added to the top-level agents namespace.
  • docs/realtime/guide.md documents that instructions/metadata are per-response overrides that do not mutate the agent.

Test plan

  • Added tests in tests/realtime/test_session.py, tests/realtime/test_openai_realtime.py, and tests/realtime/test_openai_realtime_conversions.py:
    • create_response defers while a response is active and sends exactly one response.create after the active response completes (sequencer cooperation).
    • No-arg call emits a minimal bare response.create; only-instructions omits metadata; conversion includes only provided fields.
    • Export regression test for RealtimeModelSendResponseCreate.
  • Ran the standard verification stack from the repo root:
    • make format, make lint, make typecheck — pass
    • uv run pytest -k realtime — pass (307 passed, 1 skipped)
    • make build-docs — pass

Issue number

N/A. Fits the broader direction of making the realtime API a typed first-class surface rather than requiring raw protocol messages. Happy to link a tracking issue if preferred.

Checks

  • I've added new tests, if relevant
  • I've run .agents/skills/code-change-verification/scripts/run.sh
  • I've confirmed all verification steps pass (ran make format, make lint, make typecheck, realtime tests, and make build-docs)
  • If using Codex, I've run /review before submitting this PR

Compatibility notes

Additive. Adding RealtimeModelSendResponseCreate to the RealtimeModelSendEvent union means a third-party RealtimeModel.send_event implementation gains a new union member it does not yet handle; the built-in OpenAI WebSocket/SIP models handle it. The dataclass fields are optional and appended at the end of the union, and the public method is keyword-only and appended after existing methods.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8eef197b9c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

response = (
OpenAIRealtimeResponseCreateParams(**response_params) if response_params else None
)
return OpenAIResponseCreateEvent(type="response.create", response=response)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Omit empty response payload

When session.create_response() is called without instructions or metadata, this still passes response=None into the event constructor. Pydantic treats explicitly supplied None as a set field, so _send_raw_message(...exclude_unset=True) serializes it as "response": null rather than the minimal {"type":"response.create"} payload used by the existing raw path. For no-argument response creation, that can be rejected by the Realtime schema even though the helper is documented as equivalent to an empty response.create; construct the event without the response keyword when there are no params.

Useful? React with 👍 / 👎.

Skyline-9 added 3 commits July 1, 2026 16:31
Omit the response field entirely when no per-response params are provided so the serialized payload is a bare response.create instead of {"response": null}, which the Realtime schema can reject.
@Skyline-9

Copy link
Copy Markdown
Author

@codex review

@Skyline-9 Skyline-9 force-pushed the feat/realtime-create-response-helper branch from 8eef197 to 564ac50 Compare July 1, 2026 23:31

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 564ac50d8a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

instructions: str | None = None
"""Optional instructions that override the session instructions for this response only."""

metadata: dict[str, Any] | None = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use string-valued response metadata

When a caller passes create_response(metadata={"turn": 1}) or any other non-string value, this new typed event says the value is valid and then forwards it unchanged into RealtimeResponseCreateParams; the Realtime API/OpenAI SDK schema defines response metadata as string key/value pairs, so typed callers do not get checker feedback and instead hit validation or API errors at runtime. Please match the API surface with dict[str, str] here and on the public RealtimeSession.create_response parameter.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 564ac50d8a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

instructions: str | None = None
"""Optional instructions that override the session instructions for this response only."""

metadata: dict[str, Any] | None = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Narrow response metadata values to strings

The Realtime response-create payload this is converted into expects platform metadata as dict[str, str], but the new event type permits arbitrary values. In practice session.create_response(metadata={"turn": 1}) type-checks through this API and then fails during OpenAIRealtimeResponseCreateParams conversion before any event is sent; expose dict[str, str] here and in the session helper so invalid metadata is caught at the call site.

Useful? React with 👍 / 👎.

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.

1 participant