Allow custom Codex instructions for realtime transitions (#36408)

## What changed

- Add optional `realtimeStartInstructions` and `realtimeEndInstructions` fields to `thread/realtime/start`.
- Apply the instructions when Codex enters and leaves realtime mode, while preserving the existing defaults when either field is omitted.
- Limit each field to 8,192 estimated tokens.

## Testing

- Cover custom entry and exit instructions across realtime state transitions.
- Cover token-limit validation for both fields.

GitOrigin-RevId: b9cfa1ff22e084d8a6b2ed56bd27d95ffdd6b6bd
This commit is contained in:
guinness-oai
2026-07-31 23:51:33 +00:00
committed by copyberry
parent 64b2a3008e
commit 670f69416b
18 changed files with 395 additions and 33 deletions
@@ -3632,6 +3632,8 @@ mod tests {
text: "Understood.".to_string(),
},
]),
realtime_start_instructions: Some("Use realtime output channels.".to_string()),
realtime_end_instructions: Some("Resume normal text responses.".to_string()),
prompt: Some(Some("You are on a call".to_string())),
realtime_session_id: Some("sess_456".to_string()),
transport: None,
@@ -3668,6 +3670,8 @@ mod tests {
"text": "Understood."
}
],
"realtimeStartInstructions": "Use realtime output channels.",
"realtimeEndInstructions": "Resume normal text responses.",
"prompt": "You are on a call",
"realtimeSessionId": "sess_456",
"transport": null,
@@ -3696,6 +3700,8 @@ mod tests {
output_modality: RealtimeOutputModality::Audio,
include_startup_context: None,
initial_items: None,
realtime_start_instructions: None,
realtime_end_instructions: None,
prompt: None,
realtime_session_id: None,
transport: None,
@@ -3719,6 +3725,8 @@ mod tests {
"outputModality": "audio",
"includeStartupContext": null,
"initialItems": null,
"realtimeStartInstructions": null,
"realtimeEndInstructions": null,
"realtimeSessionId": null,
"transport": null,
"version": null,
@@ -3742,6 +3750,8 @@ mod tests {
output_modality: RealtimeOutputModality::Audio,
include_startup_context: None,
initial_items: None,
realtime_start_instructions: None,
realtime_end_instructions: None,
prompt: Some(None),
realtime_session_id: None,
transport: None,
@@ -3765,6 +3775,8 @@ mod tests {
"outputModality": "audio",
"includeStartupContext": null,
"initialItems": null,
"realtimeStartInstructions": null,
"realtimeEndInstructions": null,
"prompt": null,
"realtimeSessionId": null,
"transport": null,
@@ -3988,6 +4000,8 @@ mod tests {
output_modality: RealtimeOutputModality::Audio,
include_startup_context: None,
initial_items: None,
realtime_start_instructions: None,
realtime_end_instructions: None,
prompt: Some(Some("You are on a call".to_string())),
realtime_session_id: None,
transport: None,
@@ -106,6 +106,12 @@ pub struct ThreadRealtimeStartParams {
/// limited to 128 items and 8,192 estimated text tokens in total.
#[ts(optional = nullable)]
pub initial_items: Option<Vec<ThreadRealtimeInitialItem>>,
/// Developer instructions given to the backing Codex model when this realtime session starts.
#[ts(optional = nullable)]
pub realtime_start_instructions: Option<String>,
/// Developer instructions given to the backing Codex model when this realtime session ends.
#[ts(optional = nullable)]
pub realtime_end_instructions: Option<String>,
#[serde(
default,
deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option",