Skip to content

fix: enforce realtime text guardrails and synchronize streaming cancellation#3933

Open
seratch wants to merge 1 commit into
mainfrom
fix/realtime-guardrails-and-stream-cancellation
Open

fix: enforce realtime text guardrails and synchronize streaming cancellation#3933
seratch wants to merge 1 commit into
mainfrom
fix/realtime-guardrails-and-stream-cancellation

Conversation

@seratch

@seratch seratch commented Jul 24, 2026

Copy link
Copy Markdown
Member

This pull request fixes two streaming runtime issues affecting output safety and cancellation behavior.

  • Run realtime output guardrails for text-only responses, applying the same accumulation, debounce, and interruption behavior already used for audio transcripts.
  • Prevent cancel(mode="after_turn") from starting another model request while stream consumers are still processing events.
  • Replace scheduler-dependent cancellation timing with explicit event-consumption synchronization that safely handles inactive consumers, closed iterators, and immediate cancellation.
  • Add regression coverage for fragmented text output, malformed realtime events, delayed cancellation, consumer shutdown, and runs without stream consumers.

@seratch seratch added this to the 0.19.x milestone Jul 24, 2026

@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: 4801764e70

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/run_internal/run_loop.py Outdated
Comment thread src/agents/realtime/session.py Outdated
Comment thread src/agents/realtime/session.py Outdated

@gnanirahulnutakki gnanirahulnutakki 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.

Thanks—this is a strong direction, and the text-only Realtime guardrail path is well scoped. The focused Realtime and soft-cancel suites pass locally (157 passed), and the new event names match the Realtime contract.

One blocking cancellation gap remains: event-consumption synchronization is only applied to NextStepRunAgain. A handoff can still start the next agent's model request while the consumer is processing the first turn's handoff_requested event. On the current head I deterministically observed two model requests and Agent2's final output before cancel(mode="after_turn") took effect.

Please gate the handoff (and any equivalent resumed continuation path) before another model turn begins, and add a controlled-interleaving regression test. Once that is covered, the cancellation approach looks sound.

Comment thread src/agents/run_internal/run_loop.py Outdated
@seratch
seratch force-pushed the fix/realtime-guardrails-and-stream-cancellation branch from 4801764 to 81aa66b Compare July 24, 2026 07:03
@openai openai deleted a comment from chatgpt-codex-connector Bot Jul 24, 2026
@openai openai deleted a comment from chatgpt-codex-connector Bot Jul 24, 2026

@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: 81aa66bc8b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/run_internal/run_loop.py
@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 81aa66bc8b

View security finding report

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 81aa66bc8b

View security finding report

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@gnanirahulnutakki gnanirahulnutakki 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.

Re-reviewed at 81aa66bc. The original cancellation gap is addressed: the event-consumption barrier now covers ordinary run-again, handoff, resumed run-again, and resumed handoff continuations before another model request can start. The new controlled-interleaving tests exercise both handoff and resume paths.

Local verification: 169 focused Realtime/cancellation/resume tests passed, Ruff and formatting checks passed, and an independent follow-up-commit review found no issues. GitHub’s current test, lint, typecheck, docs, and Windows matrix is green. I found no remaining issues in the follow-up.

@openai openai deleted a comment from chatgpt-codex-connector Bot Jul 24, 2026
@openai openai deleted a comment from chatgpt-codex-connector Bot Jul 24, 2026
@seratch
seratch force-pushed the fix/realtime-guardrails-and-stream-cancellation branch from 81aa66b to 558ddc1 Compare July 24, 2026 11:54

@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: 87ccdd53f6

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/realtime/session.py Outdated

@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: 3ad58eebcd

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/realtime/session.py Outdated
Comment thread src/agents/realtime/session.py Outdated
Comment thread src/agents/realtime/session.py

@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: e849790f3b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/realtime/session.py Outdated
Comment thread examples/realtime/app/README.md Outdated

@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: a5275431a7

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/realtime/session.py Outdated
Comment thread src/agents/realtime/session.py Outdated
Comment thread src/agents/realtime/session.py Outdated
@seratch
seratch force-pushed the fix/realtime-guardrails-and-stream-cancellation branch from a527543 to 085f939 Compare July 24, 2026 15:51

@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: 085f939149

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/realtime/openai_realtime.py
Comment thread src/agents/realtime/openai_realtime.py
Comment thread src/agents/result.py Outdated

@gnanirahulnutakki gnanirahulnutakki 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.

Re-reviewed the current head 085f9391 after the force-push. The follow-up closes the remaining public-result state gap: _publish_streamed_result_agent() now updates current_agent and the output schema before the handoff event-consumption barrier can honor after_turn cancellation, and the ordinary plus resumed handoff tests assert current_agent, last_agent, to_state(), and the schema.

Local verification on this exact head: uv run pytest -q tests/test_soft_cancel.py tests/test_run_impl_resume_paths.py34 passed. GitHub's current test matrix, typecheck, lint, docs, and Windows checks are all green. I found no remaining issue in the cancellation follow-up.

@seratch

seratch commented Jul 24, 2026

Copy link
Copy Markdown
Member Author

@gnanirahulnutakki Thanks for sharing your review results, but could you refrain from posting general comments? Pointing specific points out would be appreciated.

@gnanirahulnutakki

Copy link
Copy Markdown

Understood—thanks for the guidance. I’ll keep future feedback to specific, actionable inline findings and avoid posting general review-summary comments.

@seratch
seratch force-pushed the fix/realtime-guardrails-and-stream-cancellation branch from 085f939 to e6b9328 Compare July 24, 2026 22:04

@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: e6b93288b9

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

):
await self._clear_pending_response_create(parsed.error.event_id)
await self._emit_event(RealtimeModelErrorEvent(error=parsed.error))
pending = await self._clear_pending_response_create(parsed.error.event_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Release rejected recovery creates during active VAD turns

When server-side VAD wins the race after a correlated guardrail-recovery response.create has been sent, the API can reject that create while the VAD response is active. This cleanup is gated by not self._ongoing_response, so the matching error is emitted without clearing _pending_response_create; mark_response_done() then deliberately preserves the pending entry, leaving _response_control as create_requested and blocking every subsequent local response indefinitely. Handle matching create errors even while another response is active, retrying or failing the recovery deterministically. The fresh evidence in this revision is that mismatched VAD response.created events now intentionally retain the pending recovery, making this failure path reachable.

AGENTS.md reference: AGENTS.md:L109-L109

Useful? React with 👍 / 👎.

Comment on lines +944 to +949
manual = event.response_create_id is not None
request_version = await self._reserve_response_create_request(manual=manual)
self._start_response_create(
request_version,
manual=manual,
response_create_id=event.response_create_id,

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 Serialize recovery inputs with their response creates

When delayed guardrails from two different responses trip while another response is active, each recovery call sends its conversation.item.create immediately, while only the corresponding response.create is deferred and kept separate by manual=True. Both recovery items therefore enter the conversation before the first deferred create runs, so its response consumes both items and the second create later runs without its intended new input, producing combined or duplicate recovery output despite having distinct correlation IDs. Queue each recovery input together with its create, rather than sequencing only the creates.

AGENTS.md reference: AGENTS.md:L109-L109

Useful? React with 👍 / 👎.

Comment on lines +454 to +460
elif event.type == "output_text_delta":
assert isinstance(event, RealtimeModelOutputTextDeltaEvent)
self._record_output_guardrail_delta(
event.item_id,
event.delta,
event.response_id,
is_audio_output=False,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Document text deltas in the debounce setting

This branch expands debounce_text_length to text-only output, but the published RealtimeGuardrailsSettings API documentation in src/agents/realtime/config.py:231-233 still says the threshold applies only to transcript deltas. Users configuring text-only sessions can therefore miss that their output is accumulated and checked under this setting; update the public setting description alongside the new behavior.

AGENTS.md reference: AGENTS.md:L69-L69

Useful? React with 👍 / 👎.

@seratch seratch modified the milestones: 0.19.x, 0.20.x Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants