@@ -14,6 +14,7 @@ import { RuntimeEventEmitter } from '@openai/agents-core/_shims';
1414import { isZodObject , toSmartString } from '@openai/agents-core/utils' ;
1515import type {
1616 RealtimeSessionConfig ,
17+ RealtimeSessionConfigDefinition ,
1718 RealtimeToolDefinition ,
1819 RealtimeTracingConfig ,
1920 RealtimeUserInput ,
@@ -346,9 +347,20 @@ export class RealtimeSession<
346347 async #getSessionConfig(
347348 additionalConfig : Partial < RealtimeSessionConfig > = { } ,
348349 ) : Promise < Partial < RealtimeSessionConfig > > {
350+ const overridesConfig : Partial < RealtimeSessionConfig > =
351+ additionalConfig ?? { } ;
352+ const optionsConfig : Partial < RealtimeSessionConfig > =
353+ this . options . config ?? { } ;
349354 const instructions = await this . #currentAgent. getSystemPrompt (
350355 this . #context,
351356 ) ;
357+ const getAudioOutputVoiceOverride = (
358+ config : Partial < RealtimeSessionConfig > ,
359+ ) : string | undefined => {
360+ const audioConfig = ( config as Partial < RealtimeSessionConfigDefinition > )
361+ . audio ;
362+ return audioConfig ?. output ?. voice ;
363+ } ;
352364
353365 // Realtime expects tracing to be explicitly null to disable it; leaving the previous config
354366 // in place would otherwise continue emitting spans.
@@ -374,6 +386,17 @@ export class RealtimeSession<
374386 ) ;
375387 }
376388
389+ const audioOutputVoiceOverride =
390+ getAudioOutputVoiceOverride ( overridesConfig ) ??
391+ getAudioOutputVoiceOverride ( optionsConfig ) ;
392+ const topLevelVoiceOverride = overridesConfig . voice ?? optionsConfig . voice ;
393+ const resolvedVoice =
394+ typeof audioOutputVoiceOverride !== 'undefined'
395+ ? audioOutputVoiceOverride
396+ : typeof topLevelVoiceOverride !== 'undefined'
397+ ? topLevelVoiceOverride
398+ : this . #currentAgent. voice ;
399+
377400 // Start from any previously-sent config (so we preserve values like audio formats)
378401 // and the original options.config provided by the user. Preference order:
379402 // 1. Last session config we sent (#lastSessionConfig)
@@ -383,15 +406,15 @@ export class RealtimeSession<
383406 // to ensure they always reflect the current agent & runtime state.
384407 const base : Partial < RealtimeSessionConfig > = {
385408 ...( this . #lastSessionConfig ?? { } ) ,
386- ...( this . options . config ?? { } ) ,
387- ...( additionalConfig ?? { } ) ,
409+ ...optionsConfig ,
410+ ...overridesConfig ,
388411 } ;
389412
390413 // Note: Certain fields cannot be updated after the session begins, such as voice and model
391414 const fullConfig : Partial < RealtimeSessionConfig > = {
392415 ...base ,
393416 instructions,
394- voice : this . #currentAgent . voice ,
417+ voice : resolvedVoice ,
395418 model : this . options . model ,
396419 tools : this . #currentTools,
397420 tracing : tracingConfig ,
0 commit comments