From 668703c23f8a6cde07c317f687d9b95606293752 Mon Sep 17 00:00:00 2001 From: jif Date: Wed, 3 Jun 2026 12:22:23 +0200 Subject: [PATCH] feat: default hide_spawn_agent_metadata to true (#26114) For MAv2 CBv9 --- codex-rs/core/src/config/config_tests.rs | 1 + codex-rs/core/src/config/mod.rs | 2 +- .../core/src/tools/handlers/multi_agents_spec.rs | 14 ++++++++++++-- .../src/tools/handlers/multi_agents_spec_tests.rs | 9 ++++++++- .../core/src/tools/handlers/multi_agents_tests.rs | 6 +++--- .../core/tests/suite/spawn_agent_description.rs | 1 + .../core/tests/suite/subagent_notifications.rs | 1 + 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/codex-rs/core/src/config/config_tests.rs b/codex-rs/core/src/config/config_tests.rs index 8bc33bbb4..87f00fed8 100644 --- a/codex-rs/core/src/config/config_tests.rs +++ b/codex-rs/core/src/config/config_tests.rs @@ -9914,6 +9914,7 @@ enabled = true .unwrap_or_default() .contains("maximum concurrency"), ); + assert!(config.multi_agent_v2.hide_spawn_agent_metadata); assert!(config.multi_agent_v2.non_code_mode_only); Ok(()) diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index fd71cea98..43b2a2ed2 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -1065,7 +1065,7 @@ impl Default for MultiAgentV2Config { DEFAULT_MULTI_AGENT_V2_SUBAGENT_USAGE_HINT_TEXT.to_string(), ), tool_namespace: None, - hide_spawn_agent_metadata: false, + hide_spawn_agent_metadata: true, non_code_mode_only: true, } } diff --git a/codex-rs/core/src/tools/handlers/multi_agents_spec.rs b/codex-rs/core/src/tools/handlers/multi_agents_spec.rs index 4359445f9..baf46d0d0 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_spec.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_spec.rs @@ -48,6 +48,8 @@ impl Default for WaitAgentTimeoutOptions { pub fn create_spawn_agent_tool_v1(options: SpawnAgentToolOptions) -> ToolSpec { let available_models_description = (!options.hide_agent_type_model_reasoning) .then(|| spawn_agent_models_description(&options.available_models)); + let inherited_model_guidance = + (!options.hide_agent_type_model_reasoning).then_some(SPAWN_AGENT_INHERITED_MODEL_GUIDANCE); let return_value_description = "Returns the spawned agent id plus the user-facing nickname when available."; let mut properties = spawn_agent_common_properties_v1(&options.agent_type_description); @@ -62,6 +64,7 @@ pub fn create_spawn_agent_tool_v1(options: SpawnAgentToolOptions) -> ToolSpec { name: "spawn_agent".to_string(), description: spawn_agent_tool_description( available_models_description.as_deref(), + inherited_model_guidance, return_value_description, options.include_usage_hint, options.usage_hint_text, @@ -77,6 +80,8 @@ pub fn create_spawn_agent_tool_v1(options: SpawnAgentToolOptions) -> ToolSpec { pub fn create_spawn_agent_tool_v2(options: SpawnAgentToolOptions) -> ToolSpec { let available_models_description = (!options.hide_agent_type_model_reasoning) .then(|| spawn_agent_models_description(&options.available_models)); + let inherited_model_guidance = + (!options.hide_agent_type_model_reasoning).then_some(SPAWN_AGENT_INHERITED_MODEL_GUIDANCE); let mut properties = spawn_agent_common_properties_v2(&options.agent_type_description); if options.hide_agent_type_model_reasoning { hide_spawn_agent_metadata_options(&mut properties); @@ -93,6 +98,7 @@ pub fn create_spawn_agent_tool_v2(options: SpawnAgentToolOptions) -> ToolSpec { name: "spawn_agent".to_string(), description: spawn_agent_tool_description_v2( available_models_description.as_deref(), + inherited_model_guidance, options.include_usage_hint, options.usage_hint_text, options.max_concurrent_threads_per_session, @@ -632,16 +638,18 @@ fn hide_spawn_agent_metadata_options(properties: &mut BTreeMap, + inherited_model_guidance: Option<&str>, return_value_description: &str, include_usage_hint: bool, usage_hint_text: Option, ) -> String { let agent_role_guidance = available_models_description.unwrap_or_default(); + let inherited_model_guidance = inherited_model_guidance.unwrap_or_default(); let tool_description = format!( r#" {agent_role_guidance} - Spawn a sub-agent for a well-scoped task. {return_value_description} {SPAWN_AGENT_INHERITED_MODEL_GUIDANCE}"# + Spawn a sub-agent for a well-scoped task. {return_value_description} {inherited_model_guidance}"# ); if !include_usage_hint { @@ -701,11 +709,13 @@ Requests for depth, thoroughness, research, investigation, or detailed codebase fn spawn_agent_tool_description_v2( available_models_description: Option<&str>, + inherited_model_guidance: Option<&str>, include_usage_hint: bool, usage_hint_text: Option, max_concurrent_threads_per_session: Option, ) -> String { let agent_role_guidance = available_models_description.unwrap_or_default(); + let inherited_model_guidance = inherited_model_guidance.unwrap_or_default(); let concurrency_guidance = max_concurrent_threads_per_session .map(|limit| { format!( @@ -720,7 +730,7 @@ fn spawn_agent_tool_description_v2( Spawns an agent to work on the specified task. If your current task is `/root/task1` and you spawn_agent with task_name "task_3" the agent will have canonical task name `/root/task1/task_3`. You are then able to refer to this agent as `task_3` or `/root/task1/task_3` interchangeably. However an agent `/root/task2/task_3` would only be able to communicate with this agent via its canonical name `/root/task1/task_3`. The spawned agent will have the same tools as you and the ability to spawn its own subagents. -{SPAWN_AGENT_INHERITED_MODEL_GUIDANCE} +{inherited_model_guidance} It will be able to send you and other running agents messages, and its final answer will be provided to you when it finishes. The new agent's canonical task name will be provided to it along with the message. {concurrency_guidance}"# diff --git a/codex-rs/core/src/tools/handlers/multi_agents_spec_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_spec_tests.rs index fc18c312d..5f4a66a75 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_spec_tests.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_spec_tests.rs @@ -197,7 +197,12 @@ fn spawn_agent_tool_hides_service_tier_with_spawn_metadata() { max_concurrent_threads_per_session: Some(4), }); - let ToolSpec::Function(ResponsesApiTool { parameters, .. }) = tool else { + let ToolSpec::Function(ResponsesApiTool { + description, + parameters, + .. + }) = tool + else { panic!("spawn_agent should be a function tool"); }; let properties = parameters @@ -209,6 +214,8 @@ fn spawn_agent_tool_hides_service_tier_with_spawn_metadata() { assert!(!properties.contains_key("model")); assert!(!properties.contains_key("reasoning_effort")); assert!(!properties.contains_key("service_tier")); + assert!(!description.contains(SPAWN_AGENT_INHERITED_MODEL_GUIDANCE)); + assert!(!description.contains("Available model overrides")); } #[test] diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs index d4ce84ad5..e33d94234 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs @@ -1161,7 +1161,7 @@ async fn multi_agent_v2_spawn_returns_path_and_send_message_accepts_relative_pat let spawn_result: SpawnAgentResult = serde_json::from_str(&content).expect("spawn result should parse"); assert_eq!(spawn_result.task_name, "/root/test_process"); - assert!(spawn_result.nickname.is_some()); + assert_eq!(spawn_result.nickname, None); let child_thread_id = session .services @@ -2179,7 +2179,7 @@ async fn multi_agent_v2_spawn_omits_agent_id_when_named() { assert!(result.get("agent_id").is_none()); assert_eq!(result["task_name"], "/root/test_process"); - assert!(result.get("nickname").is_some()); + assert!(result.get("nickname").is_none()); assert_eq!(success, Some(true)); } @@ -2436,7 +2436,7 @@ async fn multi_agent_v2_spawn_agent_ignores_configured_max_depth() { let result: SpawnAgentResult = serde_json::from_str(&content).expect("spawn_agent result should be json"); assert_eq!(result.task_name, "/root/parent/child"); - assert!(result.nickname.is_some()); + assert_eq!(result.nickname, None); assert_eq!(success, Some(true)); } diff --git a/codex-rs/core/tests/suite/spawn_agent_description.rs b/codex-rs/core/tests/suite/spawn_agent_description.rs index c1f0d522c..3b581c905 100644 --- a/codex-rs/core/tests/suite/spawn_agent_description.rs +++ b/codex-rs/core/tests/suite/spawn_agent_description.rs @@ -165,6 +165,7 @@ async fn spawn_agent_description_lists_visible_models_and_reasoning_efforts() -> .features .enable(Feature::Collab) .expect("test config should allow feature update"); + config.multi_agent_v2.hide_spawn_agent_metadata = false; }); let test = builder.build(&server).await?; wait_for_model_available(&test.thread_manager.get_models_manager(), "visible-model").await; diff --git a/codex-rs/core/tests/suite/subagent_notifications.rs b/codex-rs/core/tests/suite/subagent_notifications.rs index 52fd1a25e..c39a6bb39 100644 --- a/codex-rs/core/tests/suite/subagent_notifications.rs +++ b/codex-rs/core/tests/suite/subagent_notifications.rs @@ -1184,6 +1184,7 @@ async fn spawn_agent_tool_description_mentions_role_locked_settings() -> Result< .features .enable(Feature::Collab) .expect("test config should allow feature update"); + config.multi_agent_v2.hide_spawn_agent_metadata = false; let role_path = config.codex_home.join("custom-role.toml"); std::fs::write( &role_path,