Skip to content

Commit 5888cf2

Browse files
authored
Realtime: send session.update event at connection/handoffs (#1112)
This is what tells the model about tools, tool choice, model etc etc.
1 parent b620166 commit 5888cf2

File tree

8 files changed

+293
-146
lines changed

8 files changed

+293
-146
lines changed

examples/realtime/demo.py

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -58,55 +58,45 @@ async def run(self) -> None:
5858
self.session = session
5959
self.ui.set_is_connected(True)
6060
async for event in session:
61-
await self.on_event(event)
61+
await self._on_event(event)
62+
print("done")
6263

6364
# Wait for UI task to complete when session ends
6465
await ui_task
6566

6667
async def on_audio_recorded(self, audio_bytes: bytes) -> None:
67-
"""Called when audio is recorded by the UI."""
68-
try:
69-
# Send the audio to the session
70-
assert self.session is not None
71-
await self.session.send_audio(audio_bytes)
72-
except Exception as e:
73-
self.ui.log_message(f"Error sending audio: {e}")
74-
75-
async def on_event(self, event: RealtimeSessionEvent) -> None:
76-
# Display event in the UI
77-
try:
78-
if event.type == "agent_start":
79-
self.ui.add_transcript(f"Agent started: {event.agent.name}")
80-
elif event.type == "agent_end":
81-
self.ui.add_transcript(f"Agent ended: {event.agent.name}")
82-
elif event.type == "handoff":
83-
self.ui.add_transcript(
84-
f"Handoff from {event.from_agent.name} to {event.to_agent.name}"
85-
)
86-
elif event.type == "tool_start":
87-
self.ui.add_transcript(f"Tool started: {event.tool.name}")
88-
elif event.type == "tool_end":
89-
self.ui.add_transcript(f"Tool ended: {event.tool.name}; output: {event.output}")
90-
elif event.type == "audio_end":
91-
self.ui.add_transcript("Audio ended")
92-
elif event.type == "audio":
93-
np_audio = np.frombuffer(event.audio.data, dtype=np.int16)
94-
self.ui.play_audio(np_audio)
95-
elif event.type == "audio_interrupted":
96-
self.ui.add_transcript("Audio interrupted")
97-
elif event.type == "error":
98-
self.ui.add_transcript(f"Error: {event.error}")
99-
elif event.type == "history_updated":
100-
pass
101-
elif event.type == "history_added":
102-
pass
103-
elif event.type == "raw_model_event":
104-
self.ui.log_message(f"Raw model event: {event.data}")
105-
else:
106-
self.ui.log_message(f"Unknown event type: {event.type}")
107-
except Exception as e:
108-
# This can happen if the UI has already exited
109-
self.ui.log_message(f"Event handling error: {str(e)}")
68+
# Send the audio to the session
69+
assert self.session is not None
70+
await self.session.send_audio(audio_bytes)
71+
72+
async def _on_event(self, event: RealtimeSessionEvent) -> None:
73+
if event.type == "agent_start":
74+
self.ui.add_transcript(f"Agent started: {event.agent.name}")
75+
elif event.type == "agent_end":
76+
self.ui.add_transcript(f"Agent ended: {event.agent.name}")
77+
elif event.type == "handoff":
78+
self.ui.add_transcript(f"Handoff from {event.from_agent.name} to {event.to_agent.name}")
79+
elif event.type == "tool_start":
80+
self.ui.add_transcript(f"Tool started: {event.tool.name}")
81+
elif event.type == "tool_end":
82+
self.ui.add_transcript(f"Tool ended: {event.tool.name}; output: {event.output}")
83+
elif event.type == "audio_end":
84+
self.ui.add_transcript("Audio ended")
85+
elif event.type == "audio":
86+
np_audio = np.frombuffer(event.audio.data, dtype=np.int16)
87+
self.ui.play_audio(np_audio)
88+
elif event.type == "audio_interrupted":
89+
self.ui.add_transcript("Audio interrupted")
90+
elif event.type == "error":
91+
self.ui.add_transcript(f"Error: {event.error}")
92+
elif event.type == "history_updated":
93+
pass
94+
elif event.type == "history_added":
95+
pass
96+
elif event.type == "raw_model_event":
97+
self.ui.log_message(f"Raw model event: {event.data}")
98+
else:
99+
self.ui.log_message(f"Unknown event type: {event.type}")
110100

111101

112102
if __name__ == "__main__":

examples/realtime/ui.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,7 @@ async def capture_audio(self) -> None:
239239

240240
# Call audio callback if set
241241
if self.audio_callback:
242-
try:
243-
await self.audio_callback(audio_bytes)
244-
except Exception as e:
245-
self.log_message(f"Audio callback error: {e}")
242+
await self.audio_callback(audio_bytes)
246243

247244
# Yield control back to event loop
248245
await asyncio.sleep(0)

src/agents/realtime/model_inputs.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from typing_extensions import NotRequired, TypeAlias, TypedDict
77

8+
from .config import RealtimeSessionModelSettings
89
from .model_events import RealtimeModelToolCallEvent
910

1011

@@ -81,10 +82,19 @@ class RealtimeModelSendInterrupt:
8182
"""Send an interrupt to the model."""
8283

8384

85+
@dataclass
86+
class RealtimeModelSendSessionUpdate:
87+
"""Send a session update to the model."""
88+
89+
session_settings: RealtimeSessionModelSettings
90+
"""The updated session settings to send."""
91+
92+
8493
RealtimeModelSendEvent: TypeAlias = Union[
8594
RealtimeModelSendRawMessage,
8695
RealtimeModelSendUserInput,
8796
RealtimeModelSendAudio,
8897
RealtimeModelSendToolOutput,
8998
RealtimeModelSendInterrupt,
99+
RealtimeModelSendSessionUpdate,
90100
]

0 commit comments

Comments
 (0)