diff --git a/codex-rs/core/src/context/mod.rs b/codex-rs/core/src/context/mod.rs index bbc5bcacf..848a4f7f0 100644 --- a/codex-rs/core/src/context/mod.rs +++ b/codex-rs/core/src/context/mod.rs @@ -20,7 +20,6 @@ mod realtime_end_instructions; mod realtime_start_instructions; mod realtime_start_with_instructions; mod skill_instructions; -mod spawn_agent_instructions; mod subagent_notification; mod turn_aborted; mod user_instructions; @@ -50,7 +49,6 @@ pub(crate) use realtime_end_instructions::RealtimeEndInstructions; pub(crate) use realtime_start_instructions::RealtimeStartInstructions; pub(crate) use realtime_start_with_instructions::RealtimeStartWithInstructions; pub(crate) use skill_instructions::SkillInstructions; -pub(crate) use spawn_agent_instructions::SpawnAgentInstructions; pub(crate) use subagent_notification::SubagentNotification; pub(crate) use turn_aborted::TurnAborted; pub(crate) use user_instructions::UserInstructions; diff --git a/codex-rs/core/src/context/spawn_agent_instructions.rs b/codex-rs/core/src/context/spawn_agent_instructions.rs deleted file mode 100644 index f8a3f4175..000000000 --- a/codex-rs/core/src/context/spawn_agent_instructions.rs +++ /dev/null @@ -1,14 +0,0 @@ -use super::ContextualUserFragment; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub(crate) struct SpawnAgentInstructions; - -impl ContextualUserFragment for SpawnAgentInstructions { - const ROLE: &'static str = "developer"; - const START_MARKER: &'static str = ""; - const END_MARKER: &'static str = ""; - - fn body(&self) -> String { - "\nYou are a newly spawned 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. You are responsible for returning the response to your assigned task in the final channel. When you give your response, the contents of your response in the final channel will be immediately delivered back to your parent agent. The prior conversation history was forked from your parent agent. Treat the next user message as your assigned task, and use the forked history only as background context.\n".to_string() - } -} diff --git a/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs b/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs index fabb01b7d..00986311a 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs @@ -5,8 +5,6 @@ use crate::agent::control::render_input_preview; use crate::agent::next_thread_spawn_depth; use crate::agent::role::DEFAULT_ROLE_NAME; use crate::agent::role::apply_role_to_config; -use crate::context::ContextualUserFragment; -use crate::context::SpawnAgentInstructions; use codex_protocol::AgentPath; use codex_protocol::protocol::InterAgentCommunication; use codex_protocol::protocol::Op; @@ -88,18 +86,6 @@ impl ToolHandler for Handler { } apply_spawn_agent_runtime_overrides(&mut config, turn.as_ref())?; apply_spawn_agent_overrides(&mut config, child_depth); - let spawn_agent_instructions = SpawnAgentInstructions.render(); - config.developer_instructions = Some( - if let Some(mut existing_instructions) = config.developer_instructions.take() { - if !existing_instructions.ends_with('\n') { - existing_instructions.push('\n'); - } - existing_instructions.push_str(&spawn_agent_instructions); - existing_instructions - } else { - spawn_agent_instructions - }, - ); let spawn_source = thread_spawn_source( session.conversation_id, diff --git a/codex-rs/core/tests/suite/subagent_notifications.rs b/codex-rs/core/tests/suite/subagent_notifications.rs index f12c68427..3f457967c 100644 --- a/codex-rs/core/tests/suite/subagent_notifications.rs +++ b/codex-rs/core/tests/suite/subagent_notifications.rs @@ -37,7 +37,6 @@ const REQUESTED_MODEL: &str = "gpt-5.4"; const REQUESTED_REASONING_EFFORT: ReasoningEffort = ReasoningEffort::Low; const ROLE_MODEL: &str = "gpt-5.4"; const ROLE_REASONING_EFFORT: ReasoningEffort = ReasoningEffort::High; -const SPAWNED_AGENT_DEVELOPER_INSTRUCTIONS: &str = "You are a newly spawned 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. You are responsible for returning the response to your assigned task in the final channel. When you give your response, the contents of your response in the final channel will be immediately delivered back to your parent agent. The prior conversation history was forked from your parent agent. Treat the next user message as your assigned task, and use the forked history only as background context."; fn body_contains(req: &wiremock::Request, text: &str) -> bool { let is_zstd = req @@ -425,7 +424,7 @@ async fn spawn_agent_requested_model_and_reasoning_override_inherited_settings_w } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn spawned_multi_agent_v2_child_receives_xml_tagged_developer_context() -> Result<()> { +async fn spawned_multi_agent_v2_child_inherits_parent_developer_context() -> Result<()> { skip_if_no_network!(Ok(())); let server = start_mock_server().await; @@ -446,9 +445,7 @@ async fn spawned_multi_agent_v2_child_receives_xml_tagged_developer_context() -> let _child_request_log = mount_sse_once_match( &server, - |req: &wiremock::Request| { - body_contains(req, CHILD_PROMPT) && body_contains(req, "") - }, + |req: &wiremock::Request| body_contains(req, CHILD_PROMPT), sse(vec![ ev_response_created("resp-child-1"), ev_completed("resp-child-1"), @@ -459,9 +456,7 @@ async fn spawned_multi_agent_v2_child_receives_xml_tagged_developer_context() -> let _turn1_followup = mount_sse_once_match( &server, |req: &wiremock::Request| { - body_contains(req, "function_call_output") - && body_contains(req, "/root/worker") - && !body_contains(req, "") + body_contains(req, "function_call_output") && body_contains(req, "/root/worker") }, sse(vec![ ev_response_created("resp-turn1-2"), @@ -494,9 +489,7 @@ async fn spawned_multi_agent_v2_child_receives_xml_tagged_developer_context() -> .unwrap_or_default() .into_iter() .find(|request| { - body_contains(request, CHILD_PROMPT) - && body_contains(request, "") - && body_contains(request, SPAWNED_AGENT_DEVELOPER_INSTRUCTIONS) + body_contains(request, CHILD_PROMPT) && !body_contains(request, SPAWN_CALL_ID) }) { break request; @@ -510,11 +503,6 @@ async fn spawned_multi_agent_v2_child_receives_xml_tagged_developer_context() -> &child_request, "Parent developer instructions." )); - assert!(body_contains(&child_request, "")); - assert!(body_contains( - &child_request, - SPAWNED_AGENT_DEVELOPER_INSTRUCTIONS - )); assert!(body_contains(&child_request, CHILD_PROMPT)); Ok(()) @@ -542,9 +530,7 @@ async fn skills_toggle_skips_instructions_for_parent_and_spawned_child() -> Resu let _child_request_log = mount_sse_once_match( &server, - |req: &wiremock::Request| { - body_contains(req, CHILD_PROMPT) && body_contains(req, "") - }, + |req: &wiremock::Request| body_contains(req, CHILD_PROMPT), sse(vec![ ev_response_created("resp-child-1"), ev_completed("resp-child-1"), @@ -555,9 +541,7 @@ async fn skills_toggle_skips_instructions_for_parent_and_spawned_child() -> Resu let _turn1_followup = mount_sse_once_match( &server, |req: &wiremock::Request| { - body_contains(req, "function_call_output") - && body_contains(req, "/root/worker") - && !body_contains(req, "") + body_contains(req, "function_call_output") && body_contains(req, "/root/worker") }, sse(vec![ ev_response_created("resp-turn1-2"), @@ -599,8 +583,7 @@ async fn skills_toggle_skips_instructions_for_parent_and_spawned_child() -> Resu .unwrap_or_default() .into_iter() .find(|request| { - body_contains(request, CHILD_PROMPT) - && body_contains(request, "") + body_contains(request, CHILD_PROMPT) && !body_contains(request, SPAWN_CALL_ID) }) { break request;