Summary
When using the Realtime API over SIP, two related issues occur when the caller hangs up:
-
If the caller ends the call after it’s connected, OpenAI immediately closes the session WebSocket.
This prevents pending events (tool calls, transcription, output buffering) from being delivered, resulting in incomplete tool calls and partial transcriptions. -
If the caller hangs up while the call is still ringing, OpenAI still accepts the call and starts an agent session as if the call were active, even though no caller is present.
This causes the agent to speak into a dead session, which then hangs until timeout.
Both situations differ from expected behavior and make proper cleanup difficult.
Issue 1: Immediate WebSocket close on caller hangup
Actual Behavior
-
When the caller hangs up, the session WebSocket is immediately closed by OpenAI.
-
No further events are delivered (e.g., tool calls,
output_audio_buffer.stopped, transcription chunks). -
This results in incomplete processing of the agent’s final output.
Expected Behavior
-
When the caller hangs up, OpenAI should not close the WebSocket immediately.
-
Instead, the session should enter a draining state:
-
Finish delivering any pending events from the agent.
-
Then close the WebSocket once no more events remain.
-
-
Optionally, the API could emit a specific event indicating that the caller disconnected before draining began.
Rationale
We encountered a similar issue when integrating with Twilio.
The fix there was to drain the agent’s event loop before closing the WebSocket.
The same pattern would avoid dropped tool calls and partial transcriptions in the SIP flow.
Issue 2: Caller hangs up while ringing, but OpenAI still accepts the call
Actual Behavior
-
Caller dials but hangs up before the call is answered.
-
The SIP provider still notifies the OpenAI webhook.
-
OpenAI accepts the call as if the caller were present.
-
The agent session starts (greeting, output events), but no events come from the caller side.
-
The session then hangs until timeout.
Expected Behavior
OpenAI should not accept the call if the caller has already disconnected.
Possible correct behaviors:
-
Reject the
acceptAPI call if the caller is no longer on the line, or -
If accepted, immediately close the control WebSocket since there is no active caller.
Impact
-
Tool calls remain unfinished.
-
Transcriptions are incomplete.
-
Agent sessions leak or hang unnecessarily.
-
Confusing behavior especially in production environments with SIP trunks.
Proposed Improvements
-
Introduce a draining phase on caller hangup (deliver remaining events before closing).
-
Emit a “caller disconnected” event to let applications react cleanly.
-
Reject accept requests or close the session early when the caller drops before answer.