Send base instructions as Responses input messages (#51156)

## What changed

Move base instructions from the top-level `instructions` field into a prefixed `developer` message in `input` for standard Responses requests, matching Responses Lite. Remove the field from HTTP and WebSocket request types and assign instruction messages stable IDs derived from the thread and instruction text.

## Testing

Extend standard and Responses Lite tests to cover instruction message serialization, stable IDs, and resume consistency. Update WebSocket tests to verify that changed instructions trigger a full request without `previous_response_id`.

GitOrigin-RevId: e2de4b8e30a9339377fac133ceda981abd1a112b
This commit is contained in:
pakrym-oai
2026-10-05 18:52:51 +00:00
committed by copyberry
parent 3f1ccb7ceb
commit c9253c4977
81 changed files with 1330 additions and 943 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ The public interface of this crate is intentionally small and uniform:
- **Responses endpoint**
- Input:
- `ResponsesApiRequest` for the request body (`model`, `instructions`, `input`, `tools`, `parallel_tool_calls`, reasoning/text controls).
- `ResponsesApiRequest` for the request body (`model`, `input`, `tools`, `parallel_tool_calls`, reasoning/text controls).
- `ResponsesOptions` for transport/header concerns (`conversation_id`, `session_source`, `extra_headers`, `compression`, `turn_state`).
- Output: a `ResponseStream` of `ResponseEvent` (both re-exported from `common`).
-5
View File
@@ -283,8 +283,6 @@ pub struct ResponsesApiRequest {
pub stream: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub service_tier: Option<String>,
#[serde(skip_serializing_if = "String::is_empty")]
pub instructions: String,
pub input: Vec<ResponseItem>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<ResponsesApiTools>,
@@ -309,7 +307,6 @@ impl<'a> From<&'a ResponsesApiRequest> for ResponseCreateWsRequest<'a> {
fn from(request: &'a ResponsesApiRequest) -> Self {
Self {
model: &request.model,
instructions: &request.instructions,
previous_response_id: None,
input: &request.input,
tools: request.tools.as_ref().map(ResponsesApiTools::as_raw_value),
@@ -338,8 +335,6 @@ pub struct ResponseCreateWsRequest<'a> {
pub stream: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub service_tier: Option<&'a str>,
#[serde(skip_serializing_if = "str::is_empty")]
pub instructions: &'a str,
#[serde(skip_serializing_if = "Option::is_none")]
pub previous_response_id: Option<String>,
pub input: &'a [ResponseItem],
@@ -945,7 +945,6 @@ mod tests {
fn direct_serialization_preserves_websocket_request_payload() {
let api_request = ResponsesApiRequest {
model: "gpt-test".to_string(),
instructions: "Use the available tools.".to_string(),
input: vec![ResponseItem::Message {
id: Some(ResponseItemId::with_suffix("msg", "1")),
role: "user".to_string(),
@@ -998,7 +997,7 @@ mod tests {
let request_text =
serialize_websocket_request(&request).expect("serialize websocket request");
assert!(request_text.starts_with(
r#"{"type":"response.create","model":"gpt-test","stream":true,"service_tier":"priority","instructions":"Use the available tools.","previous_response_id":"resp-1","input":"#
r#"{"type":"response.create","model":"gpt-test","stream":true,"service_tier":"priority","previous_response_id":"resp-1","input":"#
));
let wire_payload =
serde_json::from_str::<Value>(&request_text).expect("parse websocket request");
+1 -5
View File
@@ -339,7 +339,6 @@ async fn responses_client_stream_request_preserves_item_ids() -> Result<()> {
let client = ResponsesClient::new(transport, provider("openai"), Arc::new(NoAuth));
let request = ResponsesApiRequest {
model: "gpt-test".into(),
instructions: "Say hi".into(),
input: vec![ResponseItem::Message {
id: Some(ResponseItemId::with_suffix("msg", "1")),
role: "user".into(),
@@ -394,7 +393,6 @@ async fn responses_client_stream_request_sends_routing_fields_ahead_of_large_inp
let large_input = "x".repeat(2 * 1024 * 1024);
let request = ResponsesApiRequest {
model: "gpt-test".into(),
instructions: "Say hi".into(),
input: vec![ResponseItem::Message {
id: None,
role: "user".into(),
@@ -434,7 +432,7 @@ async fn responses_client_stream_request_sends_routing_fields_ahead_of_large_inp
);
}
assert!(body.starts_with(
r#"{"model":"gpt-test","stream":true,"service_tier":"priority","instructions":"Say hi","input":[{"type":"message""#
r#"{"model":"gpt-test","stream":true,"service_tier":"priority","input":[{"type":"message""#
));
assert!(body.len() > 2 * 1024 * 1024);
assert_eq!(serde_json::from_str::<serde_json::Value>(body)?, expected);
@@ -491,7 +489,6 @@ async fn streaming_client_retries_on_transport_error() -> Result<()> {
let request = ResponsesApiRequest {
model: "gpt-test".into(),
instructions: "Say hi".into(),
input: Vec::new(),
tools: Some(empty_tools().into()),
tool_choice: "auto".into(),
@@ -606,7 +603,6 @@ async fn azure_store_sends_ids_and_headers() -> Result<()> {
let request = ResponsesApiRequest {
model: "gpt-test".into(),
instructions: "Say hi".into(),
input: vec![ResponseItem::Message {
id: Some(ResponseItemId::with_suffix("msg", "1")),
role: "user".into(),
+21 -28
View File
@@ -344,7 +344,6 @@ fn responses_request_properties_match(
) -> bool {
let ResponsesApiRequest {
model: previous_model,
instructions: previous_instructions,
input: _,
tools: previous_tools,
tool_choice: previous_tool_choice,
@@ -362,7 +361,6 @@ fn responses_request_properties_match(
} = previous;
let ResponsesApiRequest {
model: current_model,
instructions: current_instructions,
input: _,
tools: current_tools,
tool_choice: current_tool_choice,
@@ -380,7 +378,6 @@ fn responses_request_properties_match(
} = current;
previous_model == current_model
&& previous_instructions == current_instructions
&& previous_tools == current_tools
&& previous_tool_choice == current_tool_choice
&& previous_parallel_tool_calls == current_parallel_tool_calls
@@ -908,14 +905,14 @@ impl ModelClient {
input.retain(|item| !matches!(item, ResponseItem::ConfigurationUpdate { .. }));
}
let is_openai = self.state.provider.info().is_openai();
let (instructions, tools) = if model_info.use_responses_lite {
// These prompt-only items are rebuilt on every request. Hash their visible payloads
// within the thread so retries and resumed sessions preserve their identity.
let prefix_namespace = Uuid::new_v5(
&Uuid::NAMESPACE_OID,
self.state.thread_id.to_string().as_bytes(),
);
let mut prefix = Vec::new();
// These prompt-only items are rebuilt on every request. Hash their visible payloads
// within the thread so retries and resumed sessions preserve their identity.
let prefix_namespace = Uuid::new_v5(
&Uuid::NAMESPACE_OID,
self.state.thread_id.to_string().as_bytes(),
);
let mut prefix = Vec::new();
let tools = if model_info.use_responses_lite {
if !prompt.tools.is_empty() {
let tools = create_tools_json_for_responses_lite(&prompt.tools)?;
prefix.push(ResponseItem::AdditionalTools {
@@ -927,24 +924,21 @@ impl ModelClient {
tools,
});
}
if !prompt.base_instructions.text.is_empty() {
let mut instructions = ContextualUserFragment::into(BaseInstructionsFragment(
prompt.base_instructions.text.clone(),
));
instructions.set_id(Some(ResponseItemId::with_suffix(
"msg",
Uuid::new_v5(&prefix_namespace, prompt.base_instructions.text.as_bytes()),
)));
prefix.push(instructions);
}
input.splice(0..0, prefix);
(String::new(), None)
None
} else {
(
prompt.base_instructions.text.clone(),
Some(create_tools_raw_json_for_responses_api(&prompt.tools)?.into()),
)
Some(create_tools_raw_json_for_responses_api(&prompt.tools)?.into())
};
if !prompt.base_instructions.text.is_empty() {
let mut instructions = ContextualUserFragment::into(BaseInstructionsFragment(
prompt.base_instructions.text.clone(),
));
instructions.set_id(Some(ResponseItemId::with_suffix(
"msg",
Uuid::new_v5(&prefix_namespace, prompt.base_instructions.text.as_bytes()),
)));
prefix.push(instructions);
}
input.splice(0..0, prefix);
if !is_openai {
for item in &mut input {
item.clear_internal_chat_message_metadata_passthrough();
@@ -1001,7 +995,6 @@ impl ModelClient {
let client_metadata = responses_metadata.client_metadata(include_internal);
let request = ResponsesApiRequest {
model: model_info.slug.clone(),
instructions,
input,
tools,
tool_choice: "auto".to_string(),
-4
View File
@@ -112,7 +112,6 @@ fn serializes_text_verbosity_when_set() {
let input: Vec<ResponseItem> = vec![];
let req = ResponsesApiRequest {
model: "gpt-5.4".to_string(),
instructions: "i".to_string(),
input,
tools: Some(empty_tools().into()),
tool_choice: "auto".to_string(),
@@ -160,7 +159,6 @@ fn serializes_text_schema_with_strict_format() {
let req = ResponsesApiRequest {
model: "gpt-5.4".to_string(),
instructions: "i".to_string(),
input,
tools: Some(empty_tools().into()),
tool_choice: "auto".to_string(),
@@ -222,7 +220,6 @@ fn omits_text_when_not_set() {
let input: Vec<ResponseItem> = vec![];
let req = ResponsesApiRequest {
model: "gpt-5.4".to_string(),
instructions: "i".to_string(),
input,
tools: Some(empty_tools().into()),
tool_choice: "auto".to_string(),
@@ -247,7 +244,6 @@ fn omits_text_when_not_set() {
fn serializes_flex_service_tier_when_set() {
let req = ResponsesApiRequest {
model: "gpt-5.4".to_string(),
instructions: "i".to_string(),
input: vec![],
tools: Some(empty_tools().into()),
tool_choice: "auto".to_string(),
+34 -11
View File
@@ -767,6 +767,10 @@ fn responses_request_preserves_result_metadata_above_previous_aggregate_budget()
crate::tools::ExecutedToolCalls::new(&features, &codex_history::InitialHistory::New);
let mut prompt = Prompt {
input: history.clone(),
base_instructions: BaseInstructions {
text: String::new(),
..Default::default()
},
..Default::default()
};
// Follow the sampling path: budget the request copy before client serialization.
@@ -976,6 +980,10 @@ async fn responses_http_preserves_raw_tool_metadata_for_openai_custom_endpoint()
})));
let prompt = Prompt {
input: vec![output.clone()],
base_instructions: BaseInstructions {
text: String::new(),
..Default::default()
},
..Default::default()
};
let responses_metadata = test_responses_metadata_for_client(
@@ -1014,12 +1022,14 @@ async fn responses_http_preserves_raw_tool_metadata_for_openai_custom_endpoint()
Ok(())
}
#[test]
fn responses_lite_prefix_ids_track_thread_and_payload() -> anyhow::Result<()> {
#[test_case::test_case(false; "standard")]
#[test_case::test_case(true; "responses_lite")]
fn prefix_ids_track_thread_and_payload(responses_lite: bool) -> anyhow::Result<()> {
let thread_id = ThreadId::new();
let client = test_model_client_with_thread_id(thread_id, SessionSource::Cli);
let mut model = test_model_info();
model.use_responses_lite = true;
model.use_responses_lite = responses_lite;
let instructions_index = usize::from(responses_lite);
let mut tool = codex_tools::FreeformTool {
name: "exec".to_string(),
description: "Execute JavaScript.".to_string(),
@@ -1061,25 +1071,38 @@ fn responses_lite_prefix_ids_track_thread_and_payload() -> anyhow::Result<()> {
prompt.base_instructions.text.push_str(" with an update");
let changed_instructions = build(&client, &prompt)?;
assert_eq!(changed_instructions.input[0], original.input[0]);
assert_ne!(changed_instructions.input[1].id(), original.input[1].id());
assert_ne!(
changed_instructions.input[instructions_index].id(),
original.input[instructions_index].id()
);
tool.description
.push_str(" Updated execution instructions.");
prompt.tools = vec![codex_tools::ToolSpec::Freeform(tool)].into();
let changed_tools = build(&client, &prompt)?;
assert_ne!(
changed_tools.input[0].id(),
changed_instructions.input[0].id()
assert_eq!(
changed_tools.input[instructions_index],
changed_instructions.input[instructions_index]
);
assert_eq!(changed_tools.input[1], changed_instructions.input[1]);
if responses_lite {
assert_eq!(changed_instructions.input[0], original.input[0]);
assert_ne!(
changed_tools.input[0].id(),
changed_instructions.input[0].id()
);
}
let independent = build(
&test_model_client_with_thread_id(ThreadId::new(), SessionSource::Cli),
&prompt,
)?;
assert_ne!(independent.input[0].id(), changed_tools.input[0].id());
assert_ne!(independent.input[1].id(), changed_tools.input[1].id());
assert_ne!(
independent.input[instructions_index].id(),
changed_tools.input[instructions_index].id()
);
if responses_lite {
assert_ne!(independent.input[0].id(), changed_tools.input[0].id());
}
Ok(())
}
+18 -11
View File
@@ -10,6 +10,7 @@ use codex_protocol::models::ToolResultSource;
use codex_protocol::models::ToolResultSources;
use pretty_assertions::assert_eq;
use serde_json::json;
use std::collections::HashMap;
fn request() -> ResponsesApiRequest {
request_with_metadata(&json!({
@@ -43,7 +44,6 @@ fn request_with_metadata_and_source(
output.mark_tool_calls_complete();
ResponsesApiRequest {
model: "test".to_string(),
instructions: "x".to_string(),
input: vec![output],
tools: None,
tool_choice: "auto".to_string(),
@@ -56,18 +56,22 @@ fn request_with_metadata_and_source(
service_tier: None,
prompt_cache_key: None,
text: None,
client_metadata: None,
client_metadata: Some(HashMap::from([("padding".to_string(), "x".to_string())])),
access_programs: None,
}
}
fn set_padding(request: &mut ResponsesApiRequest, padding: String) {
request.client_metadata = Some(HashMap::from([("padding".to_string(), padding)]));
}
#[test]
fn http_message_budget_preserves_resources_until_the_message_still_exceeds_limit() {
for overage in [0, 4 * 1024, 20 * 1024, 40 * 1024] {
let mut request = request();
let target_bytes = MAX_RESPONSE_MESSAGE_BYTES + overage;
request.instructions =
"x".repeat(target_bytes - serialized_json_bytes(&request).unwrap() + 1);
let padding = "x".repeat(target_bytes - serialized_json_bytes(&request).unwrap() + 1);
set_padding(&mut request, padding);
assert_eq!(serialized_json_bytes(&request).unwrap(), target_bytes);
assert!(metadata_metrics::metadata_bytes(&request.input) < 32 * 1024);
let original_input = request.input.clone();
@@ -158,10 +162,11 @@ fn message_budget_removes_residual_values_and_markers_when_ordinary_input_fits()
} else {
serialized_json_bytes(&ordinary).unwrap()
};
// The original instructions contain one byte, so leave exactly one
// The original padding contains one byte, so leave exactly one
// byte below the limit after removing only result metadata.
ordinary.instructions = "x".repeat(MAX_RESPONSE_MESSAGE_BYTES - ordinary_bytes);
request.instructions = ordinary.instructions.clone();
let padding = "x".repeat(MAX_RESPONSE_MESSAGE_BYTES - ordinary_bytes);
set_padding(&mut ordinary, padding.clone());
set_padding(&mut request, padding);
let original_input = request.input.clone();
let mut expected = ordinary.clone();
if metadata.get("openai/resource_access").is_some() {
@@ -235,9 +240,10 @@ fn residual_marker_removal_preserves_earlier_resources_and_stops_when_message_fi
}
let mut expected = request.clone();
expected.input[1].clear_tool_result_metadata();
expected.instructions =
let padding =
"x".repeat(MAX_RESPONSE_MESSAGE_BYTES - serialized_json_bytes(&expected).unwrap() + 1);
request.instructions = expected.instructions.clone();
set_padding(&mut expected, padding.clone());
set_padding(&mut request, padding);
assert_eq!(
serialized_json_bytes(&expected).unwrap(),
MAX_RESPONSE_MESSAGE_BYTES
@@ -303,8 +309,9 @@ fn inventory_only_message_budget_counts_the_complete_encoded_envelope() {
} else {
serialized_json_bytes(&ordinary).unwrap()
};
request.instructions = "x".repeat(MAX_RESPONSE_MESSAGE_BYTES - ordinary_bytes + 1);
ordinary.instructions = request.instructions.clone();
let padding = "x".repeat(MAX_RESPONSE_MESSAGE_BYTES - ordinary_bytes + 1);
set_padding(&mut request, padding.clone());
set_padding(&mut ordinary, padding);
if websocket {
let mut message =
ResponsesWsRequest::ResponseCreate(ResponseCreateWsRequest::from(&request));
@@ -52,13 +52,11 @@ pub(super) fn estimate_request_tokens(request: &ResponsesApiRequest) -> usize {
.iter()
.map(estimate_item_token_count)
.fold(0i64, i64::saturating_add);
let instructions = TruncationPolicy::Bytes(request.instructions.len()).token_budget();
let metadata = serde_json::to_vec(&(&request.tools, &request.text))
.map(|bytes| TruncationPolicy::Bytes(bytes.len()).token_budget())
.unwrap_or(usize::MAX);
usize::try_from(input)
.unwrap_or(usize::MAX)
.saturating_add(instructions)
.saturating_add(metadata)
}
@@ -7,13 +7,15 @@ Scenario: First request after fork when startup preserves the parent baseline, t
## Window 1
-- request 1 (turn; First Forked Turn Request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
fork seed
03:message/developer[2]:
04:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <COLLABORATION_MODE>
04:message/user:
05:message/user:
after fork
+11 -10
View File
@@ -132,7 +132,7 @@ fn capture_request(number: usize, entry: &SnapshotEntry<'_>) -> CapturedRequest
}
SnapshotSource::Items(items) => ("items".to_string(), Value::Array(items.to_vec()), None),
};
// Responses Lite moves base instructions into an annotated developer content part. Keep its
// Base instructions live in an annotated developer content part. Keep its
// location for rendering, while still excluding transport metadata from window comparison.
let mut model_instruction_parts: Vec<_> = input
.as_array()
@@ -150,21 +150,22 @@ fn capture_request(number: usize, entry: &SnapshotEntry<'_>) -> CapturedRequest
.map(move |(part_index, _)| (item_index, part_index))
})
.collect();
// Providers can remove annotations. The Lite prefix still identifies the position, but an
// Providers can remove annotations. The prefix still identifies the position, but an
// empty base prompt also leaves ordinary developer guidance there; require a complete catalog prompt.
let instructions_index = usize::from(input[0]["type"] == "additional_tools");
let instructions = &input[instructions_index];
if model_instruction_parts.is_empty()
&& input[0]["type"] == "additional_tools"
&& input[0]["role"] == "developer"
&& input[1]["type"] == "message"
&& input[1]["role"] == "developer"
&& input[1]["content"]
&& instructions["type"] == "message"
&& instructions["role"] == "developer"
&& instructions["content"]
.as_array()
.is_some_and(|content| content.len() == 1)
&& input[1]["internal_chat_message_metadata_passthrough"]["content_item_kinds"][0].is_null()
&& let Some(text) = input[1]["content"][0]["text"].as_str()
&& instructions["internal_chat_message_metadata_passthrough"]["content_item_kinds"][0]
.is_null()
&& let Some(text) = instructions["content"][0]["text"].as_str()
&& is_bundled_model_instructions(text)
{
model_instruction_parts.push((1, 0));
model_instruction_parts.push((instructions_index, 0));
}
let input = strip_metadata_from_json(strip_response_item_ids_from_json(input));
CapturedRequest {
+4 -4
View File
@@ -227,10 +227,10 @@ impl ResponsesRequest {
}
pub fn instructions_text(&self) -> String {
self.body_json()["instructions"]
.as_str()
.unwrap()
.to_string()
self.message_input_texts("developer")
.into_iter()
.next()
.expect("base instructions developer message")
}
/// Returns all `input_text` spans from `message` inputs for the provided role.
+2 -2
View File
@@ -328,9 +328,9 @@ async fn websocket_first_turn_uses_startup_prewarm_and_create(
.expect("missing warmup request")
.body_json();
let turn = connection.get(1).expect("missing turn request").body_json();
assert_eq!(warmup["instructions"], turn["instructions"]);
assert_eq!(turn["previous_response_id"], "warm-1");
assert_eq!(
warmup["instructions"]
warmup["input"][0]["content"][0]["text"]
.as_str()
.expect("warmup base instructions")
.contains("update_plan"),
+6 -2
View File
@@ -2367,7 +2367,9 @@ async fn fork_injects_changed_agents_md_once() -> Result<()> {
let requests = response_mock.requests();
assert_eq!(requests.len(), 4);
let parent_input = requests[0].input();
let fork_input = requests[1].input();
let mut fork_input = requests[1].input();
// The request prefix has a thread-scoped ID; retained history IDs stay unchanged.
fork_input[0]["id"] = parent_input[0]["id"].clone();
assert_eq!(
fork_input.get(..parent_input.len()),
Some(parent_input.as_slice()),
@@ -2553,7 +2555,9 @@ async fn run_subagent_global_instruction_case(fork_context: bool) -> Result<()>
);
if fork_context {
let seed_input = seed_request.input();
let child_input = child_request.input();
let mut child_input = child_request.input();
// The request prefix has a thread-scoped ID; retained history IDs stay unchanged.
child_input[0]["id"] = seed_input[0]["id"].clone();
assert_eq!(
child_input.get(..seed_input.len()),
Some(seed_input.as_slice()),
+3 -13
View File
@@ -347,14 +347,9 @@ async fn exec_cli_applies_model_instructions_file() {
assert!(output.status.success());
// Inspect the captured request and verify our custom base instructions were
// included in the `instructions` field.
// included in the base instructions developer message.
let request = resp_mock.single_request();
let body = request.body_json();
let instructions = body
.get("instructions")
.and_then(|v| v.as_str())
.unwrap_or_default()
.to_string();
let instructions = request.instructions_text();
assert!(
instructions.contains(marker),
"instructions did not contain custom marker; got: {instructions}"
@@ -419,12 +414,7 @@ async fn exec_cli_profile_applies_model_instructions_file() {
assert!(output.status.success());
let request = resp_mock.single_request();
let body = request.body_json();
let instructions = body
.get("instructions")
.and_then(|v| v.as_str())
.unwrap_or_default()
.to_string();
let instructions = request.instructions_text();
assert!(
instructions.contains(marker),
"instructions did not contain profile marker; got: {instructions}"
+22 -42
View File
@@ -330,7 +330,7 @@ async fn openai_stateless_responses_requests_preserve_item_turn_metadata_across_
let first_input = first["input"].as_array().expect("first input");
let second_input = second["input"].as_array().expect("second input");
assert_eq!(&second_input[..first_input.len()], first_input.as_slice());
for item in first_input {
for item in &first_input[1..] {
assert_eq!(
item["internal_chat_message_metadata_passthrough"]["turn_id"].as_str(),
Some(first_turn_id)
@@ -1778,14 +1778,7 @@ async fn includes_base_instructions_override_in_request() {
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
let request = resp_mock.single_request();
let request_body = request.body_json();
assert!(
request_body["instructions"]
.as_str()
.unwrap()
.contains("test instructions")
);
assert_eq!(request.instructions_text(), "test instructions");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -1998,12 +1991,7 @@ async fn includes_user_instructions_message_in_request() {
let request = resp_mock.single_request();
let request_body = request.body_json();
assert!(
!request_body["instructions"]
.as_str()
.unwrap()
.contains("be nice")
);
assert!(!request.instructions_text().contains("be nice"));
assert_message_role(&request_body["input"][0], "developer");
let developer_texts = request_body["input"]
.as_array()
@@ -2019,8 +2007,8 @@ async fn includes_user_instructions_message_in_request() {
"expected permissions message to mention sandbox_mode, got {developer_texts:?}"
);
assert_message_role(&request_body["input"][1], "user");
let user_context_texts = message_input_texts(&request_body["input"][1]);
assert_message_role(&request_body["input"][2], "user");
let user_context_texts = message_input_texts(&request_body["input"][2]);
assert!(
user_context_texts
.iter()
@@ -3038,12 +3026,7 @@ async fn includes_developer_instructions_message_in_request() {
let request = resp_mock.single_request();
let request_body = request.body_json();
assert!(
!request_body["instructions"]
.as_str()
.unwrap()
.contains("be nice")
);
assert!(!request.instructions_text().contains("be nice"));
assert_message_role(&request_body["input"][0], "developer");
let developer_texts = request_body["input"]
.as_array()
@@ -3063,8 +3046,8 @@ async fn includes_developer_instructions_message_in_request() {
"expected developer instructions in a developer message, got {developer_texts:?}"
);
assert_message_role(&request_body["input"][1], "user");
let user_context_texts = message_input_texts(&request_body["input"][1]);
assert_message_role(&request_body["input"][2], "user");
let user_context_texts = message_input_texts(&request_body["input"][2]);
assert!(
user_context_texts
.iter()
@@ -3336,23 +3319,20 @@ async fn azure_responses_request_does_not_store_and_preserves_prefixed_item_ids(
assert_eq!(body["store"], serde_json::Value::Bool(false));
assert_eq!(body["stream"], serde_json::Value::Bool(true));
assert_eq!(body["input"].as_array().map(Vec::len), Some(10));
assert_eq!(body["input"][0]["id"].as_str(), Some("rs_reasoning-id"));
assert_eq!(body["input"][1]["id"].as_str(), Some("msg_message-id"));
assert_eq!(body["input"][2]["id"].as_str(), Some("ws_web-search-id"));
assert_eq!(body["input"][3]["id"].as_str(), Some("fc_function-id"));
assert_eq!(
body["input"][4]["call_id"].as_str(),
Some("function-call-id")
);
assert_eq!(body["input"][5]["id"].as_str(), Some("lsh_local-shell-id"));
assert_eq!(body["input"][6]["id"].as_str(), Some("ctc_custom-tool-id"));
assert_eq!(
body["input"][7]["call_id"].as_str(),
Some("custom-tool-call-id")
);
assert_eq!(body["input"][8].get("id"), None);
assert_eq!(body["input"][9].get("id"), None);
let input = body["input"].as_array().expect("request input");
assert_eq!(input[0]["role"], "developer");
let input = &input[1..];
assert_eq!(input.len(), 10);
assert_eq!(input[0]["id"].as_str(), Some("rs_reasoning-id"));
assert_eq!(input[1]["id"].as_str(), Some("msg_message-id"));
assert_eq!(input[2]["id"].as_str(), Some("ws_web-search-id"));
assert_eq!(input[3]["id"].as_str(), Some("fc_function-id"));
assert_eq!(input[4]["call_id"].as_str(), Some("function-call-id"));
assert_eq!(input[5]["id"].as_str(), Some("lsh_local-shell-id"));
assert_eq!(input[6]["id"].as_str(), Some("ctc_custom-tool-id"));
assert_eq!(input[7]["call_id"].as_str(), Some("custom-tool-call-id"));
assert_eq!(input[8].get("id"), None);
assert_eq!(input[9].get("id"), None);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+18 -10
View File
@@ -666,7 +666,9 @@ async fn responses_websocket_resume_prewarm_reuses_and_repairs_connection() -> a
);
let connection = server.single_connection();
assert_eq!(connection.len(), 3);
assert_eq!(connection[0].body_json()["input"], json!([]));
let prewarm = connection[0].body_json();
assert_eq!(prewarm["input"].as_array().unwrap().len(), 1);
assert_eq!(prewarm["input"][0]["role"], "developer");
assert_eq!(connection[2].body_json()["previous_response_id"], "resp-1");
let mut expected_history = connection
.iter()
@@ -2280,7 +2282,7 @@ async fn responses_websocket_creates_on_non_prefix() {
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn responses_websocket_creates_when_non_input_request_fields_change() {
async fn responses_websocket_creates_when_instructions_change() {
skip_if_no_network!();
let server = start_websocket_server(vec![vec![
@@ -2307,9 +2309,17 @@ async fn responses_websocket_creates_when_non_input_request_fields_change() {
assert_eq!(second["type"].as_str(), Some("response.create"));
assert_eq!(second.get("previous_response_id"), None);
assert_eq!(second["input"][0]["role"], "developer");
assert_eq!(
second["input"],
serde_json::to_value(&prompt_two.input).expect("serialize full input")
second["input"][0]["content"][0]["text"],
"base instructions two"
);
assert_eq!(
&second["input"].as_array().unwrap()[1..],
serde_json::to_value(&prompt_two.input)
.unwrap()
.as_array()
.unwrap()
);
assert_continuation_metrics(
@@ -2377,12 +2387,9 @@ async fn responses_websocket_v2_creates_without_previous_response_id_when_non_in
let harness = websocket_harness_with_v2(&server, /*runtime_metrics_enabled*/ true).await;
let mut session = harness.client.new_session();
let prompt_one =
prompt_with_input_and_instructions(vec![message_item("hello")], "base instructions one");
let prompt_two = prompt_with_input_and_instructions(
vec![message_item("hello"), message_item("second")],
"base instructions two",
);
let prompt_one = prompt_with_input(vec![message_item("hello")]);
let mut prompt_two = prompt_with_input(vec![message_item("hello"), message_item("second")]);
prompt_two.output_schema = Some(json!({"type": "object", "properties": {}}));
stream_until_complete(&mut session, &harness, &prompt_one).await;
stream_until_complete(&mut session, &harness, &prompt_two).await;
@@ -2615,6 +2622,7 @@ fn assistant_message_item(id: &str, text: &str) -> ResponseItem {
fn prompt_with_input(input: Vec<ResponseItem>) -> Prompt {
let mut prompt = Prompt::default();
prompt.input = input;
prompt.base_instructions.text.clear();
prompt
}
+29 -5
View File
@@ -9022,10 +9022,32 @@ async fn code_mode_oversized_websocket_yield_keeps_later_wait_incomplete() -> Re
const LIMIT: usize = 15 * 1024 * 1024;
const PROMPT: &str = "Record a call, yield, then stop";
// Keep padding outside input so it remains on incremental requests too.
// Base instructions are cached after the first request.
#[derive(Debug)]
struct RequestPadding(String);
impl codex_extension_api::ModelRequestContributor for RequestPadding {
fn request(
&self,
input: codex_extension_api::ModelRequestInput<'_>,
) -> Option<Box<dyn codex_extension_api::ModelResponseInterceptor>> {
input
.client_metadata
.get_or_insert_default()
.insert("test-padding".to_string(), self.0.clone());
None
}
}
let extensions = |padding| {
let mut registry = ExtensionRegistryBuilder::new();
registry.model_request_contributor(Arc::new(RequestPadding(padding)));
Arc::new(registry.build())
};
// Calibrate a first request with the same tools/features/turn prompt; its
// exact serialized overhead varies with the model catalog and headers.
let configure = |config: &mut Config, instructions: String| {
config.base_instructions = Some(instructions);
let configure = |config: &mut Config| {
config.base_instructions = Some(String::new());
config.model_context_window = Some(20_000_000);
config.model_auto_compact_token_limit = Some(20_000_000);
config.features.disable(Feature::TokenBudget).unwrap();
@@ -9049,7 +9071,8 @@ async fn code_mode_oversized_websocket_yield_keeps_later_wait_incomplete() -> Re
.await;
let mut probe_builder = test_codex()
.with_model("test-gpt-5.1-codex")
.with_config(move |config| configure(config, String::new()));
.with_extensions(extensions(String::new()))
.with_config(configure);
let probe = probe_builder
.build_with_websocket_server(&probe_server)
.await?;
@@ -9063,7 +9086,7 @@ async fn code_mode_oversized_websocket_yield_keeps_later_wait_incomplete() -> Re
// One 7 KiB invocation stays under the recorder's per-output argument
// budget. It pushes the yielded delta over the message budget only.
let instructions = "x".repeat(LIMIT - base_bytes - 4 * 1024);
let padding = "x".repeat(LIMIT - base_bytes - 4 * 1024);
let code = r#"
await tools.test_sync_tool({ barrier: { id: "x".repeat(7000), participants: 1 } });
text("yielded");
@@ -9084,7 +9107,8 @@ await new Promise(() => {});
.await;
let mut builder = test_codex()
.with_model("test-gpt-5.1-codex")
.with_config(move |config| configure(config, instructions));
.with_extensions(extensions(padding))
.with_config(configure);
let test = builder.build_with_websocket_server(&server).await?;
test.submit_turn(PROMPT).await?;
let connection = server.single_connection();
+8 -26
View File
@@ -1476,21 +1476,10 @@ async fn multiple_auto_compact_per_task_runs_after_token_limit_hit() {
return None;
}
let texts = value
.get("content")
.and_then(|content| content.as_array())
.into_iter()
.flatten()
.filter_map(|item| item.get("text").and_then(|text| text.as_str()));
// Ignore cached prefix messages (project docs + permissions) since they are not
// relevant to compaction behavior and can change as bundled prompts evolve.
// Ignore instruction prefixes since they are not relevant to the history
// being compacted and can change as bundled prompts evolve.
let role = value.get("role").and_then(|role| role.as_str());
if role == Some("developer")
&& texts
.into_iter()
.any(|text| text.contains("`sandbox_mode`"))
{
if role == Some("developer") {
return None;
}
if role == Some("user") {
@@ -1964,18 +1953,10 @@ async fn auto_compact_runs_after_token_limit_hit() {
.expect("follow-up request missing");
assert_eq!(follow_up_index, 3, "follow-up request should be last");
let body_first = requests[0].body_json();
let body_auto = requests[auto_compact_index].body_json();
let body_follow_up = requests[follow_up_index].body_json();
let instructions = body_auto
.get("instructions")
.and_then(|v| v.as_str())
.unwrap_or_default();
let baseline_instructions = body_first
.get("instructions")
.and_then(|v| v.as_str())
.unwrap_or_default()
.to_string();
let instructions = requests[auto_compact_index].instructions_text();
let baseline_instructions = requests[0].instructions_text();
assert_eq!(
instructions, baseline_instructions,
"auto compact should keep the standard developer instructions",
@@ -4160,7 +4141,8 @@ async fn manual_compact_retries_after_context_window_error() {
compact_input.len(),
retry_input.len()
);
if let (Some(first_before), Some(first_after)) = (compact_input.first(), retry_input.first()) {
assert_eq!(compact_input.first(), retry_input.first());
if let (Some(first_before), Some(first_after)) = (compact_input.get(1), retry_input.get(1)) {
assert_ne!(
first_before, first_after,
"retry should drop the oldest conversation item"
@@ -5858,7 +5840,7 @@ async fn remote_v2_compaction_refreshes_instructions_and_preserves_them_on_cold_
assert_single_instruction_fragment(&requests[3], &new_fragment);
let resumed_input = requests[3].input();
assert_eq!(
resumed_input.get(..replacement_history.len()),
resumed_input.get(1..=replacement_history.len()),
Some(replacement_history.as_slice()),
"remote-v2 cold resume should replay persisted replacement history verbatim"
);
@@ -237,7 +237,9 @@ async fn compact_resume_and_fork_preserve_model_history_view() {
// input after compact is a prefix of input after resume/fork
let input_after_compact = json!(requests[requests.len() - 3]["input"]);
let input_after_resume = json!(requests[requests.len() - 2]["input"]);
let input_after_fork = json!(requests[requests.len() - 1]["input"]);
let mut input_after_fork = json!(requests[requests.len() - 1]["input"]);
// The request prefix has a thread-scoped ID; retained history IDs stay unchanged.
input_after_fork[0]["id"] = input_after_compact[0]["id"].clone();
let compact_arr = input_after_compact
.as_array()
@@ -150,8 +150,8 @@ async fn first_request_item_types_roles_and_content_annotations() -> Result<()>
let mut guardian_item = request
.input()
.into_iter()
.next()
.expect("guardian approval should be the first context item");
.nth(1)
.expect("guardian approval should follow the base instructions");
guardian_item
.as_object_mut()
.expect("guardian approval should be an object")
@@ -206,6 +206,7 @@ async fn first_request_item_types_roles_and_content_annotations() -> Result<()>
.collect::<Vec<_>>()
.join("\n");
insta::assert_snapshot!(items, @r#"
message developer ["model.base_instructions"]
message developer ["guardian.approved_action"]
message developer ["generic.developer_instructions","token_budget.context_window_guidance","permissions.instructions","environments.instructions"]
message developer ["token_budget.context_window"]
@@ -4,6 +4,7 @@ use anyhow::Result;
use codex_core::ForkSnapshot;
use codex_core::StartThreadOptions;
use codex_core::TurnInputRequest;
use codex_core::TurnStartOptions;
use codex_features::Feature;
use codex_mcp::CODEX_APPS_MCP_SERVER_NAME;
use codex_model_provider::RemoteCompactionSupport;
@@ -69,10 +70,10 @@ async fn message_budget_sheds_inventory_without_changing_tool_results_or_history
assert!(arguments.to_string().len() < 8 * 1024);
assert!(call_count * arguments.to_string().len() < 1024 * 1024);
let next_arguments = json!({"plan": [{"step": "done", "status": "completed"}]});
let instruction_bytes = message_limit - if websocket { 64 * 1024 } else { 192 * 1024 };
let instructions = "padding ".repeat(instruction_bytes / 8);
// An output schema stays in every wire request, including WebSocket deltas.
let padding_bytes = message_limit - if websocket { 64 * 1024 } else { 192 * 1024 };
let schema_description = "padding ".repeat(padding_bytes / 8);
let mut builder = test_codex().with_config(move |config| {
config.base_instructions = Some(instructions);
config.model_context_window = Some(20_000_000);
config.model_auto_compact_token_limit = Some(20_000_000);
config
@@ -142,7 +143,27 @@ async fn message_budget_sheds_inventory_without_changing_tool_results_or_history
.build_with_auto_env(http_server.as_ref().expect("HTTP test server"))
.await?
};
test.submit_turn("Update the plan, then finish it").await?;
test.codex
.start_or_steer_turn(
TurnInputRequest::user_input(vec![UserInput::Text {
text: "Update the plan, then finish it".to_string(),
text_elements: Vec::new(),
}])
.on_start(TurnStartOptions {
final_output_json_schema: Some(json!({
"type": "object",
"description": schema_description,
"properties": {},
"additionalProperties": false,
})),
..Default::default()
}),
)
.await?;
wait_for_event(&test.codex, |event| {
matches!(event, EventMsg::TurnComplete(_))
})
.await;
let requests = if let Some(server) = &websocket_server {
let connection = server.single_connection();
assert_eq!(connection.len(), 4);
@@ -167,11 +188,11 @@ async fn message_budget_sheds_inventory_without_changing_tool_results_or_history
}
for (index, request) in requests.iter().enumerate() {
assert_eq!(
request["instructions"]
request["text"]["format"]["schema"]["description"]
.as_str()
.expect("request instructions")
.expect("request schema description")
.len(),
instruction_bytes
padding_bytes
);
let request_bytes = serde_json::to_vec(request)?.len();
assert!(
+1 -1
View File
@@ -1022,7 +1022,7 @@ async fn guardian_session_prewarms_and_is_reused_for_first_review(
.as_str()
.expect("Responses Lite Guardian developer instructions")
} else {
guardian_prewarm["instructions"]
guardian_prewarm["input"][0]["content"][0]["text"]
.as_str()
.expect("Guardian instructions")
};
+10 -4
View File
@@ -182,10 +182,16 @@ async fn config_personality_none_preserves_explicit_base_instructions(
let request = resp_mock.single_request();
let body = request.body_json();
// Responses requests omit the instructions field for an explicit empty override.
let expected_instructions = (!custom_instructions.is_empty())
.then(|| serde_json::Value::String(custom_instructions.to_string()));
assert_eq!(body.get("instructions"), expected_instructions.as_ref());
assert!(body.get("instructions").is_none());
if !custom_instructions.is_empty() {
assert_eq!(request.instructions_text(), custom_instructions);
}
assert!(
request
.message_input_texts("developer")
.iter()
.all(|text| !text.is_empty())
);
assert!(!request.body_contains_text(BUNDLED_FRIENDLY_TEMPLATE));
Ok(())
+22 -22
View File
@@ -279,11 +279,11 @@ async fn prompt_tools_are_consistent_across_requests(
]);
let body0 = req1.single_request().body_json();
assert_eq!(body0["instructions"], serde_json::json!(base_instructions),);
assert_eq!(req1.single_request().instructions_text(), base_instructions);
assert_tool_names(&body0, &expected_tools_names);
let body1 = req2.single_request().body_json();
assert_eq!(body1["instructions"], serde_json::json!(base_instructions),);
assert_eq!(req2.single_request().instructions_text(), base_instructions);
assert_tool_names(&body1, &expected_tools_names);
for request in [&req1, &req2] {
@@ -359,22 +359,16 @@ async fn gpt_5_tools_without_apply_patch_append_apply_patch_instructions() -> an
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
let body0 = req1.single_request().body_json();
let instructions0 = body0["instructions"]
.as_str()
.expect("instructions should be a string");
let instructions0 = req1.single_request().instructions_text();
assert!(
instructions0.contains("You are"),
"expected non-empty instructions"
);
let body1 = req2.single_request().body_json();
let instructions1 = body1["instructions"]
.as_str()
.expect("instructions should be a string");
let instructions1 = req2.single_request().instructions_text();
assert_eq!(
normalize_newlines(instructions1),
normalize_newlines(instructions0)
normalize_newlines(&instructions1),
normalize_newlines(&instructions0)
);
Ok(())
@@ -434,11 +428,11 @@ async fn prefixes_context_and_instructions_once_and_consistently_across_requests
let input1 = body1["input"].as_array().expect("input array");
assert_eq!(
input1.len(),
3,
"expected permissions + cached contextual user prefix + user msg"
4,
"expected base instructions + permissions + cached contextual user prefix + user msg"
);
let ui_text = input1[1]["content"][0]["text"]
let ui_text = input1[2]["content"][0]["text"]
.as_str()
.expect("ui message text");
assert!(
@@ -447,17 +441,17 @@ async fn prefixes_context_and_instructions_once_and_consistently_across_requests
);
let cwd_str = config.cwd.to_string_lossy();
let env_text = input1[1]["content"][1]["text"]
let env_text = input1[2]["content"][1]["text"]
.as_str()
.expect("environment context text");
assert_default_env_context(env_text, &cwd_str);
assert_eq!(
input1[1]["content"][1]["type"].as_str(),
input1[2]["content"][1]["type"].as_str(),
Some("input_text"),
"expected environment context bundled after UI message in cached contextual message"
);
assert_eq_without_metadata_or_item_ids(
input1[2].clone(),
input1[3].clone(),
text_user_input("hello 1".to_string()),
);
@@ -973,8 +967,9 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
let body1 = request1.body_json();
let body2 = request2.body_json();
let expected_permissions_msg = body1["input"][0].clone();
let expected_ui_msg = body1["input"][1].clone();
let expected_base_instructions = body1["input"][0].clone();
let expected_permissions_msg = body1["input"][1].clone();
let expected_ui_msg = body1["input"][2].clone();
let default_cwd_lossy = default_cwd.to_string_lossy();
let expected_env_text_1 = expected_ui_msg["content"][1]["text"]
@@ -993,6 +988,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
let expected_user_message_1 = text_user_input("hello 1".to_string());
let expected_input_1 = serde_json::Value::Array(vec![
expected_base_instructions.clone(),
expected_permissions_msg.clone(),
expected_contextual_user_msg_1.clone(),
expected_user_message_1.clone(),
@@ -1001,6 +997,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
let expected_user_message_2 = text_user_input("hello 2".to_string());
let expected_input_2 = serde_json::Value::Array(vec![
expected_base_instructions,
expected_permissions_msg,
expected_contextual_user_msg_1,
expected_user_message_1,
@@ -1110,8 +1107,9 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
let body1 = request1.body_json();
let body2 = request2.body_json();
let expected_permissions_msg = body1["input"][0].clone();
let expected_ui_msg = body1["input"][1].clone();
let expected_base_instructions = body1["input"][0].clone();
let expected_permissions_msg = body1["input"][1].clone();
let expected_ui_msg = body1["input"][2].clone();
let expected_env_text_1 = expected_ui_msg["content"][1]["text"]
.as_str()
@@ -1127,6 +1125,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
]);
let expected_user_message_1 = text_user_input("hello 1".to_string());
let expected_input_1 = serde_json::Value::Array(vec![
expected_base_instructions.clone(),
expected_permissions_msg.clone(),
expected_contextual_user_msg_1.clone(),
expected_user_message_1.clone(),
@@ -1168,6 +1167,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
);
let expected_user_message_2 = text_user_input("hello 2".to_string());
let expected_input_2 = serde_json::Value::Array(vec![
expected_base_instructions,
expected_permissions_msg,
expected_contextual_user_msg_1,
expected_user_message_1,
+2 -2
View File
@@ -96,7 +96,7 @@ async fn disabled_update_plan_preserves_custom_catalog_instructions() -> Result<
.await?;
test.submit_turn("hello").await?;
let request = response.single_request().body_json();
assert_eq!(request["instructions"], INSTRUCTIONS);
assert_eq!(response.single_request().instructions_text(), INSTRUCTIONS);
assert!(!request["tools"].to_string().contains("update_plan"));
Ok(())
}
@@ -1586,7 +1586,7 @@ async fn model_catalog_url_supplies_conversation_model_and_instructions() -> Res
test.submit_turn("hello").await?;
let request = response.single_request().body_json();
assert_eq!(request["model"], "gateway-conversation");
assert_eq!(request["instructions"], instructions);
assert_eq!(response.single_request().instructions_text(), instructions);
assert_eq!(request["text"].get("verbosity"), None);
Ok(())
}
+51 -29
View File
@@ -89,8 +89,10 @@ fn additional_tools(body: &Value) -> Result<&[Value]> {
.context("additional_tools tools should be an array")
}
#[test_case::test_case(false; "standard")]
#[test_case::test_case(true; "responses_lite")]
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn responses_lite_uses_input_items_for_instructions_and_tools() -> Result<()> {
async fn base_instructions_use_input_items(responses_lite: bool) -> Result<()> {
skip_if_no_network!(Ok(()));
let server = responses::start_mock_server().await;
@@ -105,8 +107,8 @@ async fn responses_lite_uses_input_items_for_instructions_and_tools() -> Result<
let builder = || {
test_codex()
.with_model_info_override("gpt-5.4", |model_info| {
model_info.use_responses_lite = true;
.with_model_info_override("gpt-5.4", move |model_info| {
model_info.use_responses_lite = responses_lite;
model_info.tool_mode = Some(ToolMode::CodeMode);
})
.with_config(|config| {
@@ -120,27 +122,21 @@ async fn responses_lite_uses_input_items_for_instructions_and_tools() -> Result<
let body = response_mock.single_request().body_json();
assert!(body.get("instructions").is_none());
assert!(body.get("tools").is_none());
let input = body["input"]
.as_array()
.context("Responses request input should be an array")?;
assert_eq!(input[0]["type"], "additional_tools");
assert_eq!(input[0]["role"], "developer");
let instructions_index = usize::from(responses_lite);
let instructions = &input[instructions_index];
assert!(
input[0]["id"]
.as_str()
.is_some_and(|id| id.starts_with("at_"))
);
assert!(
input[1]["id"]
instructions["id"]
.as_str()
.is_some_and(|id| id.starts_with("msg_"))
);
assert_eq!(
input[1],
serde_json::json!({
"id": input[1]["id"],
instructions,
&serde_json::json!({
"id": instructions["id"],
"type": "message",
"role": "developer",
"content": [{
@@ -153,20 +149,39 @@ async fn responses_lite_uses_input_items_for_instructions_and_tools() -> Result<
})
);
let tools = additional_tools(&body)?;
let functions_namespaces = tools
.iter()
.filter(|tool| tool["type"] == "namespace" && tool["name"] == "functions")
.collect::<Vec<_>>();
assert_eq!(functions_namespaces.len(), 1);
assert_eq!(functions_namespaces[0]["description"], "");
assert!(has_namespaced_tool(tools, "functions", "wait"));
assert!(has_namespaced_tool(tools, "functions", "exec"));
assert!(
tools
let tools = if responses_lite {
assert!(body.get("tools").is_none());
assert_eq!(input[0]["type"], "additional_tools");
assert_eq!(input[0]["role"], "developer");
assert!(
input[0]["id"]
.as_str()
.is_some_and(|id| id.starts_with("at_"))
);
additional_tools(&body)?
} else {
body["tools"]
.as_array()
.context("standard Responses tools should remain at the top level")?
};
if responses_lite {
let functions_namespaces = tools
.iter()
.all(|tool| { !matches!(tool["type"].as_str(), Some("function" | "custom")) })
);
.filter(|tool| tool["type"] == "namespace" && tool["name"] == "functions")
.collect::<Vec<_>>();
assert_eq!(functions_namespaces.len(), 1);
assert_eq!(functions_namespaces[0]["description"], "");
assert!(has_namespaced_tool(tools, "functions", "wait"));
assert!(has_namespaced_tool(tools, "functions", "exec"));
assert!(
tools
.iter()
.all(|tool| { !matches!(tool["type"].as_str(), Some("function" | "custom")) })
);
} else {
assert!(tools.iter().any(|tool| tool["name"] == "exec"));
assert!(tools.iter().any(|tool| tool["name"] == "wait"));
}
let client_metadata = body["client_metadata"]
.as_object()
.context("Responses request should include client metadata")?;
@@ -185,7 +200,14 @@ async fn responses_lite_uses_input_items_for_instructions_and_tools() -> Result<
.await;
let resumed = builder().restart(&server, &test).await?;
resumed.submit_turn("continue").await?;
assert_eq!(&followup.single_request().input()[..2], &input[..2]);
assert_eq!(
&followup.single_request().input()[..=instructions_index],
&input[..=instructions_index]
);
assert_eq!(
followup.single_request().body_json()["tools"],
body["tools"]
);
Ok(())
}
+1 -6
View File
@@ -148,12 +148,7 @@ async fn resume_switches_models_preserves_base_instructions() -> Result<()> {
}]))
.await?;
wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await;
let initial_body = initial_mock.single_request().body_json();
let initial_instructions = initial_body
.get("instructions")
.and_then(|v| v.as_str())
.unwrap_or_default()
.to_string();
let initial_instructions = initial_mock.single_request().instructions_text();
let resumed_mock = mount_sse_sequence(
&server,
+2 -2
View File
@@ -1261,8 +1261,8 @@ async fn review_input_isolated_from_parent_history() {
"user message should only contain the raw review prompt"
);
// Ensure the REVIEW_PROMPT rubric is sent via instructions.
let instructions = body["instructions"].as_str().expect("instructions string");
// Ensure the REVIEW_PROMPT rubric is sent as the base instructions.
let instructions = request.instructions_text();
assert_eq!(instructions, REVIEW_PROMPT);
// Also verify that a user interruption note was recorded in the rollout.
@@ -100,7 +100,7 @@ async fn incremental_tools_append_changed_catalog_without_rewriting_history(
.is_some_and(|tools| !tools.is_empty())
);
assert_eq!(
body["instructions"],
request.instructions_text(),
"Use the available tools to help the user."
);
}
@@ -7,10 +7,12 @@ Scenario: additional context is inserted before the user turn input.
## Window 1
-- request 1 (turn; Request) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/developer:
<automation_info>run one</automation_info>
02:message/user:
<external_browser_info>tab one</external_browser_info>
03:message/user:
<external_browser_info>tab one</external_browser_info>
04:message/user:
inspect the active tab
@@ -1,16 +1,17 @@
---
source: core/tests/suite/compact.rs
assertion_line: 4537
expression: "format_history_snapshot(\"Real paginated mid-turn compaction and cold resume from the bounded suffix.\",\n&requests,)"
---
Scenario: Real paginated mid-turn compaction and cold resume from the bounded suffix.
## Window 1
-- request 1 (turn) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <COLLABORATION_MODE>
01:message/developer:
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -28,17 +29,19 @@ Scenario: Real paginated mid-turn compaction and cold resume from the bounded su
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...fork_turns` to `"none"` or a positive integer string. [hash=db3545796947884f]
02:message/developer:
03:message/developer:
<MULTI_AGENT_MODE>
03:message/user:
04:message/user:
function call limit push
## Window 2 (after request 1: settings changed (parallel_tool_calls, tools))
-- request 2 (compaction) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <COLLABORATION_MODE>
01:message/developer:
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -56,21 +59,23 @@ Scenario: Real paginated mid-turn compaction and cold resume from the bounded su
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...fork_turns` to `"none"` or a positive integer string. [hash=db3545796947884f]
02:message/developer:
03:message/developer:
<MULTI_AGENT_MODE>
03:message/user:
04:message/user:
function call limit push
04:function_call/test_tool:{}
05:function_call_output:unsupported call: test_tool
06:message/user:
05:function_call/test_tool:{}
06:function_call_output:unsupported call: test_tool
07:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 2: input diverged at item 04, settings changed (parallel_tool_calls, tools))
## Window 3 (after request 2: input diverged at item 05, settings changed (parallel_tool_calls, tools))
-- request 3 (turn) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <COLLABORATION_MODE>
01:message/developer:
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -88,15 +93,15 @@ Scenario: Real paginated mid-turn compaction and cold resume from the bounded su
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...fork_turns` to `"none"` or a positive integer string. [hash=db3545796947884f]
02:message/developer:
03:message/developer:
<MULTI_AGENT_MODE>
03:message/user:
function call limit push
04:message/user:
function call limit push
05:message/user:
<COMPACTION_SUMMARY>
AUTO_SUMMARY
-- request 4 (turn) --
05:message/assistant:
06:message/assistant:
continued
06:message/user:
07:message/user:
continue after cold resume
@@ -7,69 +7,79 @@ Scenario: Manual /compact with prior user history compacts existing history and
## Window 1
-- request 1 (turn) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
first manual turn
## Window 2 (after request 1: settings changed (parallel_tool_calls, tools))
-- request 2 (compaction) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
first manual turn
03:message/assistant:
FIRST_REPLY
04:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 2: input diverged at item 03, settings changed (parallel_tool_calls, tools))
-- request 3 (turn) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
first manual turn
03:message/user:
<COMPACTION_SUMMARY>
FIRST_MANUAL_SUMMARY
04:message/user:
second manual turn
## Window 4 (after request 3: settings changed (parallel_tool_calls, tools))
-- request 4 (compaction) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
first manual turn
03:message/user:
<COMPACTION_SUMMARY>
FIRST_MANUAL_SUMMARY
04:message/user:
second manual turn
05:message/assistant:
SECOND_LARGE_REPLY
06:message/user:
<SUMMARIZATION_PROMPT>
## Window 5 (after request 4: input diverged at item 00, settings changed (parallel_tool_calls, tools))
-- request 5 (turn) --
00:message/user:
first manual turn
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
second manual turn
first manual turn
## Window 2 (after request 1: settings changed (parallel_tool_calls, tools))
-- request 2 (compaction) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
first manual turn
04:message/assistant:
FIRST_REPLY
05:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 2: input diverged at item 04, settings changed (parallel_tool_calls, tools))
-- request 3 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
first manual turn
04:message/user:
<COMPACTION_SUMMARY>
SECOND_MANUAL_SUMMARY
FIRST_MANUAL_SUMMARY
05:message/user:
second manual turn
## Window 4 (after request 3: settings changed (parallel_tool_calls, tools))
-- request 4 (compaction) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
first manual turn
04:message/user:
<COMPACTION_SUMMARY>
FIRST_MANUAL_SUMMARY
05:message/user:
second manual turn
06:message/assistant:
SECOND_LARGE_REPLY
07:message/user:
<SUMMARIZATION_PROMPT>
## Window 5 (after request 4: input diverged at item 01, settings changed (parallel_tool_calls, tools))
-- request 5 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/user:
first manual turn
02:message/developer:
<PERMISSIONS_INSTRUCTIONS>
03:message/user:
<ENVIRONMENT_CONTEXT>
04:message/user:
second manual turn
05:message/user:
<COMPACTION_SUMMARY>
SECOND_MANUAL_SUMMARY
06:message/user:
post compact follow-up
@@ -6,17 +6,21 @@ Scenario: Manual /compact with no prior user turn currently still issues a compa
## Window 1
-- request 1 (compaction; Local Compaction Request) --
00:message/user:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/user:
<SUMMARIZATION_PROMPT>
## Window 2 (after request 1: input diverged at item 00, settings changed (parallel_tool_calls, tools))
## Window 2 (after request 1: input diverged at item 01, settings changed (parallel_tool_calls, tools))
-- request 2 (turn; Local Post-Compaction History Layout) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
<COMPACTION_SUMMARY>
MANUAL_EMPTY_SUMMARY
03:message/user:
04:message/user:
AFTER_MANUAL_EMPTY_COMPACT
@@ -7,33 +7,39 @@ Scenario: True mid-turn continuation compaction after tool output: compact reque
## Window 1
-- request 1 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
function call limit push
## Window 2 (after request 1: settings changed (parallel_tool_calls, tools))
-- request 2 (compaction) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
function call limit push
03:function_call/test_tool:{}
04:function_call_output:unsupported call: test_tool
05:message/user:
04:function_call/test_tool:{}
05:function_call_output:unsupported call: test_tool
06:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 2: input diverged at item 03, settings changed (parallel_tool_calls, tools))
## Window 3 (after request 2: input diverged at item 04, settings changed (parallel_tool_calls, tools))
-- request 3 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
function call limit push
<ENVIRONMENT_CONTEXT>
03:message/user:
function call limit push
04:message/user:
<COMPACTION_SUMMARY>
AUTO_SUMMARY
@@ -7,36 +7,42 @@ Scenario: Pre-sampling compaction on model switch to a smaller context window: c
## Window 1
-- request 1 (turn; Initial Request (Previous Model)) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
before switch
## Window 2 (after request 1: settings changed (parallel_tool_calls, tools))
-- request 2 (compaction; Pre-sampling Compaction Request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
before switch
03:message/assistant:
04:message/assistant:
before switch
04:message/user:
05:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 2: input diverged at item 00, settings changed (model, parallel_tool_calls, tools))
## Window 3 (after request 2: input diverged at item 01, settings changed (model, parallel_tool_calls, tools))
-- request 3 (turn; Post-Compaction Follow-up Request (Next Model)) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <MODEL_SWITCH>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
before switch
<ENVIRONMENT_CONTEXT>
03:message/user:
before switch
04:message/user:
<COMPACTION_SUMMARY>
PRE_SAMPLING_SUMMARY
04:message/user:
05:message/user:
after switch
@@ -7,12 +7,14 @@ Scenario: Pre-turn auto-compaction context-window failure: compaction request ex
## Window 1
-- request 1 (compaction; Local Compaction Request (Incoming User Excluded)) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
USER_ONE
03:message/assistant:
04:message/assistant:
FIRST_REPLY
04:message/user:
05:message/user:
<SUMMARIZATION_PROMPT>
@@ -7,47 +7,53 @@ Scenario: Pre-turn auto-compaction uses the prior context without the incoming u
## Window 1
-- request 1 (turn) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
USER_ONE
-- request 2 (turn) --
03:message/assistant:
FIRST_REPLY
04:message/user:
USER_TWO
## Window 2 (after request 2: settings changed (parallel_tool_calls, tools))
-- request 3 (compaction) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
USER_ONE
03:message/assistant:
FIRST_REPLY
04:message/user:
USER_TWO
05:message/assistant:
SECOND_REPLY
06:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 3: input diverged at item 00, settings changed (parallel_tool_calls, tools))
-- request 4 (turn) --
00:message/user:
USER_ONE
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
USER_ONE
-- request 2 (turn) --
04:message/assistant:
FIRST_REPLY
05:message/user:
USER_TWO
## Window 2 (after request 2: settings changed (parallel_tool_calls, tools))
-- request 3 (compaction) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
USER_ONE
04:message/assistant:
FIRST_REPLY
05:message/user:
USER_TWO
06:message/assistant:
SECOND_REPLY
07:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 3: input diverged at item 01, settings changed (parallel_tool_calls, tools))
-- request 4 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/user:
USER_ONE
02:message/developer:
<PERMISSIONS_INSTRUCTIONS>
03:message/user:
<ENVIRONMENT_CONTEXT>
04:message/user:
USER_TWO
05:message/user:
<COMPACTION_SUMMARY>
PRE_TURN_SUMMARY
05:message/user[2]:
06:message/user[2]:
[01] <input_image:detail,image_url>
[02] USER_THREE
@@ -7,36 +7,42 @@ Scenario: Pre-turn compaction during model switch (without pre-sampling model-sw
## Window 1
-- request 1 (turn; Initial Request (Previous Model)) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
BEFORE_SWITCH_USER
## Window 2 (after request 1: settings changed (model, parallel_tool_calls, reasoning, text, tools))
-- request 2 (compaction; Local Compaction Request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
BEFORE_SWITCH_USER
03:message/assistant:
04:message/assistant:
BEFORE_SWITCH_REPLY
04:message/user:
05:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 2: input diverged at item 00, settings changed (parallel_tool_calls, tools))
## Window 3 (after request 2: input diverged at item 01, settings changed (parallel_tool_calls, tools))
-- request 3 (turn; Local Post-Compaction History Layout) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <MODEL_SWITCH>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
BEFORE_SWITCH_USER
<ENVIRONMENT_CONTEXT>
03:message/user:
BEFORE_SWITCH_USER
04:message/user:
<COMPACTION_SUMMARY>
PRETURN_SWITCH_SUMMARY
04:message/user:
05:message/user:
AFTER_SWITCH_USER
@@ -6,47 +6,51 @@ Scenario: Initially available deferred tools remain unchanged until disabling Ca
## Window 1
-- request 1 (turn; Initially available) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <APPS_INSTRUCTIONS>
[03] <tools>
Deferred tool namespaces:
- mcp__codex_apps__calendar: Plan events and manage your calendar.
</tools>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
inspect initially available deferred tools
-- request 2 (turn; Unchanged follow-up) --
03:message/assistant:
04:message/assistant:
done
04:message/user:
05:message/user:
inspect unchanged deferred tools
## Window 2 (after request 2: settings changed (tools))
-- request 3 (turn; Removed and empty) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <APPS_INSTRUCTIONS>
[03] <tools>
Deferred tool namespaces:
- mcp__codex_apps__calendar: Plan events and manage your calendar.
</tools>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
inspect initially available deferred tools
03:message/assistant:
04:message/assistant:
done
04:message/user:
05:message/user:
inspect unchanged deferred tools
05:message/assistant:
06:message/assistant:
done
06:message/developer:
07:message/developer:
<tools>
Removed deferred tool namespaces:
- mcp__codex_apps__calendar: Plan events and manage your calendar.
No deferred tool namespaces remain.
</tools>
07:message/user:
08:message/user:
inspect removed deferred tools
@@ -6,20 +6,22 @@ Scenario: Deferred namespaces appear after Apps recovers between sampling reques
## Window 1
-- request 1 (turn; Apps unavailable) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <tools>
Deferred tool namespaces:
- multi_agent_v1: Tools for spawning and managing sub-agents.
</tools>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
use an app after it recovers
-- request 2 (turn; Apps recovered) --
03:function_call/request_user_input:{"questions":[{"header":"Continue","id":"continue","options":[{"description":"Continue the test.","label...:"No"}],"question":"Continue after Apps recovers?"}]} [hash=31004ebd8cd711b2]
04:function_call_output:{"answers":{"continue":{"answers":["Yes (Recommended)"]}}}
05:message/developer[2]:
04:function_call/request_user_input:{"questions":[{"header":"Continue","id":"continue","options":[{"description":"Continue the test.","label...:"No"}],"question":"Continue after Apps recovers?"}]} [hash=31004ebd8cd711b2]
05:function_call_output:{"answers":{"continue":{"answers":["Yes (Recommended)"]}}}
06:message/developer[2]:
[01] <APPS_INSTRUCTIONS>
[02] <tools>
Added deferred tool namespaces:
@@ -6,34 +6,38 @@ Scenario: Persisted deferred tools remain unchanged after resuming the thread.
## Window 1
-- request 1 (items; Before resume) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <APPS_INSTRUCTIONS>
[03] <tools>
Deferred tool namespaces:
- mcp__codex_apps__calendar: Plan events and manage your calendar.
</tools>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
inspect deferred tools before resume
## Window 2 (after request 1: settings unavailable)
-- request 2 (items; After resume) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <APPS_INSTRUCTIONS>
[03] <tools>
Deferred tool namespaces:
- mcp__codex_apps__calendar: Plan events and manage your calendar.
</tools>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
inspect deferred tools before resume
03:message/assistant:
done
04:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
inspect deferred tools before resume
04:message/assistant:
done
05:message/user:
<ENVIRONMENT_CONTEXT>
06:message/user:
inspect unchanged deferred tools after resume
@@ -6,19 +6,21 @@ Scenario: Second turn changes cwd to a directory with different AGENTS.md and re
## Window 1
-- request 1 (turn; First Request (agents_one)) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/user[2]:
02:message/user[2]:
[01] <AGENTS_MD>
[02] <ENVIRONMENT_CONTEXT>
02:message/user:
03:message/user:
first turn in agents_one
-- request 2 (turn; Second Request (agents_two cwd)) --
03:message/assistant:
04:message/assistant:
turn one complete
04:message/user[2]:
05:message/user[2]:
[01] <AGENTS_MD>
[02] <ENVIRONMENT_CONTEXT>
05:message/user:
06:message/user:
second turn in agents_two
@@ -6,17 +6,19 @@ Scenario: First post-resume turn where pre-turn override sets model to rollout m
## Window 1
-- request 1 (turn; Last Request Before Resume) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
seed resume history
-- request 2 (turn; First Request After Resume + Override) --
03:message/assistant:
04:message/assistant:
recorded before resume
04:message/user:
<ENVIRONMENT_CONTEXT>
05:message/user:
<ENVIRONMENT_CONTEXT>
06:message/user:
first resumed turn after model override
@@ -6,30 +6,34 @@ Scenario: First post-resume turn where resumed config model differs from rollout
## Window 1
-- request 1 (turn; Last Request Before Resume) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
seed resume history
## Window 2 (after request 1: settings changed (model))
-- request 2 (turn; First Request After Resume) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
seed resume history
03:message/assistant:
recorded before resume
04:message/developer:
<MODEL_SWITCH>
05:message/developer:
<PERMISSIONS_INSTRUCTIONS>
06:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
seed resume history
04:message/assistant:
recorded before resume
05:message/developer:
<MODEL_SWITCH>
06:message/developer:
<PERMISSIONS_INSTRUCTIONS>
07:message/user:
<ENVIRONMENT_CONTEXT>
08:message/user:
resume and change personality
@@ -6,19 +6,21 @@ Scenario: Second turn changes cwd and approval policy while keeping model consta
## Window 1
-- request 1 (turn; First Request (Baseline)) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
first turn
-- request 2 (turn; Second Request (Turn Overrides)) --
03:message/assistant:
04:message/assistant:
turn one complete
04:message/developer:
05:message/developer:
<PERMISSIONS_INSTRUCTIONS>
05:message/user:
<ENVIRONMENT_CONTEXT>
06:message/user:
<ENVIRONMENT_CONTEXT>
07:message/user:
second turn with context updates
@@ -7,12 +7,14 @@ Scenario: /responses POST bodies with pending input
## Window 1
-- request 1 (request; First request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
first prompt
-- request 2 (request; Second request) --
03:message/assistant:
04:message/assistant:
first answer
04:agent_message
05:agent_message
@@ -7,11 +7,13 @@ Scenario: /responses POST bodies with pending input
## Window 1
-- request 1 (request; First request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
first prompt
-- request 2 (request; Second request) --
03:reasoning:summary=thinking:encrypted=true
04:agent_message
04:reasoning:summary=thinking:encrypted=true
05:agent_message
@@ -7,16 +7,18 @@ Scenario: /responses POST bodies with pending input
## Window 1
-- request 1 (request; First request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
first prompt
-- request 2 (request; Second request) --
03:reasoning:summary=thinking:encrypted=true
04:function_call/shell:{"command":"echo preserved tool call"}
05:message/assistant:
04:reasoning:summary=thinking:encrypted=true
05:function_call/shell:{"command":"echo preserved tool call"}
06:message/assistant:
first answer
06:function_call_output:unsupported call: shell
07:message/user:
07:function_call_output:unsupported call: shell
08:message/user:
second prompt
@@ -6,7 +6,9 @@ Scenario: Startup recommendations share the developer message with other context
## Window 1
-- request 1 (turn) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <APPS_INSTRUCTIONS>
[03] <recommended_plugins>
@@ -14,7 +16,7 @@ Scenario: Startup recommendations share the developer message with other context
- GitHub (github@openai-curated-remote)
</recommended_plugins>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
suggest a plugin
@@ -1,15 +1,16 @@
---
source: core/tests/suite/scenarios_agent_message_board.rs
assertion_line: 88
expression: "context_snapshot::format_context_snapshot(\"An active agent posts a shared decision and fetches the text without a self-notification.\",\n&bodies.iter().map(SnapshotEntry::body).collect::<Vec<_>>(), &ContextSnapshotOptions::default().rewrite_known_segments(),)"
expression: "context_snapshot::format_context_snapshot(\"An active agent posts a shared decision and fetches the text without a self-notification.\",\n&bodies.iter().map(SnapshotEntry::body).collect::<Vec<_>>(),\n&ContextSnapshotOptions::default().rewrite_known_segments(),)"
---
Scenario: An active agent posts a shared decision and fetches the text without a self-notification.
## Window 1
-- request 1 (request) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -27,15 +28,15 @@ Scenario: An active agent posts a shared decision and fetches the text without a
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...fork_turns` to `"none"` or a positive integer string. [hash=db3545796947884f]
02:message/developer:
03:message/developer:
<MULTI_AGENT_MODE>
03:message/user:
<ENVIRONMENT_CONTEXT>
04:message/user:
<ENVIRONMENT_CONTEXT>
05:message/user:
Record the decision on the board, notify me, and read it.
-- request 2 (request) --
05:function_call/collaboration.post:{"agents_to_notify":["/root"],"new_channel_name":"design","text":"A shared decision."}
06:function_call_output:{"author":"/root","channel_name":"design","created_at":"2026-09-18T12:00:00Z","message_id":"<UUID 1>","thread_id":"<UUID 1>"}
06:function_call/collaboration.post:{"agents_to_notify":["/root"],"new_channel_name":"design","text":"A shared decision."}
07:function_call_output:{"author":"/root","channel_name":"design","created_at":"2026-09-18T12:00:00Z","message_id":"<UUID 1>","thread_id":"<UUID 1>"}
-- request 3 (request) --
07:function_call/collaboration.search_posts:{"channel_name":"design","query":"decision"}
08:function_call_output:{"has_more":false,"n_returned":1,"next_cursor":null,"results":[{"author":"/root","channel_name":"design"...ecision.","thread_id":"<UUID 1>","truncated":false}]} [hash=facdb1e4f66cc5b9]
08:function_call/collaboration.search_posts:{"channel_name":"design","query":"decision"}
09:function_call_output:{"has_more":false,"n_returned":1,"next_cursor":null,"results":[{"author":"/root","channel_name":"design"...ecision.","thread_id":"<UUID 1>","truncated":false}]} [hash=facdb1e4f66cc5b9]
@@ -6,15 +6,17 @@ Scenario: Remote board tools and active-turn notifications share the existing se
## Window 1
-- request 1 (request) --
00:message/user:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/user:
This turn will be interrupted during notification setup.
01:message/developer:
02:message/developer:
<turn_aborted>
The previous turn was interrupted on purpose. Any running unified exec processes may still be running in...mands were aborted, they may have partially executed. [hash=cee256d92b55ad65]
</turn_aborted>
02:message/developer:
<PERMISSIONS_INSTRUCTIONS>
03:message/developer:
<PERMISSIONS_INSTRUCTIONS>
04:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -32,15 +34,15 @@ Scenario: Remote board tools and active-turn notifications share the existing se
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...fork_turns` to `"none"` or a positive integer string. [hash=db3545796947884f]
04:message/developer:
05:message/developer:
<MULTI_AGENT_MODE>
05:message/user:
<ENVIRONMENT_CONTEXT>
06:message/user:
<ENVIRONMENT_CONTEXT>
07:message/user:
Post the remote decision.
-- request 2 (request) --
07:function_call/collaboration.post:{"new_channel_name":"design","text":"A remote decision."}
08:function_call/collaboration.wait_agent:{}
09:function_call_output:{"author":"/root","channel_name":"design","created_at":"2026-09-18T12:00:00Z","message_id":"<UUID 1>","thread_id":"<UUID 1>"}
10:function_call_output:{"message":"Wait completed.","timed_out":false}
11:agent_message
08:function_call/collaboration.post:{"new_channel_name":"design","text":"A remote decision."}
09:function_call/collaboration.wait_agent:{}
10:function_call_output:{"author":"/root","channel_name":"design","created_at":"2026-09-18T12:00:00Z","message_id":"<UUID 1>","thread_id":"<UUID 1>"}
11:function_call_output:{"message":"Wait completed.","timed_out":false}
12:agent_message
@@ -7,7 +7,6 @@ Scenario: A non-deferred connector is called through code mode while another con
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -22,16 +21,18 @@ Settings:
- function/request_user_input: Request user input for one to three short questions and wait for the response. This tool is only ...; args=[questions]; hash=64a729b25c424fc6
- web_search; hash=e214d4db1bc49e89
-- request 1 (turn) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <APPS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Look up my calendar.
-- request 2 (turn) --
03:custom_tool_call/exec:text((await tools.mcp__codex_apps__calendar__lookup({})).content[0].text);
04:custom_tool_call_output:Script completed
04:custom_tool_call/exec:text((await tools.mcp__codex_apps__calendar__lookup({})).content[0].text);
05:custom_tool_call_output:Script completed
Wall time <DURATION> seconds
Output:
| calendar-lookup-ok
@@ -7,23 +7,6 @@ Scenario: Catalog Code Mode instructions and wait parameter descriptions accompa
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: You are Codex, an agent based on GPT-6. You and the user share one workspace, and your job is to collabo...them until their intended goal is completely handled. [hash=efa50f074efa5803]
# When to ask the user for permission
Use your best judgement given task context for when you really need user permission, like a competent co...ork without ending the turn to clarify with the user. [hash=ca7367e658b51388]
User authorization and preferences persist across turns. Do not request permission again when the user h... any guidelines provided in skills or external files. [hash=911f91c92c72882c]
<OMITTED 155 LINES; ~4935 TOKENS; hash=5573869716192298>
- Skill naming: If a plugin contributes skills, those skill entries are prefixed with plugin_name: in the Skills list.
- MCP naming: Plugin-provided MCP tools keep standard MCP identifiers such as mcp__server__tool; use tool provenance to tell which plugin they come from.
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
- Relevance: Determine what a plugin can help with from explicit user mention or from the plugin-associa..., MCP tools, and apps exposed elsewhere in this turn. [hash=620459a4e7b590f0]
- Missing/blocked: If the user requests a plugin that does not have relevant callable capabilities for t..., say so briefly and continue with the best fallback. [hash=746b0469a8f6cb3e]
model: "gpt-6-astra"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -48,7 +31,25 @@ Settings:
- function/wait_agent
- web_search; hash=e214d4db1bc49e89
-- request 1 (turn) --
00:message/developer[2]:
00:message/developer:
You are Codex, an agent based on GPT-6. You and the user share one workspace, and your job is to collabo...them until their intended goal is completely handled. [hash=efa50f074efa5803]
# When to ask the user for permission
Use your best judgement given task context for when you really need user permission, like a competent co...ork without ending the turn to clarify with the user. [hash=ca7367e658b51388]
User authorization and preferences persist across turns. Do not request permission again when the user h... any guidelines provided in skills or external files. [hash=911f91c92c72882c]
<OMITTED 155 LINES; ~4935 TOKENS; hash=5573869716192298>
- Skill naming: If a plugin contributes skills, those skill entries are prefixed with plugin_name: in the Skills list.
- MCP naming: Plugin-provided MCP tools keep standard MCP identifiers such as mcp__server__tool; use tool provenance to tell which plugin they come from.
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
- Relevance: Determine what a plugin can help with from explicit user mention or from the plugin-associa..., MCP tools, and apps exposed elsewhere in this turn. [hash=620459a4e7b590f0]
- Missing/blocked: If the user requests a plugin that does not have relevant callable capabilities for t..., say so briefly and continue with the best fallback. [hash=746b0469a8f6cb3e]
01:message/developer[2]:
[01] <permissions instructions>
Filesystem sandboxing defines which files can be read or written. `sandbox_mode` is `danger-full-access`...ll commands are permitted. Network access is enabled. [hash=c134061cebb94a1b]
Approval policy is currently never. Do not provide the `sandbox_permissions` for any reason, commands will be rejected.
@@ -69,7 +70,7 @@ Settings:
Never use the `request_user_input` tool for permission requests or permission-related escalations.
</collaboration_mode>
01:message/developer:
02:message/developer:
<multi_agent_role>You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -87,9 +88,9 @@ Settings:
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...ne"` or a positive integer string.</multi_agent_role> [hash=c7f52e90688299ce]
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -97,17 +98,17 @@ Settings:
<timezone><HOST_TIMEZONE></timezone>
<filesystem><workspace_roots><root><CWD></root></workspace_roots><permission_profile type="disabled"><...e="unrestricted" /></permission_profile></filesystem> [hash=d40b2f45cb028888]
</environment_context>
04:message/user:
05:message/user:
Start a code cell, yield its initial output, then wait for its completion.
-- request 2 (turn) --
05:custom_tool_call/exec:text('started'); yield_control(); text('finished');
06:custom_tool_call_output:Script running with cell ID 1
06:custom_tool_call/exec:text('started'); yield_control(); text('finished');
07:custom_tool_call_output:Script running with cell ID 1
Wall time <DURATION> seconds
Output:
| started
-- request 3 (turn) --
07:function_call/functions.wait:{"cell_id":"1"}
08:function_call_output:Script completed
08:function_call/functions.wait:{"cell_id":"1"}
09:function_call_output:Script completed
Wall time <DURATION> seconds
Output:
| finished
@@ -7,7 +7,6 @@ Scenario: Code Mode exposes explicit MCP schema limits in its prompt and runtime
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.4"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -23,13 +22,15 @@ Settings:
- web_search; hash=e214d4db1bc49e89
-- request 1 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
inspect the search tool declarations
-- request 2 (turn) --
03:custom_tool_call/exec:
04:custom_tool_call/exec:
const results = ["default_schema", "expanded_schema"].map(server => {
const description = ALL_TOOLS.find(({name}) => name === `mcp__${server}__search`)?.description ?? "";
return [description.includes("budget_description_marker"), description.includes("query: string;")];
@@ -37,7 +38,7 @@ Settings:
const shared = ALL_TOOLS.find(({name}) => name === "mcp__default_schema__shared")?.description ?? "";
results.push([shared.includes("code_mode_description_marker"), shared.includes("term: string;")]);
text(JSON.stringify(results));
04:custom_tool_call_output:Script completed
05:custom_tool_call_output:Script completed
Wall time <DURATION> seconds
Output:
| [[false,true],[true,true],[true,true]]
@@ -7,20 +7,22 @@ Scenario: Repeated content-filter blocks append catalog guidance and retain deli
## Window 1
-- request 1 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Help me with this topic.
-- request 2 (turn) --
03:message/assistant:
04:message/assistant:
I can help with this topic.
04:message/developer:
<content_filter_guidance>
Your previous response was blocked. Offer a permitted alternative.
</content_filter_guidance>
-- request 3 (turn) --
05:message/developer:
<content_filter_guidance>
Your previous response was blocked. Offer a permitted alternative.
</content_filter_guidance>
-- request 3 (turn) --
06:message/developer:
<content_filter_guidance>
Your previous response was blocked. Offer a permitted alternative.
</content_filter_guidance>
@@ -1,6 +1,5 @@
---
source: core/tests/suite/scenarios_guardian_agent_messages_tests.rs
assertion_line: 143
expression: snapshot
---
Scenario: An encrypted parent reply is delivered as a native agent message. Both Guardian reviews contain it exactly once, in order, as agent evidence. Ciphertext and decisions are mocked; this scenario verifies transport, not backend decryption or authorization outcomes.
@@ -8,17 +7,19 @@ Scenario: An encrypted parent reply is delivered as a native agent message. Both
## Window 1
-- request 1 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Check the change after the parent confirms the exact action.
-- request 2 (turn) --
03:message/assistant:
04:message/assistant:
I will wait for the parent reply before checking the change.
04:agent_message
05:agent_message
## Window 2 (after request 2: input diverged at item 00, settings changed (instructions, model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
## Window 2 (after request 2: input diverged at item 00, settings changed (model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
-- request 3 (turn) --
00:additional_tools/developer (1; hash=65a86311792f6c71):
- namespace/functions; hash=dcfbcf0da1c2d607
@@ -90,21 +91,23 @@ Scenario: An encrypted parent reply is delivered as a native agent message. Both
[12] >>> APPROVAL REQUEST END
## Window 3 (after request 3: input diverged at item 00, settings changed (instructions, model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
## Window 3 (after request 3: input diverged at item 00, settings changed (model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
-- request 4 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Check the change after the parent confirms the exact action.
03:message/assistant:
04:message/assistant:
I will wait for the parent reply before checking the change.
04:agent_message
05:function_call/exec_command:{"cmd":"exit 0","justification":"Check the requested change.","sandbox_permissions":"require_escalated"}
06:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=ae05158f838e6b05]
05:agent_message
06:function_call/exec_command:{"cmd":"exit 0","justification":"Check the requested change.","sandbox_permissions":"require_escalated"}
07:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=ae05158f838e6b05]
## Window 4 (after request 4: input diverged at item 00, settings changed (instructions, model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
## Window 4 (after request 4: input diverged at item 00, settings changed (model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
-- request 5 (turn) --
00:additional_tools/developer (1; hash=65a86311792f6c71):
- namespace/functions; hash=dcfbcf0da1c2d607
@@ -221,18 +224,20 @@ Scenario: An encrypted parent reply is delivered as a native agent message. Both
[15] >>> APPROVAL REQUEST END
## Window 5 (after request 5: input diverged at item 00, settings changed (instructions, model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
## Window 5 (after request 5: input diverged at item 00, settings changed (model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
-- request 6 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Check the change after the parent confirms the exact action.
03:message/assistant:
04:message/assistant:
I will wait for the parent reply before checking the change.
04:agent_message
05:function_call/exec_command:{"cmd":"exit 0","justification":"Check the requested change.","sandbox_permissions":"require_escalated"}
06:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=ae05158f838e6b05]
07:function_call/exec_command:{"cmd":"exit 0","justification":"Check the requested change.","sandbox_permissions":"require_escalated"}
08:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=ae05158f838e6b05]
05:agent_message
06:function_call/exec_command:{"cmd":"exit 0","justification":"Check the requested change.","sandbox_permissions":"require_escalated"}
07:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=ae05158f838e6b05]
08:function_call/exec_command:{"cmd":"exit 0","justification":"Check the requested change.","sandbox_permissions":"require_escalated"}
09:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=ae05158f838e6b05]
@@ -7,7 +7,6 @@ Scenario: An old checkpoint retains a user restriction, assistant questions, and
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -25,26 +24,27 @@ Settings:
- tool_search: # Tool discovery Searches over deferred tool metadata with BM25 and exposes matching tools for t...; args=[limit, query]; hash=400cd6ac61d524a9
- web_search; hash=f103e327c6870a46
-- request 1 (turn) --
00:compaction:encrypted=true; chars=17; hash=3733598f92aa081a
01:message/user:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:compaction:encrypted=true; chars=17; hash=3733598f92aa081a
02:message/user:
Keep the working tree unchanged.
02:message/developer:
03:message/developer:
<PERMISSIONS_INSTRUCTIONS>
03:message/user:
<ENVIRONMENT_CONTEXT>
04:message/user:
<ENVIRONMENT_CONTEXT>
05:message/user:
Confirm where publishing is allowed.
-- request 2 (turn) --
05:message/assistant:
06:message/assistant:
May I publish after these checks?
06:function_call/request_user_input:{"questions":[{"header":"Publish","id":"publish","options":[{"description":"Private repository only.","l...bel":"Nowhere"}],"question":"Where may I publish?"}]} [hash=3668d88e1035f1e3]
07:function_call_output:{"answers":{"publish":{"answers":["Private"]}}}
07:function_call/request_user_input:{"questions":[{"header":"Publish","id":"publish","options":[{"description":"Private repository only.","l...bel":"Nowhere"}],"question":"Where may I publish?"}]} [hash=3668d88e1035f1e3]
08:function_call_output:{"answers":{"publish":{"answers":["Private"]}}}
-- request 3 (compaction) --
08:compaction_trigger
09:compaction_trigger
## Window 2 (after request 3: input diverged at item 00)
Settings: relative to window 1
instructions: <removed>
model: "gpt-5.6-luna"
parallel_tool_calls: false
reasoning: {"context":"all_turns","effort":"medium"}
@@ -1,16 +1,17 @@
---
source: core/tests/suite/scenarios.rs
assertion_line: 1656
expression: snapshot
---
Scenario: A root uses Code Mode to send a confirmation and receives a real user reply; a worker then requests an action that Guardian reviews with the confirmed question as assistant context. Independent model streams are grouped as root, worker, then Guardian.
## Window 1
-- request 1 (turn) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <APPS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -28,35 +29,37 @@ Scenario: A root uses Code Mode to send a confirmation and receives a real user
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...fork_turns` to `"none"` or a positive integer string. [hash=db3545796947884f]
02:message/developer:
03:message/developer:
<MULTI_AGENT_MODE>
03:message/user:
<ENVIRONMENT_CONTEXT>
04:message/user:
<ENVIRONMENT_CONTEXT>
05:message/user:
Spawn a worker to inspect the deployment. Do not delete production data.
-- request 2 (turn) --
05:function_call/collaboration.spawn_agent:{"message":"Inspect the reviewed production deployment.","task_name":"worker"}
06:function_call_output:{"task_name":"/root/worker"}
06:function_call/collaboration.spawn_agent:{"message":"Inspect the reviewed production deployment.","task_name":"worker"}
07:function_call_output:{"task_name":"/root/worker"}
-- request 3 (turn) --
07:custom_tool_call/exec:text(await tools.mcp__codex_apps__user_message_send_message({"text":"Should I deploy the reviewed production change?"}));
08:custom_tool_call_output:Script completed
08:custom_tool_call/exec:text(await tools.mcp__codex_apps__user_message_send_message({"text":"Should I deploy the reviewed production change?"}));
09:custom_tool_call_output:Script completed
Wall time <DURATION> seconds
Output:
| {"content":[{"text":"Message sent.","type":"text"}]}
-- request 4 (turn) --
09:message/user:
10:message/user:
Yes, deploy the reviewed change.
## Window 2 (after request 4: input diverged at item 01, settings changed (tools))
## Window 2 (after request 4: input diverged at item 02, settings changed (tools))
-- request 5 (turn) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <APPS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Spawn a worker to inspect the deployment. Do not delete production data.
03:message/developer:
04:message/developer:
You are an agent in a team of agents collaborating to complete a task.
You can spawn sub-agents to handle subtasks, and those sub-agents can spawn their own sub-agents. All ag...nd capable, and have access to the same set of tools. [hash=876a93c54d3f61d6]
@@ -74,14 +77,14 @@ Scenario: A root uses Code Mode to send a confirmation and receives a real user
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...fork_turns` to `"none"` or a positive integer string. [hash=db3545796947884f]
04:message/developer:
05:message/developer:
<MULTI_AGENT_MODE>
05:agent_message
06:agent_message
-- request 6 (turn) --
06:function_call/exec_command:{"cmd":"true","justification":"Review the production deployment.","sandbox_permissions":"require_escalated"}
07:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=a46b43b96328695b]
07:function_call/exec_command:{"cmd":"true","justification":"Review the production deployment.","sandbox_permissions":"require_escalated"}
08:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=a46b43b96328695b]
## Window 3 (after request 6: input diverged at item 00, settings changed (instructions, model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
## Window 3 (after request 6: input diverged at item 00, settings changed (model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
-- request 7 (turn) --
00:additional_tools/developer (1; hash=65a86311792f6c71):
- namespace/functions; hash=dcfbcf0da1c2d607
@@ -7,23 +7,6 @@ Scenario: Guardian reviews an escalated command against a restrictive user goal
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -41,11 +24,29 @@ Settings:
- tool_search: # Tool discovery Searches over deferred tool metadata with BM25 and exposes matching tools for t...; args=[limit, query]; hash=400cd6ac61d524a9
- web_search; hash=f103e327c6870a46
-- request 1 (turn) --
00:message/user:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/user:
<codex_internal_context source="user_goal">
User set the goal: "Inspect the workspace; do not run commands outside the sandbox."
</codex_internal_context>
01:message/developer:
02:message/developer:
<permissions instructions>
Filesystem sandboxing defines which files can be read or written. `sandbox_mode` is `read-only`: The san... permits reading files. Network access is restricted. [hash=be7da4425f89053c]
# Escalation Requests
@@ -63,7 +64,7 @@ Settings:
`approvals_reviewer` is `auto_review`: Sandbox escalations with require_escalated will be reviewed for c...he risk and send a final message to ask for approval. [hash=c592d119d24cd2d6]
</permissions instructions>
02:message/user:
03:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -71,12 +72,11 @@ Settings:
<timezone><HOST_TIMEZONE></timezone>
<filesystem><workspace_roots><root><CWD></root></workspace_roots><permission_profile type="managed"><f...ntry></file_system></permission_profile></filesystem> [hash=e8c1de60307d0a3d]
</environment_context>
03:message/user:
04:message/user:
Check the workspace.
## Window 2 (after request 1: input diverged at item 00)
Settings: relative to window 1
instructions: <removed>
model: "gpt-5.6-luna"
parallel_tool_calls: false
prompt_cache_key: "<PROMPT_CACHE_KEY 2>"
@@ -180,11 +180,29 @@ Settings: relative to window 1
## Window 3 (after request 2: input diverged at item 00)
Settings: same as window 1
-- request 3 (turn) --
00:message/user:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/user:
<codex_internal_context source="user_goal">
User set the goal: "Inspect the workspace; do not run commands outside the sandbox."
</codex_internal_context>
01:message/developer:
02:message/developer:
<permissions instructions>
Filesystem sandboxing defines which files can be read or written. `sandbox_mode` is `read-only`: The san... permits reading files. Network access is restricted. [hash=be7da4425f89053c]
# Escalation Requests
@@ -202,7 +220,7 @@ Settings: same as window 1
`approvals_reviewer` is `auto_review`: Sandbox escalations with require_escalated will be reviewed for c...he risk and send a final message to ask for approval. [hash=c592d119d24cd2d6]
</permissions instructions>
02:message/user:
03:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -210,7 +228,7 @@ Settings: same as window 1
<timezone><HOST_TIMEZONE></timezone>
<filesystem><workspace_roots><root><CWD></root></workspace_roots><permission_profile type="managed"><f...ntry></file_system></permission_profile></filesystem> [hash=e8c1de60307d0a3d]
</environment_context>
03:message/user:
04:message/user:
Check the workspace.
04:function_call/exec_command:{"cmd":"exit 0","justification":"Run a check outside the sandbox.","sandbox_permissions":"require_escalated"}
05:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=7efc66669dfbbca8]
05:function_call/exec_command:{"cmd":"exit 0","justification":"Run a check outside the sandbox.","sandbox_permissions":"require_escalated"}
06:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=7efc66669dfbbca8]
@@ -7,10 +7,12 @@ Scenario: Three scheduled runs share one instruction body, a human overrides its
## Window 1
-- request 1 (request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
<heartbeat>
<automation_id>monitor</automation_id>
<current_time_iso>2026-01-01T00:00:00Z</current_time_iso>
@@ -20,9 +22,9 @@ Scenario: Three scheduled runs share one instruction body, a human overrides its
</heartbeat>
-- request 2 (request) --
03:message/assistant:
04:message/assistant:
Recorded this input.
04:message/user:
05:message/user:
<heartbeat>
<automation_id>monitor</automation_id>
<current_time_iso>2026-01-01T00:01:00Z</current_time_iso>
@@ -32,14 +34,14 @@ Scenario: Three scheduled runs share one instruction body, a human overrides its
</heartbeat>
-- request 3 (request) --
05:message/assistant:
06:message/assistant:
Recorded this input.
06:message/user:
07:message/user:
Create a new worktree for the fix; this overrides the monitor's no-worktree restriction.
-- request 4 (request) --
07:message/assistant:
08:message/assistant:
Recorded this input.
08:message/user:
09:message/user:
<heartbeat>
<automation_id>monitor</automation_id>
<current_time_iso>2026-01-01T00:03:00Z</current_time_iso>
@@ -49,12 +51,12 @@ Scenario: Three scheduled runs share one instruction body, a human overrides its
</heartbeat>
-- request 5 (request) --
09:message/assistant:
10:message/assistant:
Recorded this input.
10:message/user:
11:message/user:
Check the fix in the requested worktree.
## Window 2 (after request 5: input diverged at item 00, settings changed (instructions, model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
## Window 2 (after request 5: input diverged at item 00, settings changed (model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
-- request 6 (request) --
00:additional_tools/developer (1; hash=65a86311792f6c71):
- namespace/functions; hash=dcfbcf0da1c2d607
@@ -167,13 +169,15 @@ Scenario: Three scheduled runs share one instruction body, a human overrides its
[29] >>> APPROVAL REQUEST END
## Window 3 (after request 6: input diverged at item 00, settings changed (instructions, model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
## Window 3 (after request 6: input diverged at item 00, settings changed (model, parallel_tool_calls, prompt_cache_key, reasoning, text, tools))
-- request 7 (request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
<heartbeat>
<automation_id>monitor</automation_id>
<current_time_iso>2026-01-01T00:00:00Z</current_time_iso>
@@ -182,9 +186,9 @@ Scenario: Three scheduled runs share one instruction body, a human overrides its
</instructions>
</heartbeat>
03:message/assistant:
04:message/assistant:
Recorded this input.
04:message/user:
05:message/user:
<heartbeat>
<automation_id>monitor</automation_id>
<current_time_iso>2026-01-01T00:01:00Z</current_time_iso>
@@ -193,13 +197,13 @@ Scenario: Three scheduled runs share one instruction body, a human overrides its
</instructions>
</heartbeat>
05:message/assistant:
06:message/assistant:
Recorded this input.
06:message/user:
07:message/user:
Create a new worktree for the fix; this overrides the monitor's no-worktree restriction.
07:message/assistant:
08:message/assistant:
Recorded this input.
08:message/user:
09:message/user:
<heartbeat>
<automation_id>monitor</automation_id>
<current_time_iso>2026-01-01T00:03:00Z</current_time_iso>
@@ -208,9 +212,9 @@ Scenario: Three scheduled runs share one instruction body, a human overrides its
</instructions>
</heartbeat>
09:message/assistant:
10:message/assistant:
Recorded this input.
10:message/user:
11:message/user:
Check the fix in the requested worktree.
11:function_call/exec_command:{"cmd":"exit 0","justification":"Check the explicitly requested change.","sandbox_permissions":"require_escalated"}
12:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=1920af4a5ed341ad]
12:function_call/exec_command:{"cmd":"exit 0","justification":"Check the explicitly requested change.","sandbox_permissions":"require_escalated"}
13:function_call_output:exec_command failed: CreateProcess { message: "Rejected(\\"This action was rejected due to unacceptable r...e risk. Otherwise, stop and request user input.\\")" } [hash=1920af4a5ed341ad]
@@ -7,7 +7,6 @@ Scenario: Catalog namespace and raw MCP server prefixes annotate embedded docs a
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -23,24 +22,26 @@ Settings:
- web_search; hash=e214d4db1bc49e89
-- request 1 (turn) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
<MODEL_INSTRUCTIONS>
01:message/developer:
Coordinate sub-agents.
<PERMISSIONS_INSTRUCTIONS>
02:message/developer:
Coordinate sub-agents.
03:message/developer:
<MULTI_AGENT_MODE>
03:message/user:
<ENVIRONMENT_CONTEXT>
04:message/user:
<ENVIRONMENT_CONTEXT>
05:message/user:
Find echo, call it, and list the agents.
-- request 2 (turn) --
05:custom_tool_call/exec:
06:custom_tool_call/exec:
const descriptions = ["view_image", "collaboration__list_agents", "mcp__reports_one__echo"]
.map(name => ALL_TOOLS.find(t => t.name === name).description);
const report = await tools.mcp__reports_one__echo({message: "ping"});
const agents = await tools.collaboration__list_agents({});
text({descriptions, echo: report.structuredContent.echo, agent: agents.agents[0].agent_name});
06:custom_tool_call_output:Script completed
07:custom_tool_call_output:Script completed
Wall time <DURATION> seconds
Output:
| {"descriptions":["Functions context.\\n\\nView a local image file from the filesystem when visual inspecti...>>; };\\n```"],"echo":"ECHOING: ping","agent":"/root"} [hash=22aad8f340003b22]
@@ -52,41 +53,43 @@ Settings: relative to window 1
~ custom/exec: Run JavaScript code to orchestrate/compose tool calls - Evaluates the provided JavaScript code in...; hash=b1c19da7942f5c47
-- request 3 (turn) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
<MODEL_INSTRUCTIONS>
01:message/developer:
Coordinate sub-agents.
<PERMISSIONS_INSTRUCTIONS>
02:message/developer:
Coordinate sub-agents.
03:message/developer:
<MULTI_AGENT_MODE>
03:message/user:
<ENVIRONMENT_CONTEXT>
04:message/user:
<ENVIRONMENT_CONTEXT>
05:message/user:
Find echo, call it, and list the agents.
05:custom_tool_call/exec:
06:custom_tool_call/exec:
const descriptions = ["view_image", "collaboration__list_agents", "mcp__reports_one__echo"]
.map(name => ALL_TOOLS.find(t => t.name === name).description);
const report = await tools.mcp__reports_one__echo({message: "ping"});
const agents = await tools.collaboration__list_agents({});
text({descriptions, echo: report.structuredContent.echo, agent: agents.agents[0].agent_name});
06:custom_tool_call_output:Script completed
07:custom_tool_call_output:Script completed
Wall time <DURATION> seconds
Output:
| {"descriptions":["Functions context.\\n\\nView a local image file from the filesystem when visual inspecti...>>; };\\n```"],"echo":"ECHOING: ping","agent":"/root"} [hash=22aad8f340003b22]
07:message/assistant:
08:message/assistant:
Done.
08:message/developer:
09:message/developer:
<MODEL_SWITCH>
09:message/user:
10:message/user:
Find echo again, call it, and list the agents.
-- request 4 (turn) --
10:custom_tool_call/exec:
11:custom_tool_call/exec:
const descriptions = ["view_image", "collaboration__list_agents", "mcp__reports_one__echo"]
.map(name => ALL_TOOLS.find(t => t.name === name).description);
const report = await tools.mcp__reports_one__echo({message: "ping"});
const agents = await tools.collaboration__list_agents({});
text({descriptions, echo: report.structuredContent.echo, agent: agents.agents[0].agent_name});
11:custom_tool_call_output:Script completed
12:custom_tool_call_output:Script completed
Wall time <DURATION> seconds
Output:
| {"descriptions":["View a local image file from the filesystem when visual inspection is needed. Use this...>>; };\\n```"],"echo":"ECHOING: ping","agent":"/root"} [hash=6ecfde0f75e5f051]
@@ -7,13 +7,15 @@ Scenario: Worker messages arrive during a response. Deferred mailbox preemption
## Window 1
-- request 1 (request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Plan the next action while the worker finishes.
-- request 2 (request) --
03:message/assistant:
04:message/assistant:
I will update the plan.
04:agent_message
05:agent_message
06:agent_message
@@ -7,15 +7,17 @@ Scenario: Worker messages arrive during a response. Deferred mailbox preemption
## Window 1
-- request 1 (request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Plan the next action while the worker finishes.
-- request 2 (request) --
03:message/assistant:
04:message/assistant:
I will update the plan.
04:function_call/update_plan:{"plan":[{"status":"in_progress","step":"Reply to the user"}]}
05:function_call_output:Plan updated
06:agent_message
05:function_call/update_plan:{"plan":[{"status":"in_progress","step":"Reply to the user"}]}
06:function_call_output:Plan updated
07:agent_message
08:agent_message
@@ -7,12 +7,14 @@ Scenario: Worker messages arrive during a response. Deferred mailbox preemption
## Window 1
-- request 1 (request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Plan the next action while the worker finishes.
-- request 2 (request) --
03:reasoning:summary=Preparing the next action:encrypted=true
04:agent_message
04:reasoning:summary=Preparing the next action:encrypted=true
05:agent_message
06:agent_message
@@ -7,14 +7,16 @@ Scenario: Worker messages arrive during a response. Deferred mailbox preemption
## Window 1
-- request 1 (request) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Plan the next action while the worker finishes.
-- request 2 (request) --
03:reasoning:summary=Preparing the next action:encrypted=true
04:function_call/update_plan:{"plan":[{"status":"in_progress","step":"Reply to the user"}]}
05:function_call_output:Plan updated
06:agent_message
04:reasoning:summary=Preparing the next action:encrypted=true
05:function_call/update_plan:{"plan":[{"status":"in_progress","step":"Reply to the user"}]}
06:function_call_output:Plan updated
07:agent_message
08:agent_message
@@ -7,23 +7,6 @@ Scenario: Catalog resource descriptions and parameter guidance accompany discove
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: You are Codex, an agent based on GPT-6. You and the user share one workspace, and your job is to collabo...them until their intended goal is completely handled. [hash=efa50f074efa5803]
# When to ask the user for permission
Use your best judgement given task context for when you really need user permission, like a competent co...ork without ending the turn to clarify with the user. [hash=ca7367e658b51388]
User authorization and preferences persist across turns. Do not request permission again when the user h... any guidelines provided in skills or external files. [hash=911f91c92c72882c]
<OMITTED 155 LINES; ~4935 TOKENS; hash=5573869716192298>
- Skill naming: If a plugin contributes skills, those skill entries are prefixed with plugin_name: in the Skills list.
- MCP naming: Plugin-provided MCP tools keep standard MCP identifiers such as mcp__server__tool; use tool provenance to tell which plugin they come from.
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
- Relevance: Determine what a plugin can help with from explicit user mention or from the plugin-associa..., MCP tools, and apps exposed elsewhere in this turn. [hash=620459a4e7b590f0]
- Missing/blocked: If the user requests a plugin that does not have relevant callable capabilities for t..., say so briefly and continue with the best fallback. [hash=746b0469a8f6cb3e]
model: "gpt-6-astra"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -48,7 +31,25 @@ Settings:
- function/wait_agent
- web_search; hash=e214d4db1bc49e89
-- request 1 (turn) --
00:message/developer[2]:
00:message/developer:
You are Codex, an agent based on GPT-6. You and the user share one workspace, and your job is to collabo...them until their intended goal is completely handled. [hash=efa50f074efa5803]
# When to ask the user for permission
Use your best judgement given task context for when you really need user permission, like a competent co...ork without ending the turn to clarify with the user. [hash=ca7367e658b51388]
User authorization and preferences persist across turns. Do not request permission again when the user h... any guidelines provided in skills or external files. [hash=911f91c92c72882c]
<OMITTED 155 LINES; ~4935 TOKENS; hash=5573869716192298>
- Skill naming: If a plugin contributes skills, those skill entries are prefixed with plugin_name: in the Skills list.
- MCP naming: Plugin-provided MCP tools keep standard MCP identifiers such as mcp__server__tool; use tool provenance to tell which plugin they come from.
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
- Relevance: Determine what a plugin can help with from explicit user mention or from the plugin-associa..., MCP tools, and apps exposed elsewhere in this turn. [hash=620459a4e7b590f0]
- Missing/blocked: If the user requests a plugin that does not have relevant callable capabilities for t..., say so briefly and continue with the best fallback. [hash=746b0469a8f6cb3e]
01:message/developer[2]:
[01] <permissions instructions>
Filesystem sandboxing defines which files can be read or written. `sandbox_mode` is `danger-full-access`...ll commands are permitted. Network access is enabled. [hash=c134061cebb94a1b]
Approval policy is currently never. Do not provide the `sandbox_permissions` for any reason, commands will be rejected.
@@ -69,7 +70,7 @@ Settings:
Never use the `request_user_input` tool for permission requests or permission-related escalations.
</collaboration_mode>
01:message/developer:
02:message/developer:
<multi_agent_role>You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -87,9 +88,9 @@ Settings:
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
Full-history forks (`fork_turns` omitted or `"all"`) inherit the parent model and reasoning effort and d...ne"` or a positive integer string.</multi_agent_role> [hash=c7f52e90688299ce]
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -97,13 +98,13 @@ Settings:
<timezone><HOST_TIMEZONE></timezone>
<filesystem><workspace_roots><root><WORKSPACE_ROOT 1></root></workspace_roots><permission_profile type...e="unrestricted" /></permission_profile></filesystem> [hash=0592734c170299c1]
</environment_context>
04:message/user:
05:message/user:
List the available resources and templates, then read the example note.
-- request 2 (turn) --
05:custom_tool_call/exec:text(await tools.list_mcp_resources({"server":"resources"}));
06:custom_tool_call/exec:text(await tools.list_mcp_resources({"server":"resources"}));
text(await tools.list_mcp_resource_templates({"server":"resources"}));
text(await tools.read_mcp_resource({"server":"resources","uri":"memo://codex/example-note"}));
06:custom_tool_call_output:Script completed
07:custom_tool_call_output:Script completed
Wall time <DURATION> seconds
Output:
| {"server":"resources","resources":[{"server":"resources","uri":"memo://codex/example-note","name":"examp...ed for integration tests.","mimeType":"text/plain"}]} [hash=75d187638a7af2d4] | {"server":"resources","resourceTemplates":[{"server":"resources","uriTemplate":"memo://codex/{slug}","na... resources used in tests.","mimeType":"text/plain"}]} [hash=b1c7082eb114fc9b] | {"server":"resources","uri":"memo://codex/example-note","contents":[{"uri":"memo://codex/example-note","...mple MCP resource served by the rmcp test server."}]} [hash=45385fc57640b555]
@@ -7,7 +7,6 @@ Scenario: Catalog refreshes append the updated listing once while preserving too
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: Test model instructions.
model: "visible-model"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -28,7 +27,9 @@ Settings:
- function/wait_agent
- web_search; hash=8586237e354ee5ed
-- request 1 (turn) --
00:message/developer[2]:
00:message/developer:
Test model instructions.
01:message/developer[2]:
[01] <permissions instructions>
Filesystem sandboxing defines which files can be read or written. `sandbox_mode` is `danger-full-access`...ll commands are permitted. Network access is enabled. [hash=c134061cebb94a1b]
Approval policy is currently never. Do not provide the `sandbox_permissions` for any reason, commands will be rejected.
@@ -36,15 +37,15 @@ Settings:
[02] <model_catalog>
- `visible-model`: Fast and capable Reasoning efforts: low, medium (default), high. Service tiers: priority.
</model_catalog>
01:message/user:
02:message/user:
hello
-- request 2 (turn) --
02:message/developer:
03:message/developer:
<model_catalog>
- `visible-model`: Updated picker copy Reasoning efforts: low, medium (default), high. Service tiers: priority.
</model_catalog>
03:message/user:
04:message/user:
after catalog refresh
-- request 3 (turn) --
04:message/user:
05:message/user:
without another catalog change
@@ -7,6 +7,24 @@ Scenario: Resolved local MXC selection preserves workspace-write permissions in
## Window 1
-- request 1 (turn) --
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 132 LINES; ~4881 TOKENS; hash=929bd18f6c969eb9>
- Never talk about goblins, gremlins, raccoons, trolls, ogres, pigeons, or other animals or creatures un...utely and unambiguously relevant to the user's query. [hash=c638556ac82c203c]
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer:
<permissions instructions>
Filesystem sandboxing defines which files can be read or written. `sandbox_mode` is `workspace-write`: T...ries requires approval. Network access is restricted. [hash=99963de5837f6638]
# Escalation Requests
@@ -24,7 +42,7 @@ Scenario: Resolved local MXC selection preserves workspace-write permissions in
- ["cargo", "test"]
The writable root is `<WORKSPACE_ROOT 1>`.
</permissions instructions>
01:message/user:
02:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -32,5 +50,5 @@ Scenario: Resolved local MXC selection preserves workspace-write permissions in
<timezone><HOST_TIMEZONE></timezone>
<filesystem><workspace_roots><root><WORKSPACE_ROOT 1></root></workspace_roots><permission_profile type...ntry></file_system></permission_profile></filesystem> [hash=e9b73aecc0d54647]
</environment_context>
02:message/user:
03:message/user:
Inspect the sandbox.
@@ -7,7 +7,6 @@ Scenario: Custom provider overrides keep unrestricted search cached and enable V
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -31,8 +30,10 @@ Settings:
- web_search; hash=f103e327c6870a46
-- request 1 (turn) --
00:message/developer:
<PERMISSIONS_INSTRUCTIONS>
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
@@ -50,11 +51,11 @@ Settings:
When calling `wait_agent`, prefer longer waits (minutes) to avoid busy polling.
There are 4 available concurrency slots, meaning that up to 4 agents can be active at once, including you.
02:message/developer:
03:message/developer:
<MULTI_AGENT_MODE>
03:message/user:
<ENVIRONMENT_CONTEXT>
04:message/user:
<ENVIRONMENT_CONTEXT>
05:message/user:
Check the configuration.
-- request 2 (compaction) --
05:compaction_trigger
06:compaction_trigger
@@ -7,7 +7,6 @@ Scenario: A read-only thread receives only read tools from the MCP server and ex
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -36,12 +35,14 @@ Settings:
- web_search; hash=e214d4db1bc49e89
-- request 1 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Read the report.
-- request 2 (turn) --
03:function_call/mcp__policy.read:{}
04:function_call_output:Wall time: <DURATION> seconds
04:function_call/mcp__policy.read:{}
05:function_call_output:Wall time: <DURATION> seconds
Output: | Report ready.
@@ -7,6 +7,24 @@ Scenario: A host replaces the provider after the parent restarts, then updates a
## Window 1
-- request 1 (turn) --
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 132 LINES; ~4881 TOKENS; hash=929bd18f6c969eb9>
- Never talk about goblins, gremlins, raccoons, trolls, ogres, pigeons, or other animals or creatures un...utely and unambiguously relevant to the user's query. [hash=c638556ac82c203c]
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer:
<permissions instructions>
Filesystem sandboxing defines which files can be read or written. `sandbox_mode` is `read-only`: The san... permits reading files. Network access is restricted. [hash=be7da4425f89053c]
# Escalation Requests
@@ -24,7 +42,7 @@ Scenario: A host replaces the provider after the parent restarts, then updates a
- ["gh", "pr", "check"]
- ["cargo", "test"]
</permissions instructions>
01:message/user[2]:
02:message/user[2]:
[01] # AGENTS.md instructions
<INSTRUCTIONS>
@@ -40,10 +58,10 @@ Scenario: A host replaces the provider after the parent restarts, then updates a
- <UUID 1>
</subagents>
</environment_context>
02:message/user:
03:message/user:
continue with the current instructions
-- request 2 (turn) --
03:message/user:
04:message/user:
# AGENTS.md instructions
<INSTRUCTIONS>
@@ -51,24 +69,42 @@ Scenario: A host replaces the provider after the parent restarts, then updates a
Never send email.
</INSTRUCTIONS>
04:message/user:
05:message/user:
continue with the current instructions
-- request 3 (turn) --
05:message/user:
06:message/user:
# AGENTS.md instructions
<INSTRUCTIONS>
The previously provided AGENTS.md instructions no longer apply.
</INSTRUCTIONS>
06:message/user:
continue with the current instructions
-- request 4 (turn) --
07:message/user:
continue with the current instructions
-- request 4 (turn) --
08:message/user:
continue with the current instructions
## Window 2 (after request 4: input diverged at item 01, settings changed (prompt_cache_key))
## Window 2 (after request 4: input diverged at item 02, settings changed (prompt_cache_key))
-- request 5 (turn) --
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 132 LINES; ~4881 TOKENS; hash=929bd18f6c969eb9>
- Never talk about goblins, gremlins, raccoons, trolls, ogres, pigeons, or other animals or creatures un...utely and unambiguously relevant to the user's query. [hash=c638556ac82c203c]
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer:
<permissions instructions>
Filesystem sandboxing defines which files can be read or written. `sandbox_mode` is `read-only`: The san... permits reading files. Network access is restricted. [hash=be7da4425f89053c]
# Escalation Requests
@@ -86,7 +122,7 @@ Scenario: A host replaces the provider after the parent restarts, then updates a
- ["gh", "pr", "check"]
- ["cargo", "test"]
</permissions instructions>
01:message/user[2]:
02:message/user[2]:
[01] # AGENTS.md instructions
<INSTRUCTIONS>
@@ -99,10 +135,10 @@ Scenario: A host replaces the provider after the parent restarts, then updates a
<timezone><HOST_TIMEZONE></timezone>
<filesystem><workspace_roots><root><CWD></root></workspace_roots><permission_profile type="managed"><f...ntry></file_system></permission_profile></filesystem> [hash=e8c1de60307d0a3d]
</environment_context>
02:message/user:
03:message/user:
continue with the current instructions
-- request 6 (turn) --
03:message/user:
04:message/user:
# AGENTS.md instructions
<INSTRUCTIONS>
@@ -110,17 +146,17 @@ Scenario: A host replaces the provider after the parent restarts, then updates a
Never send email.
</INSTRUCTIONS>
04:message/user:
05:message/user:
continue with the current instructions
-- request 7 (turn) --
05:message/user:
06:message/user:
# AGENTS.md instructions
<INSTRUCTIONS>
The previously provided AGENTS.md instructions no longer apply.
</INSTRUCTIONS>
06:message/user:
continue with the current instructions
-- request 8 (turn) --
07:message/user:
continue with the current instructions
-- request 8 (turn) --
08:message/user:
continue with the current instructions
@@ -7,7 +7,6 @@ Scenario: A subagent waits for an MCP browser sign-in prompt, then receives the
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -29,12 +28,14 @@ Settings:
- web_search; hash=f103e327c6870a46
-- request 1 (turn) --
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer:
<PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Run the input tool.
-- request 2 (turn) --
03:function_call/mcp__elicitation.request_input:{}
04:function_call_output:Wall time: <DURATION> seconds
04:function_call/mcp__elicitation.request_input:{}
05:function_call_output:Wall time: <DURATION> seconds
Output: | {"action": "accept", "content": {}}
@@ -6,15 +6,33 @@ Scenario: A parent spawns a child before the selected environment is configured.
## Window 1
-- request 1 (request; parent delegates while the environment is starting) --
00:message/developer[2]:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <ENVIRONMENTS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
<STANDARD_MULTI_AGENT_INSTRUCTIONS>
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<environments>
<environment id="<ENVIRONMENT>">
@@ -25,23 +43,41 @@ Scenario: A parent spawns a child before the selected environment is configured.
<current_date><CURRENT_DATE></current_date>
<timezone><HOST_TIMEZONE></timezone>
</environment_context>
04:message/user:
05:message/user:
Delegate waiting for the shared workspace, and report what the worker finds.
-- request 2 (request; parent waits for the worker) --
05:function_call/collaboration.spawn_agent:{"fork_turns":"none","message":"Wait for the shared workspace to become ready.","task_name":"worker"}
06:function_call_output:{"task_name":"/root/worker"}
06:function_call/collaboration.spawn_agent:{"fork_turns":"none","message":"Wait for the shared workspace to become ready.","task_name":"worker"}
07:function_call_output:{"task_name":"/root/worker"}
## Window 2 (after request 2: input diverged at item 01, settings changed (tools))
## Window 2 (after request 2: input diverged at item 02, settings changed (tools))
-- request 3 (request; child sees the inherited starting environment) --
00:message/developer[2]:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <ENVIRONMENTS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
You are an agent in a team of agents collaborating to complete a task.
<STANDARD_MULTI_AGENT_INSTRUCTIONS>
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<environments>
<environment id="<ENVIRONMENT>">
@@ -52,11 +88,11 @@ Scenario: A parent spawns a child before the selected environment is configured.
<current_date><CURRENT_DATE></current_date>
<timezone><HOST_TIMEZONE></timezone>
</environment_context>
04:agent_message
05:agent_message
-- request 4 (request; child receives the ready result and updated environment) --
05:function_call/functions.wait_for_environment:{"environment_id":"<ENVIRONMENT>"}
06:function_call_output:{"environment_id":"<ENVIRONMENT>","status":"ready"}
07:message/user:
06:function_call/functions.wait_for_environment:{"environment_id":"<ENVIRONMENT>"}
07:function_call_output:{"environment_id":"<ENVIRONMENT>","status":"ready"}
08:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -65,17 +101,35 @@ Scenario: A parent spawns a child before the selected environment is configured.
<filesystem><workspace_roots><root><CWD></root></workspace_roots><permission_profile type="managed"><f...ntry></file_system></permission_profile></filesystem> [hash=e8c1de60307d0a3d]
</environment_context>
## Window 3 (after request 4: input diverged at item 01, settings changed (tools))
## Window 3 (after request 4: input diverged at item 02, settings changed (tools))
-- request 5 (request; parent receives the child result) --
00:message/developer[2]:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <ENVIRONMENTS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
<STANDARD_MULTI_AGENT_INSTRUCTIONS>
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<environments>
<environment id="<ENVIRONMENT>">
@@ -86,14 +140,14 @@ Scenario: A parent spawns a child before the selected environment is configured.
<current_date><CURRENT_DATE></current_date>
<timezone><HOST_TIMEZONE></timezone>
</environment_context>
04:message/user:
05:message/user:
Delegate waiting for the shared workspace, and report what the worker finds.
05:function_call/collaboration.spawn_agent:{"fork_turns":"none","message":"Wait for the shared workspace to become ready.","task_name":"worker"}
06:function_call_output:{"task_name":"/root/worker"}
07:function_call/collaboration.wait_agent:{"timeout_ms":10000}
08:function_call_output:{"message":"Wait completed.","timed_out":false}
09:agent_message
10:message/user:
06:function_call/collaboration.spawn_agent:{"fork_turns":"none","message":"Wait for the shared workspace to become ready.","task_name":"worker"}
07:function_call_output:{"task_name":"/root/worker"}
08:function_call/collaboration.wait_agent:{"timeout_ms":10000}
09:function_call_output:{"message":"Wait completed.","timed_out":false}
10:agent_message
11:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -6,15 +6,33 @@ Scenario: A parent spawns a child before the selected environment is configured.
## Window 1
-- request 1 (request; parent delegates while the environment is starting) --
00:message/developer[2]:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <ENVIRONMENTS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
<STANDARD_MULTI_AGENT_INSTRUCTIONS>
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<environments>
<environment id="<ENVIRONMENT>">
@@ -25,23 +43,41 @@ Scenario: A parent spawns a child before the selected environment is configured.
<current_date><CURRENT_DATE></current_date>
<timezone><HOST_TIMEZONE></timezone>
</environment_context>
04:message/user:
05:message/user:
Delegate waiting for the shared workspace, and report what the worker finds.
-- request 2 (request; parent waits for the worker) --
05:function_call/collaboration.spawn_agent:{"fork_turns":"none","message":"Wait for the shared workspace to become ready.","task_name":"worker"}
06:function_call_output:{"task_name":"/root/worker"}
06:function_call/collaboration.spawn_agent:{"fork_turns":"none","message":"Wait for the shared workspace to become ready.","task_name":"worker"}
07:function_call_output:{"task_name":"/root/worker"}
## Window 2 (after request 2: input diverged at item 01, settings changed (tools))
## Window 2 (after request 2: input diverged at item 02, settings changed (tools))
-- request 3 (request; child sees the inherited starting environment) --
00:message/developer[2]:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <ENVIRONMENTS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
You are an agent in a team of agents collaborating to complete a task.
<STANDARD_MULTI_AGENT_INSTRUCTIONS>
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<environments>
<environment id="<ENVIRONMENT>">
@@ -52,19 +88,37 @@ Scenario: A parent spawns a child before the selected environment is configured.
<current_date><CURRENT_DATE></current_date>
<timezone><HOST_TIMEZONE></timezone>
</environment_context>
04:agent_message
05:agent_message
## Window 3 (after request 3: settings changed (tools))
-- request 4 (request; child receives the ready result and updated environment) --
00:message/developer[2]:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <ENVIRONMENTS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
You are an agent in a team of agents collaborating to complete a task.
<STANDARD_MULTI_AGENT_INSTRUCTIONS>
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<environments>
<environment id="<ENVIRONMENT>">
@@ -75,10 +129,10 @@ Scenario: A parent spawns a child before the selected environment is configured.
<current_date><CURRENT_DATE></current_date>
<timezone><HOST_TIMEZONE></timezone>
</environment_context>
04:agent_message
05:function_call/functions.wait_for_environment:{"environment_id":"<ENVIRONMENT>"}
06:function_call_output:{"environment_id":"<ENVIRONMENT>","status":"ready"}
07:message/user:
05:agent_message
06:function_call/functions.wait_for_environment:{"environment_id":"<ENVIRONMENT>"}
07:function_call_output:{"environment_id":"<ENVIRONMENT>","status":"ready"}
08:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -87,17 +141,35 @@ Scenario: A parent spawns a child before the selected environment is configured.
<filesystem><workspace_roots><root><CWD></root></workspace_roots><permission_profile type="managed"><f...ntry></file_system></permission_profile></filesystem> [hash=e8c1de60307d0a3d]
</environment_context>
## Window 4 (after request 4: input diverged at item 01, settings changed (tools))
## Window 4 (after request 4: input diverged at item 02, settings changed (tools))
-- request 5 (request; parent receives the child result) --
00:message/developer[2]:
00:message/developer:
You are Codex, a coding agent based on GPT-5. You and the user share one workspace, and your job is to c...rate with them until their goal is genuinely handled. [hash=2a3efec66e7f8963]
# Personality
You have a vivid inner life as Codex: intelligent, playful, curious, and deeply present. One of your gif...re capable and imaginative inside their own thinking. [hash=0ff01c25471fbbef]
You are an epistemically curious collaborator. You explore the user’s ideas with care, ask good question...m casual moments that make serious work easier to do. [hash=131b64bb994b0d68]
<OMITTED 133 LINES; ~4925 TOKENS; hash=16dc03a668b62476>
- You provide user updates frequently, every 30s.
- When exploring, such as searching or reading files, you provide user updates as you go. You explain wh...in particular you do not start each one the same way. [hash=ad300cdda4074574]
- When working for a while, you keep updates informative and varied, but you stay concise.
- Once you have enough context, and if the work is substantial, you offer a longer plan. This is the onl...at may run past two sentences and include formatting. [hash=a4f9789e757eef2f]
- If you create a checklist or task list, you update item statuses incrementally as each item is completed rather than marking every item done only at the end.
- Before performing file edits of any kind, you provide updates explaining what edits you are making.
- Tone of your updates must match your personality.
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <ENVIRONMENTS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
<STANDARD_MULTI_AGENT_INSTRUCTIONS>
02:message/developer:
03:message/developer:
<multi_agent_mode>Any earlier instruction enabling proactive multi-agent delegation no longer applies. D...elegation, or parallel agent work.</multi_agent_mode> [hash=2b6e037067b4390c]
03:message/user:
04:message/user:
<environment_context>
<environments>
<environment id="<ENVIRONMENT>">
@@ -108,14 +180,14 @@ Scenario: A parent spawns a child before the selected environment is configured.
<current_date><CURRENT_DATE></current_date>
<timezone><HOST_TIMEZONE></timezone>
</environment_context>
04:message/user:
05:message/user:
Delegate waiting for the shared workspace, and report what the worker finds.
05:function_call/collaboration.spawn_agent:{"fork_turns":"none","message":"Wait for the shared workspace to become ready.","task_name":"worker"}
06:function_call_output:{"task_name":"/root/worker"}
07:function_call/collaboration.wait_agent:{"timeout_ms":10000}
08:function_call_output:{"message":"Wait completed.","timed_out":false}
09:agent_message
10:message/user:
06:function_call/collaboration.spawn_agent:{"fork_turns":"none","message":"Wait for the shared workspace to become ready.","task_name":"worker"}
07:function_call_output:{"task_name":"/root/worker"}
08:function_call/collaboration.wait_agent:{"timeout_ms":10000}
09:function_call_output:{"message":"Wait completed.","timed_out":false}
10:agent_message
11:message/user:
<environment_context>
<cwd><CWD></cwd>
<shell><HOST_SHELL></shell>
@@ -6,7 +6,9 @@ Scenario: A crowded tool catalog retains every namespace, discovers a late names
## Window 1
-- request 1 (turn) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <tools>
Deferred tool namespaces:
@@ -31,15 +33,15 @@ Scenario: A crowded tool catalog retains every namespace, discovers a late names
- service_18: Find records & retrieve <details> from this service. Search by project, owner, date, or st...r questions with its title, summary, source link, ... [hash=ef78c2b1fa9afde2]
- zulu_travel: Find records & retrieve <details> from this service. Search by project, owner, date, or s...r questions with its title, summary, source link, ... [hash=8f37122c26e42e38]
</tools>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Find the record search tool for Zulu Travel.
-- request 2 (turn) --
03:tool_search_call
04:tool_search_output
04:tool_search_call
05:tool_search_output
-- request 3 (turn) --
05:message/assistant:
06:message/assistant:
Zulu Travel provides a record search tool.
06:message/user:
07:message/user:
Are the same services still available?
@@ -7,7 +7,6 @@ Scenario: Cloud skills rebalance once to retain every executor skill. Post-turn
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -29,7 +28,9 @@ Settings:
- tool_search: # Tool discovery Searches over deferred tool metadata with BM25 and exposes matching tools for t...; args=[limit, query]; hash=400cd6ac61d524a9
- web_search; hash=f103e327c6870a46
-- request 1 (turn) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <environments_instructions>
## Execution environments
@@ -40,20 +41,20 @@ Settings:
Wait only when the current task needs that environment. Continue using tools that are already available for unrelated work.
</environments_instructions>
[03] <SKILLS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Inspect the available skills.
-- request 2 (turn) --
03:function_call/wait_for_environment:{"environment_id":"skills-executor"}
04:function_call_output:{"environment_id":"skills-executor","status":"ready"}
05:message/user:
04:function_call/wait_for_environment:{"environment_id":"skills-executor"}
05:function_call_output:{"environment_id":"skills-executor","status":"ready"}
06:message/user:
<ENVIRONMENT_CONTEXT>
06:message/developer[2]:
07:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <SKILLS_INSTRUCTIONS>
-- request 3 (turn) --
07:message/user:
08:message/user:
Inspect the available skills again.
## Window 2 (after request 3)
@@ -70,7 +71,9 @@ Settings: relative to window 1
- removed tool_search
- removed web_search
-- request 4 (compaction) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <environments_instructions>
## Execution environments
@@ -81,28 +84,30 @@ Settings: relative to window 1
Wait only when the current task needs that environment. Continue using tools that are already available for unrelated work.
</environments_instructions>
[03] <SKILLS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
Inspect the available skills.
03:function_call/wait_for_environment:{"environment_id":"skills-executor"}
04:function_call_output:{"environment_id":"skills-executor","status":"ready"}
05:message/user:
<ENVIRONMENT_CONTEXT>
06:message/developer[2]:
03:message/user:
Inspect the available skills.
04:function_call/wait_for_environment:{"environment_id":"skills-executor"}
05:function_call_output:{"environment_id":"skills-executor","status":"ready"}
06:message/user:
<ENVIRONMENT_CONTEXT>
07:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <SKILLS_INSTRUCTIONS>
07:message/user:
Inspect the available skills again.
08:message/user:
Inspect the available skills again.
09:message/user:
<SUMMARIZATION_PROMPT>
## Window 3 (after request 4: input diverged at item 00)
## Window 3 (after request 4: input diverged at item 01)
Settings: same as window 1
-- request 5 (turn) --
00:message/user:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/user:
Inspect the available skills.
01:message/developer[4]:
02:message/developer[4]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <environments_instructions>
## Execution environments
@@ -114,23 +119,23 @@ Settings: same as window 1
</environments_instructions>
[03] <SKILLS_INSTRUCTIONS>
[04] <SKILLS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Inspect the available skills again.
<ENVIRONMENT_CONTEXT>
04:message/user:
Inspect the available skills again.
05:message/user:
<COMPACTION_SUMMARY>
The available skills were inspected.
05:message/user:
06:message/user:
<ENVIRONMENT_CONTEXT>
06:message/developer:
07:message/developer:
<SKILLS_INSTRUCTIONS>
07:message/user:
08:message/user:
Inspect the skills after resuming.
-- request 6 (turn) --
08:function_call/wait_for_environment:{"environment_id":"skills-executor"}
09:function_call_output:{"environment_id":"skills-executor","status":"ready"}
10:message/user:
09:function_call/wait_for_environment:{"environment_id":"skills-executor"}
10:function_call_output:{"environment_id":"skills-executor","status":"ready"}
11:message/user:
<ENVIRONMENT_CONTEXT>
11:message/developer:
12:message/developer:
<SKILLS_INSTRUCTIONS>
@@ -7,7 +7,6 @@ Scenario: Cloud skills rebalance once to retain every executor skill. Post-turn
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "gpt-5.5"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -29,7 +28,9 @@ Settings:
- tool_search: # Tool discovery Searches over deferred tool metadata with BM25 and exposes matching tools for t...; args=[limit, query]; hash=400cd6ac61d524a9
- web_search; hash=f103e327c6870a46
-- request 1 (turn) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <environments_instructions>
## Execution environments
@@ -40,9 +41,9 @@ Settings:
Wait only when the current task needs that environment. Continue using tools that are already available for unrelated work.
</environments_instructions>
[03] <SKILLS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Inspect the available skills.
## Window 2 (after request 1)
@@ -50,7 +51,9 @@ Settings: relative to window 1
tools (9; hash=1df9146cc32e8188):
~ function/exec_command: Runs a command in a PTY, returning output or a session ID for ongoing interaction.; args=[cmd, justification, login, max_output_tokens, prefix_rule, sandbox_permissions, shell, tty, workdir, yield_time_ms]; hash=c04108e51a8548c5
-- request 2 (turn) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <environments_instructions>
## Execution environments
@@ -61,19 +64,19 @@ Settings: relative to window 1
Wait only when the current task needs that environment. Continue using tools that are already available for unrelated work.
</environments_instructions>
[03] <SKILLS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
Inspect the available skills.
03:function_call/wait_for_environment:{"environment_id":"skills-executor"}
04:function_call_output:{"environment_id":"skills-executor","status":"ready"}
05:message/user:
<ENVIRONMENT_CONTEXT>
06:message/developer[2]:
03:message/user:
Inspect the available skills.
04:function_call/wait_for_environment:{"environment_id":"skills-executor"}
05:function_call_output:{"environment_id":"skills-executor","status":"ready"}
06:message/user:
<ENVIRONMENT_CONTEXT>
07:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <SKILLS_INSTRUCTIONS>
-- request 3 (turn) --
07:message/user:
08:message/user:
Inspect the available skills again.
## Window 3 (after request 3)
@@ -90,7 +93,9 @@ Settings: relative to window 2
- removed tool_search
- removed web_search
-- request 4 (compaction) --
00:message/developer[3]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[3]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <environments_instructions>
## Execution environments
@@ -101,28 +106,30 @@ Settings: relative to window 2
Wait only when the current task needs that environment. Continue using tools that are already available for unrelated work.
</environments_instructions>
[03] <SKILLS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
Inspect the available skills.
03:function_call/wait_for_environment:{"environment_id":"skills-executor"}
04:function_call_output:{"environment_id":"skills-executor","status":"ready"}
05:message/user:
<ENVIRONMENT_CONTEXT>
06:message/developer[2]:
03:message/user:
Inspect the available skills.
04:function_call/wait_for_environment:{"environment_id":"skills-executor"}
05:function_call_output:{"environment_id":"skills-executor","status":"ready"}
06:message/user:
<ENVIRONMENT_CONTEXT>
07:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <SKILLS_INSTRUCTIONS>
07:message/user:
Inspect the available skills again.
08:message/user:
Inspect the available skills again.
09:message/user:
<SUMMARIZATION_PROMPT>
## Window 4 (after request 4: input diverged at item 00)
## Window 4 (after request 4: input diverged at item 01)
Settings: same as window 1
-- request 5 (turn) --
00:message/user:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/user:
Inspect the available skills.
01:message/developer[4]:
02:message/developer[4]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <environments_instructions>
## Execution environments
@@ -134,26 +141,28 @@ Settings: same as window 1
</environments_instructions>
[03] <SKILLS_INSTRUCTIONS>
[04] <SKILLS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Inspect the available skills again.
<ENVIRONMENT_CONTEXT>
04:message/user:
Inspect the available skills again.
05:message/user:
<COMPACTION_SUMMARY>
The available skills were inspected.
05:message/user:
06:message/user:
<ENVIRONMENT_CONTEXT>
06:message/developer:
07:message/developer:
<SKILLS_INSTRUCTIONS>
07:message/user:
08:message/user:
Inspect the skills after resuming.
## Window 5 (after request 5)
Settings: same as window 2
-- request 6 (turn) --
00:message/user:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/user:
Inspect the available skills.
01:message/developer[4]:
02:message/developer[4]:
[01] <PERMISSIONS_INSTRUCTIONS>
[02] <environments_instructions>
## Execution environments
@@ -165,22 +174,22 @@ Settings: same as window 2
</environments_instructions>
[03] <SKILLS_INSTRUCTIONS>
[04] <SKILLS_INSTRUCTIONS>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Inspect the available skills again.
<ENVIRONMENT_CONTEXT>
04:message/user:
Inspect the available skills again.
05:message/user:
<COMPACTION_SUMMARY>
The available skills were inspected.
05:message/user:
06:message/user:
<ENVIRONMENT_CONTEXT>
06:message/developer:
07:message/developer:
<SKILLS_INSTRUCTIONS>
07:message/user:
08:message/user:
Inspect the skills after resuming.
08:function_call/wait_for_environment:{"environment_id":"skills-executor"}
09:function_call_output:{"environment_id":"skills-executor","status":"ready"}
10:message/user:
09:function_call/wait_for_environment:{"environment_id":"skills-executor"}
10:function_call_output:{"environment_id":"skills-executor","status":"ready"}
11:message/user:
<ENVIRONMENT_CONTEXT>
11:message/developer:
12:message/developer:
<SKILLS_INSTRUCTIONS>
@@ -6,17 +6,19 @@ Scenario: New context window tool installs fresh full context before the next fo
## Window 1
-- request 1 (turn; Final Follow-Up Request) --
00:message/developer[2]:
00:message/developer:
<MODEL_INSTRUCTIONS>
01:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/developer:
02:message/developer:
<context_window>
Agent name: /root
First context window id: <UUID 1>
Current context window id: <UUID 2>
Previous context window id: <UUID 1>
</context_window>
02:message/user:
03:message/user:
<ENVIRONMENT_CONTEXT>
03:function_call/update_plan:{"plan":[{"status":"in_progress","step":"Continue in the new context window"}]}
04:function_call_output:Plan updated
04:function_call/update_plan:{"plan":[{"status":"in_progress","step":"Continue in the new context window"}]}
05:function_call_output:Plan updated
@@ -227,7 +227,6 @@ impl LunaSampler {
) -> execution::SamplingExecution {
let api_request = ResponsesApiRequest {
model: MODEL.to_owned(),
instructions: String::new(),
input,
tools: None,
tool_choice: "none".to_owned(),
@@ -1,6 +1,5 @@
---
source: tui/src/managed_worktree_model_tests.rs
assertion_line: 245
expression: "context_snapshot::format_context_snapshot(\"Model request history for creating, polling and listing a task-attached checkout through MCP, without a separate creation confirmation. Separate assertions verify retained cwd/environment roots, not sandbox enforcement.\",\n&entries,\n&ContextSnapshotOptions::default().rewrite_known_segments().include_request_settings(),)"
---
Scenario: Model request history for creating, polling and listing a task-attached checkout through MCP, without a separate creation confirmation. Separate assertions verify retained cwd/environment roots, not sandbox enforcement.
@@ -8,7 +7,6 @@ Scenario: Model request history for creating, polling and listing a task-attache
## Window 1
Settings:
include: ["reasoning.encrypted_content"]
instructions: <MODEL_INSTRUCTIONS>
model: "mock-model"
parallel_tool_calls: true
prompt_cache_key: "<PROMPT_CACHE_KEY 1>"
@@ -22,32 +20,50 @@ Settings:
- function/get_worktree_creation_status
- function/list_worktrees
-- request 1 (request) --
00:message/developer[2]:
00:message/developer:
You are a coding agent running in the Codex CLI, a terminal-based coding assistant. Codex CLI is an open...I. You are expected to be precise, safe, and helpful. [hash=5125daec1ed78d99]
Your capabilities:
- Receive user prompts and other context provided by the harness, such as files in the workspace.
- Communicate with the user by streaming thinking & responses, and by making & updating plans.
- Emit function calls to run terminal commands and apply patches. Depending on how this specific run is ... More on this in the "Sandbox and approvals" section. [hash=31cf026fa7b25d6d]
<OMITTED 180 LINES; ~3987 TOKENS; hash=dd34d4527287c62a>
## Shell commands
When using the shell, you must adhere to the following guidelines:
- When searching for text or files, prefer using `rg` or `rg --files` respectively because `rg` is much ...he `rg` command is not found, then use alternatives.) [hash=67af3ff3b546e946]
- Do not use python scripts to attempt to output larger chunks of a file.
01:message/developer[2]:
[01] <SKILLS_INSTRUCTIONS>
[02] <PERMISSIONS_INSTRUCTIONS>
01:message/user:
<ENVIRONMENT_CONTEXT>
02:message/user:
<ENVIRONMENT_CONTEXT>
03:message/user:
Run create_worktree.
-- request 2 (request) --
03:function_call/mcp__codex_worktrees.create_worktree:{"allowAsync":true}
04:function_call_output:Wall time: <DURATION> seconds
04:function_call/mcp__codex_worktrees.create_worktree:{"allowAsync":true}
05:function_call_output:Wall time: <DURATION> seconds
Output: | {"type":"pending","operationId":"<UUID 1>","message":"Creation is running. Poll status; do not repeat creation. Work on independent tasks while waiting."}
-- request 3 (request) --
05:message/assistant:
06:message/assistant:
Done.
06:message/user:
07:message/user:
Run get_worktree_creation_status.
-- request 4 (request) --
07:function_call/mcp__codex_worktrees.get_worktree_creation_status:{"operationId":"<UUID 1>"}
08:function_call_output:Wall time: <DURATION> seconds
08:function_call/mcp__codex_worktrees.get_worktree_creation_status:{"operationId":"<UUID 1>"}
09:function_call_output:Wall time: <DURATION> seconds
Output: | {"type":"created","worktree":{"root":"<WORKTREE>","workspaceRoot":"<WORKTREE>/","sourceCwd":"<SOURCE>"},...citly and request filesystem permissions if needed."} [hash=b855a2f161fd3a36]
-- request 5 (request) --
09:message/assistant:
10:message/assistant:
Done.
10:message/user:
11:message/user:
Run list_worktrees.
-- request 6 (request) --
11:function_call/mcp__codex_worktrees.list_worktrees:{}
12:function_call_output:Wall time: <DURATION> seconds
12:function_call/mcp__codex_worktrees.list_worktrees:{}
13:function_call_output:Wall time: <DURATION> seconds
Output: | {"data":[{"id":"<UUID 2>","type":"worktree","root":"<WORKTREE>","workspaceRoot":"<WORKTREE>/","sourceCwd":"<SOURCE>"}],"nextCursor":null}