Add realtime start instructions config override (#14270)

- add `realtime_start_instructions` config support
- thread it into realtime context updates, schema, docs, and tests
This commit is contained in:
Ahmed Ibrahim
2026-03-10 18:42:05 -07:00
committed by Michael Bolin
parent 31bf1dbe63
commit 39c1bc1c68
7 changed files with 134 additions and 3 deletions

View File

@@ -161,6 +161,25 @@ fn assert_request_contains_realtime_start(request: &responses::ResponsesRequest)
);
}
fn assert_request_contains_custom_realtime_start(
request: &responses::ResponsesRequest,
instructions: &str,
) {
let body = request.body_json().to_string();
assert!(
body.contains("<realtime_conversation>"),
"expected request to preserve the realtime wrapper"
);
assert!(
body.contains(instructions),
"expected request to use custom realtime start instructions"
);
assert!(
!body.contains("Realtime conversation started."),
"expected request to replace the default realtime start instructions"
);
}
fn assert_request_contains_realtime_end(request: &responses::ResponsesRequest) {
let body = request.body_json().to_string();
assert!(
@@ -1518,6 +1537,53 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_restates_realtime_sta
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn remote_request_uses_custom_experimental_realtime_start_instructions() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = wiremock::MockServer::start().await;
let realtime_server = start_remote_realtime_server().await;
let custom_instructions = "custom realtime start instructions";
let mut builder = remote_realtime_test_codex_builder(&realtime_server).with_config({
let custom_instructions = custom_instructions.to_string();
move |config| {
config.experimental_realtime_start_instructions = Some(custom_instructions);
}
});
let test = builder.build(&server).await?;
let responses_mock = responses::mount_sse_once(
&server,
responses::sse(vec![
responses::ev_assistant_message("m1", "REMOTE_FIRST_REPLY"),
responses::ev_completed("r1"),
]),
)
.await;
start_realtime_conversation(test.codex.as_ref()).await?;
test.codex
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "USER_ONE".to_string(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
})
.await?;
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
assert_request_contains_custom_realtime_start(
&responses_mock.single_request(),
custom_instructions,
);
close_realtime_conversation(test.codex.as_ref()).await?;
realtime_server.shutdown().await;
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn snapshot_request_shape_remote_pre_turn_compaction_restates_realtime_end() -> Result<()> {
skip_if_no_network!(Ok(()));