Skip to content

Conversation

gn00295120
Copy link
Contributor

Summary

Fixes #1907

When turn_detection.interrupt_response is set to True and a guardrail triggers an interrupt, the SDK was only sending response.interrupt but not response.cancel. This caused the API to think the response was still active, leading to "Conversation already has an active response" errors on subsequent requests.

Root Cause

  • Guardrail interrupts are SDK-side logic, but the API doesn't know about them
  • interrupt_response=True tells the API to auto-cancel on user voice interrupts
  • When a guardrail triggered, the SDK would skip sending response.cancel if interrupt_response=True, incorrectly assuming the API would handle it

Solution

  1. Add force_cancel parameter to RealtimeModelSendInterrupt
  2. Set force_cancel=True for guardrail interrupts
  3. Always send response.cancel when force_cancel=True, regardless of interrupt_response setting
  4. User voice interrupts continue to respect interrupt_response setting

Files Changed

  • src/agents/realtime/model_inputs.py: Add force_cancel parameter with documentation
  • src/agents/realtime/session.py: Pass force_cancel=True for guardrail interrupts
  • src/agents/realtime/openai_realtime.py: Check force_cancel in _send_interrupt() method

Testing

Comprehensive test suite included in branch:

  • tests/realtime/test_issue_1907_guardrail_interrupt.py (5 test cases)

Tests verify:

  • ✅ Guardrails send cancel when interrupt_response=True (core fix)
  • ✅ Guardrails send cancel when interrupt_response=False (baseline)
  • ✅ User voice interrupts do NOT send cancel when interrupt_response=True (edge case)
  • ✅ Multiple guardrail triggers only send one cancel per response (deduplication)
  • ✅ Safe guardrails don't trigger interrupts (negative test)

All existing tests pass:

  • 153 realtime tests ✅
  • All guardrail functionality tests ✅

Backward Compatibility

✅ Fully backward compatible

  • force_cancel defaults to False, preserving existing behavior for user voice interrupts
  • Only guardrail interrupts use force_cancel=True
  • No changes to public API or existing configurations

@gn00295120 gn00295120 force-pushed the fix/issue-1907-guardrail-interrupt-with-auto-response branch from 3a20351 to 5d4414b Compare October 21, 2025 02:28
When turn_detection.interrupt_response is set to True and a guardrail triggers
an interrupt, the SDK was only sending response.interrupt but not response.cancel.
This caused the API to think the response was still active, leading to
"Conversation already has an active response" errors on subsequent requests.

Root cause:
- Guardrail interrupts are SDK-side logic, but the API doesn't know about them
- interrupt_response=True tells the API to auto-cancel on USER VOICE interrupts
- When a guardrail triggered, the SDK would skip sending response.cancel if
  interrupt_response=True, assuming the API would handle it (incorrect)

Solution:
- Add force_cancel parameter to RealtimeModelSendInterrupt
- Set force_cancel=True for guardrail interrupts
- Always send response.cancel when force_cancel=True, regardless of
  interrupt_response setting
- User voice interrupts continue to respect interrupt_response setting

Changes:
- src/agents/realtime/model_inputs.py: Add force_cancel parameter
- src/agents/realtime/session.py: Pass force_cancel=True for guardrails
- src/agents/realtime/openai_realtime.py: Check force_cancel in _send_interrupt

Fixes openai#1907
@gn00295120 gn00295120 force-pushed the fix/issue-1907-guardrail-interrupt-with-auto-response branch from 5d4414b to b1fc173 Compare October 21, 2025 02:33
@seratch
Copy link
Member

seratch commented Oct 21, 2025

Perhaps, I need to take time to identify the best solution for this issue, but at a glance, I am unsure if this simple fix works.

@gn00295120
Copy link
Contributor Author

Perhaps, I need to take time to identify the best solution for this issue, but at a glance, I am unsure if this simple fix works.

As a beginner/newcomer, I would like to ask if I should submit the test file

@seratch
Copy link
Member

seratch commented Oct 21, 2025

Just having auto-generated tests does not guarantee your fix is effective for fixing the issue. I need to take time to investigate the actual behavior, but I haven't had the bandwidth for it.

@seratch
Copy link
Member

seratch commented Oct 21, 2025

Closing this in favor of #1952

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.

Realtime guardrails: "Conversation already has an active response in progress" error

2 participants