From 061a614d857e0f2289457770e90caf8a45b5e430 Mon Sep 17 00:00:00 2001 From: sayan-oai Date: Sat, 16 May 2026 13:43:30 -0700 Subject: [PATCH] multiagent: trim model-visible description, cap to 5 models (#23069) ## Why The `spawn_agent` model override guidance is uncapped and bloating context. We need to trim down each entry and cap total entries. picked 5 as cap, we can change ## What changed - Cap the model override summaries shown in `spawn_agent` to the first 5 picker-visible models, preserving the existing priority ordering from the models manager. - Condense each rendered entry to the actionable pieces the model needs: - use the model slug as the label - render compact reasoning effort lists with the default marked inline - render only service tier IDs, and omit the clause when no tiers are available - Update coverage so the compact formatter shape and the top-5 cap are exercised, and keep the end-to-end request assertion aligned with real model metadata. ## Example Before: `- gpt-5.4 ('gpt-5.4\'): Strong model for everyday coding. Default reasoning effort: medium. Supported reasoning efforts: low (Fast responses with lighter reasoning), medium (Balances speed and reasoning depth for everyday tasks), high (Greater reasoning depth for complex problems), xhigh (Extra high reasoning depth for complex problems). Supported service tiers: priority (Fast: 1.5x speed, increased usage).` After: `- 'gpt-5.4': Strong model for everyday coding. Reasoning efforts: low, medium (default), high, xhigh. Service tiers: priority.` --- .../src/tools/handlers/multi_agents_spec.rs | 50 ++++++++++++------- .../tools/handlers/multi_agents_spec_tests.rs | 41 ++++++++++++--- .../tests/suite/spawn_agent_description.rs | 17 +++---- 3 files changed, 75 insertions(+), 33 deletions(-) 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 111ab6779..e1295b50d 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_spec.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_spec.rs @@ -9,6 +9,7 @@ use std::collections::BTreeMap; const SPAWN_AGENT_INHERITED_MODEL_GUIDANCE: &str = "Spawned agents inherit your current model by default. Omit `model` to use that preferred default; set `model` only when an explicit override is needed."; const SPAWN_AGENT_MODEL_OVERRIDE_DESCRIPTION: &str = "Optional model override for the new agent. Leave unset to inherit the same model as the parent, which is the preferred default. Only set this when the user explicitly asks for a different model or the task clearly requires one."; const SPAWN_AGENT_SERVICE_TIER_OVERRIDE_DESCRIPTION: &str = "Optional service tier override for the new agent. Leave unset unless the user explicitly asks for one."; +const MAX_MODEL_OVERRIDES_IN_SPAWN_AGENT_DESCRIPTION: usize = 5; #[derive(Debug, Clone, Default)] pub struct SpawnAgentToolOptions { @@ -711,8 +712,11 @@ The new agent's canonical task name will be provided to it along with the messag } fn spawn_agent_models_description(models: &[ModelPreset]) -> String { - let visible_models: Vec<&ModelPreset> = - models.iter().filter(|model| model.show_in_picker).collect(); + let visible_models: Vec<&ModelPreset> = models + .iter() + .filter(|model| model.show_in_picker) + .take(MAX_MODEL_OVERRIDES_IN_SPAWN_AGENT_DESCRIPTION) + .collect(); if visible_models.is_empty() { return "No picker-visible model overrides are currently loaded.".to_string(); } @@ -720,30 +724,40 @@ fn spawn_agent_models_description(models: &[ModelPreset]) -> String { let model_descriptions = visible_models .into_iter() .map(|model| { + let default_reasoning_effort = model.default_reasoning_effort; let efforts = model .supported_reasoning_efforts .iter() - .map(|preset| format!("{} ({})", preset.effort, preset.description)) + .map(|preset| { + let effort = preset.effort; + if effort == default_reasoning_effort { + format!("{effort} (default)") + } else { + effort.to_string() + } + }) .collect::>() .join(", "); - let service_tiers = if model.service_tiers.is_empty() { - "none".to_string() + let reasoning_efforts_suffix = if efforts.is_empty() { + String::new() } else { - model - .service_tiers - .iter() - .map(|tier| format!("{} ({}: {})", tier.id, tier.name, tier.description)) - .collect::>() - .join(", ") + format!(" Reasoning efforts: {efforts}.") }; + let service_tiers = model + .service_tiers + .iter() + .map(|tier| tier.id.as_str()) + .collect::>() + .join(", "); + let service_tiers_suffix = if service_tiers.is_empty() { + String::new() + } else { + format!(" Service tiers: {service_tiers}.") + }; + let model_slug = &model.model; + let description = &model.description; format!( - "- {} (`{}`): {} Default reasoning effort: {}. Supported reasoning efforts: {}. Supported service tiers: {}.", - model.display_name, - model.model, - model.description, - model.default_reasoning_effort, - efforts, - service_tiers + "- `{model_slug}`: {description}{reasoning_efforts_suffix}{service_tiers_suffix}" ) }) .collect::>() 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 aaa29d6d4..711db2fd1 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 @@ -74,12 +74,10 @@ fn spawn_agent_tool_v2_requires_task_name_and_lists_visible_models() { description .contains("Available model overrides (optional; inherited parent model is preferred):") ); - assert!(description.contains("visible display (`visible-model`)")); - assert!( - description - .contains("Supported service tiers: priority (Fast: 1.5x speed, increased usage).") - ); - assert!(!description.contains("hidden display (`hidden-model`)")); + assert!(description.contains( + "- `visible-model`: visible description Reasoning efforts: medium (default). Service tiers: priority." + )); + assert!(!description.contains("hidden-model")); assert!(properties.contains_key("task_name")); assert!(properties.contains_key("message")); assert!(properties.contains_key("fork_turns")); @@ -150,6 +148,37 @@ fn spawn_agent_tool_v1_keeps_legacy_fork_context_field() { ); } +#[test] +fn spawn_agent_tool_caps_visible_model_summaries() { + let tool = create_spawn_agent_tool_v2(SpawnAgentToolOptions { + available_models: vec![ + model_preset("first", /*show_in_picker*/ true), + model_preset("second", /*show_in_picker*/ true), + model_preset("third", /*show_in_picker*/ true), + model_preset("fourth", /*show_in_picker*/ true), + model_preset("fifth", /*show_in_picker*/ true), + model_preset("sixth", /*show_in_picker*/ true), + ], + agent_type_description: "role help".to_string(), + hide_agent_type_model_reasoning: false, + include_usage_hint: true, + usage_hint_text: None, + max_concurrent_threads_per_session: Some(4), + }); + + let ToolSpec::Function(ResponsesApiTool { description, .. }) = tool else { + panic!("spawn_agent should be a function tool"); + }; + + for model in ["first", "second", "third", "fourth", "fifth"] { + assert!( + description.contains(&format!("`{model}-model`")), + "expected {model} model summary in spawn_agent description: {description:?}" + ); + } + assert!(!description.contains("`sixth-model`")); +} + #[test] fn spawn_agent_tool_hides_service_tier_with_spawn_metadata() { let tool = create_spawn_agent_tool_v2(SpawnAgentToolOptions { diff --git a/codex-rs/core/tests/suite/spawn_agent_description.rs b/codex-rs/core/tests/suite/spawn_agent_description.rs index 5aab77cd7..c70f9bce3 100644 --- a/codex-rs/core/tests/suite/spawn_agent_description.rs +++ b/codex-rs/core/tests/suite/spawn_agent_description.rs @@ -123,6 +123,10 @@ async fn spawn_agent_description_lists_visible_models_and_reasoning_efforts() -> effort: ReasoningEffort::Low, description: "Quick scan".to_string(), }, + ReasoningEffortPreset { + effort: ReasoningEffort::Medium, + description: "Balanced".to_string(), + }, ReasoningEffortPreset { effort: ReasoningEffort::High, description: "Deep dive".to_string(), @@ -175,7 +179,7 @@ async fn spawn_agent_description_lists_visible_models_and_reasoning_efforts() -> spawn_agent_description(&body).expect("spawn_agent description should be present"); assert!( - description.contains("- Visible Model (`visible-model`): Fast and capable"), + description.contains("- `visible-model`: Fast and capable"), "expected visible model summary in spawn_agent description: {description:?}" ); assert!( @@ -196,20 +200,15 @@ async fn spawn_agent_description_lists_visible_models_and_reasoning_efforts() -> "expected model override usage guidance in spawn_agent description: {description:?}" ); assert!( - description.contains("Default reasoning effort: medium."), + description.contains("Reasoning efforts: low, medium (default), high."), "expected default reasoning effort in spawn_agent description: {description:?}" ); assert!( - description.contains("low (Quick scan), high (Deep dive)."), - "expected reasoning efforts in spawn_agent description: {description:?}" - ); - assert!( - description - .contains("Supported service tiers: priority (Fast: 1.5x speed, increased usage)."), + description.contains("Service tiers: priority."), "expected service tier guidance in spawn_agent description: {description:?}" ); assert!( - !description.contains("Hidden Model"), + !description.contains("hidden-model"), "hidden picker model should be omitted from spawn_agent description: {description:?}" ); assert!(