[codex] Add Ultra reasoning effort (#29899)

## Why

Ultra should be one user-facing reasoning selection for work that
benefits from both maximum reasoning and proactive multi-agent
delegation. Without it, clients must coordinate maximum reasoning with
the experimental `multiAgentMode` setting, even though the inference
backend still expects its existing `max` effort value.

This change makes reasoning effort the source of truth: clients select
`ultra`, core derives proactive multi-agent behavior when the turn is
eligible for multi-agent V2, and inference requests continue to use the
backend-compatible `max` value.

## What changed

- Add `ultra` as a first-class reasoning effort and preserve
model-catalog ordering when exposing it to clients.
- Convert `ultra` to `max` at the inference request boundary, including
Responses HTTP/WebSocket requests, startup prewarm, compaction, and
memory summarization.
- Derive effective multi-agent mode per turn from effective reasoning
effort:
  - eligible multi-agent V2 + `ultra` → `proactive`
  - eligible multi-agent V2 + any other effort → `explicitRequestOnly`
- V1 or otherwise ineligible sessions → no multi-agent mode instruction
- Keep the derived effective mode in turn context history so successive
turns can emit a developer-message update only when the effective mode
changes.
- Remove selected multi-agent mode from core session configuration, turn
construction, thread settings, resume/fork restoration, and subagent
spawn plumbing. Subagents inherit reasoning effort and derive their own
effective mode.
- Retain the experimental app-server `multiAgentMode` fields for wire
compatibility while marking them deprecated. Request values are accepted
but ignored; compatibility response fields report `explicitRequestOnly`.
- Display Ultra in the TUI using the order supplied by `model/list`.

## Validation

- `just test -p codex-core ultra_reasoning_uses_max_for_requests`
- `just test -p codex-tui model_reasoning_selection_popup`
This commit is contained in:
Shijie Rao
2026-06-24 20:13:52 -07:00
committed by GitHub
Unverified
parent fa036d39aa
commit df1199fddb
41 changed files with 172 additions and 651 deletions
-2
View File
@@ -19,7 +19,6 @@ use crate::thread_rollout_truncation::truncate_rollout_to_last_n_fork_turns;
use codex_protocol::AgentPath;
use codex_protocol::SessionId;
use codex_protocol::ThreadId;
use codex_protocol::config_types::MultiAgentMode;
use codex_protocol::error::CodexErr;
use codex_protocol::error::Result as CodexResult;
use codex_protocol::models::ContentItem;
@@ -68,7 +67,6 @@ pub(crate) struct SpawnAgentOptions {
pub(crate) fork_mode: Option<SpawnAgentForkMode>,
pub(crate) parent_thread_id: Option<ThreadId>,
pub(crate) environments: Option<Vec<TurnEnvironmentSelection>>,
pub(crate) initial_multi_agent_mode: Option<MultiAgentMode>,
}
#[derive(Clone, Debug)]
@@ -142,7 +142,6 @@ async fn spawn_v2_subagent(
/*forked_from_thread_id*/ None,
Some(ThreadSource::Subagent),
/*metrics_service_name*/ None,
/*initial_multi_agent_mode*/ None,
/*inherited_environments*/ None,
/*inherited_exec_policy*/ None,
/*environments*/ None,
-6
View File
@@ -1,13 +1,11 @@
use super::residency::is_v2_resident_session_source;
use super::*;
use codex_protocol::config_types::MultiAgentMode;
const AGENT_NAMES: &str = include_str!("../agent_names.txt");
struct SpawnAgentThreadInheritance {
environments: Option<TurnEnvironmentSnapshot>,
exec_policy: Option<Arc<crate::exec_policy::ExecPolicyManager>>,
inherited_multi_agent_mode: Option<MultiAgentMode>,
}
fn default_agent_nickname_list() -> Vec<&'static str> {
@@ -241,7 +239,6 @@ impl AgentControl {
exec_policy: self
.inherited_exec_policy_for_source(&state, session_source.as_ref(), &config)
.await,
inherited_multi_agent_mode: options.initial_multi_agent_mode,
};
let (session_source, mut agent_metadata) = match session_source {
Some(SessionSource::SubAgent(SubAgentSource::ThreadSpawn {
@@ -288,7 +285,6 @@ impl AgentControl {
/*forked_from_thread_id*/ None,
/*thread_source*/ Some(ThreadSource::Subagent),
/*metrics_service_name*/ None,
inheritance.inherited_multi_agent_mode,
inheritance.environments,
inheritance.exec_policy,
options.environments.clone(),
@@ -394,7 +390,6 @@ impl AgentControl {
let SpawnAgentThreadInheritance {
environments: inherited_environments,
exec_policy: inherited_exec_policy,
inherited_multi_agent_mode,
} = inheritance;
if options.fork_parent_spawn_call_id.is_none() {
return Err(CodexErr::Fatal(
@@ -519,7 +514,6 @@ impl AgentControl {
/*thread_source*/ Some(ThreadSource::Subagent),
/*parent_thread_id*/ Some(parent_thread_id),
/*forked_from_thread_id*/ Some(parent_thread_id),
inherited_multi_agent_mode,
inherited_environments,
inherited_exec_policy,
options.environments.clone(),
+3 -91
View File
@@ -18,7 +18,6 @@ use codex_login::AuthManager;
use codex_login::CodexAuth;
use codex_protocol::AgentPath;
use codex_protocol::config_types::ModeKind;
use codex_protocol::config_types::MultiAgentMode;
use codex_protocol::models::ContentItem;
use codex_protocol::models::MessagePhase;
use codex_protocol::models::ResponseItem;
@@ -889,42 +888,6 @@ async fn ephemeral_spawn_does_not_persist_agent_graph_edge() {
);
}
#[tokio::test]
async fn spawn_thread_subagent_uses_supplied_initial_multi_agent_mode_without_history() {
let harness = AgentControlHarness::new().await;
let (parent_thread_id, _parent_thread) = harness.start_thread().await;
let child_thread_id = harness
.control
.spawn_agent_with_metadata(
harness.config.clone(),
text_input("child task"),
Some(SessionSource::SubAgent(SubAgentSource::ThreadSpawn {
parent_thread_id,
depth: 1,
agent_path: None,
agent_nickname: None,
agent_role: None,
})),
SpawnAgentOptions {
initial_multi_agent_mode: Some(MultiAgentMode::Proactive),
..Default::default()
},
)
.await
.expect("spawn child without parent history")
.thread_id;
let child_snapshot = harness
.manager
.get_thread(child_thread_id)
.await
.expect("child thread should be registered")
.config_snapshot()
.await;
assert_eq!(child_snapshot.multi_agent_mode, MultiAgentMode::Proactive);
}
#[tokio::test]
async fn spawn_agent_can_fork_parent_thread_history_with_sanitized_items() {
let harness = AgentControlHarness::new().await;
@@ -947,15 +910,6 @@ async fn spawn_agent_can_fork_parent_thread_history_with_sanitized_items() {
.expect("start parent thread");
let parent_thread_id = new_thread.thread_id;
let parent_thread = new_thread.thread;
parent_thread
.codex
.session
.update_settings(crate::session::SessionSettingsUpdate {
multi_agent_mode: Some(MultiAgentMode::Proactive),
..Default::default()
})
.await
.expect("update parent multi-agent mode");
parent_thread
.inject_user_message_without_turn("parent seed context".to_string())
.await;
@@ -1050,7 +1004,6 @@ async fn spawn_agent_can_fork_parent_thread_history_with_sanitized_items() {
SpawnAgentOptions {
fork_parent_spawn_call_id: Some(parent_spawn_call_id.clone()),
fork_mode: Some(SpawnAgentForkMode::FullHistory),
initial_multi_agent_mode: Some(MultiAgentMode::Proactive),
..Default::default()
},
)
@@ -1063,10 +1016,6 @@ async fn spawn_agent_can_fork_parent_thread_history_with_sanitized_items() {
.get_thread(child_thread_id)
.await
.expect("child thread should be registered");
assert_eq!(
child_thread.config_snapshot().await.multi_agent_mode,
MultiAgentMode::Proactive
);
assert_ne!(child_thread_id, parent_thread_id);
let history = child_thread.codex.session.clone_history().await;
let mut expected_final_answer =
@@ -1359,15 +1308,6 @@ async fn spawn_agent_fork_flushes_parent_rollout_before_loading_history() {
async fn spawn_agent_fork_last_n_turns_keeps_only_recent_turns() {
let harness = AgentControlHarness::new().await;
let (parent_thread_id, parent_thread) = harness.start_thread().await;
parent_thread
.codex
.session
.update_settings(crate::session::SessionSettingsUpdate {
multi_agent_mode: Some(MultiAgentMode::Proactive),
..Default::default()
})
.await
.expect("update parent multi-agent mode");
parent_thread
.inject_user_message_without_turn("old parent context".to_string())
@@ -1452,7 +1392,6 @@ async fn spawn_agent_fork_last_n_turns_keeps_only_recent_turns() {
SpawnAgentOptions {
fork_parent_spawn_call_id: Some(parent_spawn_call_id.clone()),
fork_mode: Some(SpawnAgentForkMode::LastNTurns(2)),
initial_multi_agent_mode: Some(MultiAgentMode::Proactive),
..Default::default()
},
)
@@ -1465,10 +1404,6 @@ async fn spawn_agent_fork_last_n_turns_keeps_only_recent_turns() {
.get_thread(child_thread_id)
.await
.expect("child thread should be registered");
assert_eq!(
child_thread.config_snapshot().await.multi_agent_mode,
MultiAgentMode::Proactive
);
let history = child_thread.codex.session.clone_history().await;
assert!(
@@ -2283,7 +2218,6 @@ async fn spawn_thread_subagents_persist_parent_originator_across_new_and_truncat
thread_source: None,
dynamic_tools: Vec::new(),
metrics_service_name: Some("codex_work_desktop".to_string()),
multi_agent_mode: None,
parent_trace: None,
environments: Vec::new(),
thread_extension_init: ExtensionDataInit::default(),
@@ -2393,7 +2327,7 @@ async fn spawn_thread_subagent_uses_role_specific_nickname_candidates() {
}
#[tokio::test]
async fn resume_thread_subagent_restores_stored_metadata_and_effective_multi_agent_mode() {
async fn resume_thread_subagent_restores_stored_metadata() {
let (home, config) = test_config().await;
let thread_store = Arc::new(InMemoryThreadStore::default());
let manager = ThreadManager::new(
@@ -2418,7 +2352,7 @@ async fn resume_thread_subagent_restores_stored_metadata_and_effective_multi_age
manager,
control,
};
let (parent_thread_id, parent_thread) = harness.start_thread().await;
let (parent_thread_id, _parent_thread) = harness.start_thread().await;
let agent_path = AgentPath::from_string("/root/explorer".to_string())
.expect("test agent path should be valid");
@@ -2443,18 +2377,6 @@ async fn resume_thread_subagent_restores_stored_metadata_and_effective_multi_age
.get_thread(child_thread_id)
.await
.expect("child thread should exist");
let mut child_turn_context = child_thread
.codex
.session
.new_default_turn()
.await
.to_turn_context_item();
child_turn_context.multi_agent_mode = Some(MultiAgentMode::Proactive);
child_thread
.codex
.session
.persist_rollout_items(&[RolloutItem::TurnContext(child_turn_context)])
.await;
child_thread
.codex
.session
@@ -2465,16 +2387,7 @@ async fn resume_thread_subagent_restores_stored_metadata_and_effective_multi_age
.session
.flush_rollout()
.await
.expect("flush child effective multi-agent mode");
parent_thread
.codex
.session
.update_settings(crate::session::SessionSettingsUpdate {
multi_agent_mode: Some(MultiAgentMode::ExplicitRequestOnly),
..Default::default()
})
.await
.expect("change parent multi-agent mode before child resume");
.expect("flush child rollout");
let mut status_rx = harness
.control
.subscribe_status(child_thread_id)
@@ -2567,7 +2480,6 @@ async fn resume_thread_subagent_restores_stored_metadata_and_effective_multi_age
assert_eq!(resumed_agent_path, Some(agent_path));
assert_eq!(resumed_nickname, Some(original_nickname));
assert_eq!(resumed_role, Some("explorer".to_string()));
assert_eq!(resumed_snapshot.multi_agent_mode, MultiAgentMode::Proactive);
let _ = harness
.control
+17 -6
View File
@@ -163,6 +163,13 @@ pub(crate) struct CompactConversationRequestSettings {
pub(crate) service_tier: Option<String>,
}
fn reasoning_effort_for_request(effort: ReasoningEffortConfig) -> ReasoningEffortConfig {
match effort {
ReasoningEffortConfig::Ultra => ReasoningEffortConfig::Custom("max".to_string()),
effort => effort,
}
}
fn session_telemetry_for_request(
session_telemetry: &SessionTelemetry,
request: &ResponsesApiRequest,
@@ -665,11 +672,13 @@ impl ModelClient {
let payload = ApiMemorySummarizeInput {
model: model_info.slug.clone(),
raw_memories,
reasoning: effort.map(|effort| Reasoning {
effort: Some(effort),
summary: None,
context: None,
}),
reasoning: effort
.map(reasoning_effort_for_request)
.map(|effort| Reasoning {
effort: Some(effort),
summary: None,
context: None,
}),
};
client
@@ -768,7 +777,9 @@ impl ModelClient {
) -> Option<Reasoning> {
if model_info.supports_reasoning_summaries {
Some(Reasoning {
effort: effort.or_else(|| model_info.default_reasoning_level.clone()),
effort: effort
.or_else(|| model_info.default_reasoning_level.clone())
.map(reasoning_effort_for_request),
summary: if summary == ReasoningSummaryConfig::None {
None
} else {
+15
View File
@@ -31,6 +31,7 @@ use codex_protocol::auth::AuthMode;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ResponseItem;
use codex_protocol::openai_models::ModelInfo;
use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::InternalSessionSource;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SubAgentSource;
@@ -154,6 +155,20 @@ fn test_session_telemetry() -> SessionTelemetry {
)
}
#[test]
fn ultra_reasoning_uses_max_for_requests() {
assert_eq!(
(
super::reasoning_effort_for_request(ReasoningEffort::Ultra),
super::reasoning_effort_for_request(ReasoningEffort::High),
),
(
ReasoningEffort::Custom("max".to_string()),
ReasoningEffort::High,
)
);
}
#[derive(Default)]
struct TagCollectorVisitor {
tags: BTreeMap<String, String>,
-1
View File
@@ -123,7 +123,6 @@ pub(crate) async fn run_codex_thread_interactive(
attestation_provider: parent_session.services.attestation_provider.clone(),
external_time_provider: Some(Arc::clone(&parent_session.services.time_provider)),
inherited_multi_agent_version: Some(MultiAgentVersion::Disabled),
initial_multi_agent_mode: None,
}))
.or_cancel(&cancel_token)
.await??;
-5
View File
@@ -8,7 +8,6 @@ use codex_otel::SessionTelemetry;
use codex_protocol::ThreadId;
use codex_protocol::config_types::ApprovalsReviewer;
use codex_protocol::config_types::CollaborationMode;
use codex_protocol::config_types::MultiAgentMode;
use codex_protocol::config_types::Personality;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::WindowsSandboxLevel;
@@ -72,7 +71,6 @@ pub struct ThreadConfigSnapshot {
pub reasoning_summary: Option<ReasoningSummary>,
pub personality: Option<Personality>,
pub collaboration_mode: CollaborationMode,
pub multi_agent_mode: MultiAgentMode,
pub session_source: SessionSource,
pub forked_from_thread_id: Option<ThreadId>,
pub parent_thread_id: Option<ThreadId>,
@@ -154,7 +152,6 @@ pub struct CodexThreadSettingsOverrides {
pub summary: Option<ReasoningSummary>,
pub service_tier: Option<Option<String>>,
pub collaboration_mode: Option<CollaborationMode>,
pub multi_agent_mode: Option<MultiAgentMode>,
pub personality: Option<Personality>,
}
@@ -375,7 +372,6 @@ impl CodexThread {
summary,
service_tier,
collaboration_mode,
multi_agent_mode,
personality,
} = overrides;
let collaboration_mode = if let Some(collaboration_mode) = collaboration_mode {
@@ -399,7 +395,6 @@ impl CodexThread {
active_permission_profile,
windows_sandbox_level,
collaboration_mode: Some(collaboration_mode),
multi_agent_mode,
reasoning_summary: summary,
service_tier,
personality,
+1 -5
View File
@@ -78,11 +78,7 @@ fn build_multi_agent_mode_update_item(
previous: Option<&TurnContextItem>,
next: &TurnContext,
) -> Option<String> {
let effective_multi_agent_mode = crate::session::multi_agents::effective_multi_agent_mode(
next.multi_agent_version,
&next.session_source,
next.multi_agent_mode,
);
let effective_multi_agent_mode = crate::session::multi_agents::effective_multi_agent_mode(next);
let previous = previous?;
if previous.multi_agent_mode == effective_multi_agent_mode {
return None;
-3
View File
@@ -124,7 +124,6 @@ async fn thread_settings_update(
summary,
service_tier,
collaboration_mode,
multi_agent_mode,
personality,
} = thread_settings;
let collaboration_mode = match collaboration_mode {
@@ -150,7 +149,6 @@ async fn thread_settings_update(
active_permission_profile,
windows_sandbox_level,
collaboration_mode: Some(collaboration_mode),
multi_agent_mode,
reasoning_summary: summary,
service_tier,
personality,
@@ -178,7 +176,6 @@ async fn thread_settings_applied_event(sess: &Session) -> EventMsg {
reasoning_summary: snapshot.reasoning_summary,
personality: snapshot.personality,
collaboration_mode: snapshot.collaboration_mode,
multi_agent_mode: snapshot.multi_agent_mode,
},
})
}
+1 -9
View File
@@ -453,7 +453,6 @@ pub(crate) struct CodexSpawnArgs {
pub(crate) attestation_provider: Option<Arc<dyn AttestationProvider>>,
pub(crate) external_time_provider: Option<Arc<dyn TimeProvider>>,
pub(crate) inherited_multi_agent_version: Option<MultiAgentVersion>,
pub(crate) initial_multi_agent_mode: Option<MultiAgentMode>,
}
pub(crate) fn resolve_multi_agent_version(
@@ -539,7 +538,6 @@ impl Codex {
attestation_provider,
external_time_provider,
inherited_multi_agent_version,
initial_multi_agent_mode,
} = args;
let (tx_sub, rx_sub) = async_channel::bounded(SUBMISSION_CHANNEL_CAPACITY);
let (tx_event, rx_event) = async_channel::unbounded();
@@ -594,7 +592,6 @@ impl Codex {
.await;
let multi_agent_version =
resolve_multi_agent_version(&conversation_history, inherited_multi_agent_version);
let multi_agent_mode = initial_multi_agent_mode.unwrap_or_default();
config
.validate_multi_agent_v2_config()
.map_err(|err| CodexErr::InvalidRequest(err.to_string()))?;
@@ -628,7 +625,6 @@ impl Codex {
let session_configuration = SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode,
model_reasoning_summary: config.model_reasoning_summary,
service_tier,
developer_instructions: config.developer_instructions.clone(),
@@ -3402,11 +3398,7 @@ impl Session {
{
items.push(usage_hint_message);
}
match multi_agents::effective_multi_agent_mode(
turn_context.multi_agent_version,
&session_source,
turn_context.multi_agent_mode,
) {
match multi_agents::effective_multi_agent_mode(turn_context) {
Some(
multi_agent_mode
@ (MultiAgentMode::ExplicitRequestOnly | MultiAgentMode::Proactive),
+9 -7
View File
@@ -1,6 +1,7 @@
use crate::config::MultiAgentV2Config;
use crate::session::turn_context::TurnContext;
use codex_protocol::config_types::MultiAgentMode;
use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::MultiAgentVersion;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SubAgentSource;
@@ -35,16 +36,17 @@ fn configured_usage_hint_text_for_source<'a>(
}
}
pub(crate) fn effective_multi_agent_mode(
multi_agent_version: MultiAgentVersion,
session_source: &SessionSource,
multi_agent_mode: MultiAgentMode,
) -> Option<MultiAgentMode> {
if multi_agent_version != MultiAgentVersion::V2 {
pub(crate) fn effective_multi_agent_mode(turn_context: &TurnContext) -> Option<MultiAgentMode> {
if turn_context.multi_agent_version != MultiAgentVersion::V2 {
return None;
}
match session_source {
let multi_agent_mode = match turn_context.effective_reasoning_effort() {
Some(ReasoningEffort::Ultra) => MultiAgentMode::Proactive,
_ => MultiAgentMode::ExplicitRequestOnly,
};
match &turn_context.session_source {
SessionSource::SubAgent(SubAgentSource::ThreadSpawn { .. })
| SessionSource::Cli
| SessionSource::VSCode
-1
View File
@@ -128,7 +128,6 @@ pub(super) async fn spawn_review_thread(
developer_instructions: None,
user_instructions: None,
collaboration_mode: parent_turn_context.collaboration_mode.clone(),
multi_agent_mode: parent_turn_context.multi_agent_mode,
multi_agent_version: MultiAgentVersion::Disabled,
personality: parent_turn_context.personality,
approval_policy: parent_turn_context.approval_policy.clone(),
-6
View File
@@ -52,7 +52,6 @@ pub(crate) struct SessionConfiguration {
pub(super) provider: ModelProviderInfo,
pub(super) collaboration_mode: CollaborationMode,
pub(super) multi_agent_mode: MultiAgentMode,
pub(super) model_reasoning_summary: Option<ReasoningSummaryConfig>,
pub(super) service_tier: Option<String>,
@@ -195,7 +194,6 @@ impl SessionConfiguration {
reasoning_summary: self.model_reasoning_summary,
personality: self.personality,
collaboration_mode: self.collaboration_mode.clone(),
multi_agent_mode: self.multi_agent_mode,
session_source: self.session_source.clone(),
forked_from_thread_id: self.forked_from_thread_id,
parent_thread_id: self.parent_thread_id,
@@ -233,9 +231,6 @@ impl SessionConfiguration {
if let Some(collaboration_mode) = updates.collaboration_mode.clone() {
next_configuration.collaboration_mode = collaboration_mode;
}
if let Some(multi_agent_mode) = updates.multi_agent_mode {
next_configuration.multi_agent_mode = multi_agent_mode;
}
if let Some(summary) = updates.reasoning_summary {
next_configuration.model_reasoning_summary = Some(summary);
}
@@ -430,7 +425,6 @@ pub(crate) struct SessionSettingsUpdate {
pub(crate) active_permission_profile: Option<ActivePermissionProfile>,
pub(crate) windows_sandbox_level: Option<WindowsSandboxLevel>,
pub(crate) collaboration_mode: Option<CollaborationMode>,
pub(crate) multi_agent_mode: Option<MultiAgentMode>,
pub(crate) reasoning_summary: Option<ReasoningSummaryConfig>,
pub(crate) service_tier: Option<Option<String>>,
pub(crate) final_output_json_schema: Option<Option<Value>>,
-8
View File
@@ -3651,7 +3651,6 @@ async fn set_rate_limits_retains_previous_credits() {
let session_configuration = SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode: Default::default(),
model_reasoning_summary: config.model_reasoning_summary,
developer_instructions: config.developer_instructions.clone(),
loaded_agents_md: None,
@@ -3759,7 +3758,6 @@ async fn set_rate_limits_updates_plan_type_when_present() {
let session_configuration = SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode: Default::default(),
model_reasoning_summary: config.model_reasoning_summary,
developer_instructions: config.developer_instructions.clone(),
loaded_agents_md: None,
@@ -4291,7 +4289,6 @@ pub(crate) async fn make_session_configuration_for_tests() -> SessionConfigurati
SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode: Default::default(),
model_reasoning_summary: config.model_reasoning_summary,
developer_instructions: config.developer_instructions.clone(),
loaded_agents_md: None,
@@ -5163,7 +5160,6 @@ async fn session_new_fails_when_zsh_fork_enabled_without_packaged_zsh() {
let session_configuration = SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode: Default::default(),
model_reasoning_summary: config.model_reasoning_summary,
developer_instructions: config.developer_instructions.clone(),
loaded_agents_md: None,
@@ -5293,7 +5289,6 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
let session_configuration = SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode: Default::default(),
model_reasoning_summary: config.model_reasoning_summary,
developer_instructions: config.developer_instructions.clone(),
loaded_agents_md: None,
@@ -5541,7 +5536,6 @@ async fn make_session_with_config_and_rx(
let session_configuration = SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode: Default::default(),
model_reasoning_summary: config.model_reasoning_summary,
developer_instructions: config.developer_instructions.clone(),
loaded_agents_md: None,
@@ -5649,7 +5643,6 @@ async fn make_session_with_history_source_and_agent_control_and_rx(
let session_configuration = SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode: Default::default(),
model_reasoning_summary: config.model_reasoning_summary,
developer_instructions: config.developer_instructions.clone(),
loaded_agents_md: None,
@@ -7374,7 +7367,6 @@ where
let session_configuration = SessionConfiguration {
provider: config.model_provider.clone(),
collaboration_mode,
multi_agent_mode: Default::default(),
model_reasoning_summary: config.model_reasoning_summary,
developer_instructions: config.developer_instructions.clone(),
loaded_agents_md: None,
@@ -750,7 +750,6 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() {
attestation_provider: None,
external_time_provider: None,
inherited_multi_agent_version: None,
initial_multi_agent_mode: None,
})
.await
.expect("spawn guardian subagent");
+1 -8
View File
@@ -126,7 +126,6 @@ pub struct TurnContext {
pub(crate) developer_instructions: Option<String>,
pub(crate) user_instructions: Option<String>,
pub(crate) collaboration_mode: CollaborationMode,
pub(crate) multi_agent_mode: MultiAgentMode,
pub(crate) multi_agent_version: MultiAgentVersion,
pub(crate) personality: Option<Personality>,
pub(crate) approval_policy: Constrained<AskForApproval>,
@@ -276,7 +275,6 @@ impl TurnContext {
developer_instructions: self.developer_instructions.clone(),
user_instructions: self.user_instructions.clone(),
collaboration_mode,
multi_agent_mode: self.multi_agent_mode,
multi_agent_version: self.multi_agent_version,
personality: self.personality,
approval_policy: self.approval_policy.clone(),
@@ -375,11 +373,7 @@ impl TurnContext {
personality: self.personality,
collaboration_mode: Some(self.collaboration_mode.clone()),
multi_agent_version: Some(self.multi_agent_version),
multi_agent_mode: super::multi_agents::effective_multi_agent_mode(
self.multi_agent_version,
&self.session_source,
self.multi_agent_mode,
),
multi_agent_mode: super::multi_agents::effective_multi_agent_mode(self),
realtime_active: Some(self.realtime_active),
effort: self.reasoning_effort.clone(),
summary: ReasoningSummaryConfig::Auto,
@@ -563,7 +557,6 @@ impl Session {
.as_ref()
.map(LoadedAgentsMd::render),
collaboration_mode: session_configuration.collaboration_mode.clone(),
multi_agent_mode: session_configuration.multi_agent_mode,
multi_agent_version,
personality: session_configuration.personality,
approval_policy: session_configuration.approval_policy.clone(),
-28
View File
@@ -40,7 +40,6 @@ use codex_models_manager::manager::RefreshStrategy;
use codex_models_manager::manager::SharedModelsManager;
use codex_protocol::ThreadId;
use codex_protocol::config_types::CollaborationModeMask;
use codex_protocol::config_types::MultiAgentMode;
use codex_protocol::error::CodexErr;
use codex_protocol::error::Result as CodexResult;
use codex_protocol::openai_models::ModelPreset;
@@ -188,7 +187,6 @@ pub struct StartThreadOptions {
pub thread_source: Option<ThreadSource>,
pub dynamic_tools: Vec<codex_protocol::dynamic_tools::DynamicToolSpec>,
pub metrics_service_name: Option<String>,
pub multi_agent_mode: Option<MultiAgentMode>,
pub parent_trace: Option<W3cTraceContext>,
pub environments: Vec<TurnEnvironmentSelection>,
pub thread_extension_init: ExtensionDataInit,
@@ -639,7 +637,6 @@ impl ThreadManager {
thread_source: None,
dynamic_tools,
metrics_service_name: None,
multi_agent_mode: None,
parent_trace: None,
environments,
thread_extension_init: ExtensionDataInit::default(),
@@ -679,7 +676,6 @@ impl ThreadManager {
thread_source,
options.dynamic_tools,
options.metrics_service_name,
options.multi_agent_mode,
/*inherited_environments*/ None,
/*inherited_exec_policy*/ None,
options.parent_trace,
@@ -764,7 +760,6 @@ impl ThreadManager {
let (session_source, thread_source) = initial_history
.get_resumed_session_sources()
.unwrap_or_else(|| (self.state.session_source.clone(), None));
let initial_multi_agent_mode = initial_history.get_latest_effective_multi_agent_mode();
Box::pin(self.state.spawn_thread_with_source(
config,
initial_history,
@@ -776,7 +771,6 @@ impl ThreadManager {
thread_source,
Vec::new(),
/*metrics_service_name*/ None,
initial_multi_agent_mode,
/*inherited_environments*/ None,
/*inherited_exec_policy*/ None,
parent_trace,
@@ -809,7 +803,6 @@ impl ThreadManager {
/*thread_source*/ None,
Vec::new(),
/*metrics_service_name*/ None,
/*initial_multi_agent_mode*/ None,
/*parent_trace*/ None,
environments,
/*thread_extension_init*/ ExtensionDataInit::default(),
@@ -836,7 +829,6 @@ impl ThreadManager {
let (session_source, thread_source) = initial_history
.get_resumed_session_sources()
.unwrap_or_else(|| (self.state.session_source.clone(), None));
let initial_multi_agent_mode = initial_history.get_latest_effective_multi_agent_mode();
Box::pin(self.state.spawn_thread_with_source(
config,
initial_history,
@@ -848,7 +840,6 @@ impl ThreadManager {
thread_source,
Vec::new(),
/*metrics_service_name*/ None,
initial_multi_agent_mode,
/*inherited_environments*/ None,
/*inherited_exec_policy*/ None,
/*parent_trace*/ None,
@@ -1004,13 +995,6 @@ impl ThreadManager {
InitialHistory::Forked(_) => history.forked_from_id(),
InitialHistory::New | InitialHistory::Cleared => None,
};
let initial_multi_agent_mode = match source_thread_id {
Some(thread_id) => match self.get_thread(thread_id).await {
Ok(thread) => Some(thread.config_snapshot().await.multi_agent_mode),
Err(_) => history.get_latest_effective_multi_agent_mode(),
},
None => history.get_latest_effective_multi_agent_mode(),
};
let multi_agent_version = self
.state
.effective_multi_agent_version_for_spawn(
@@ -1039,7 +1023,6 @@ impl ThreadManager {
thread_source,
Vec::new(),
/*metrics_service_name*/ None,
initial_multi_agent_mode,
parent_trace,
environments,
/*thread_extension_init*/ ExtensionDataInit::default(),
@@ -1322,7 +1305,6 @@ impl ThreadManagerState {
/*forked_from_thread_id*/ None,
/*thread_source*/ None,
/*metrics_service_name*/ None,
/*initial_multi_agent_mode*/ None,
/*inherited_environments*/ None,
/*inherited_exec_policy*/ None,
/*environments*/ None,
@@ -1340,7 +1322,6 @@ impl ThreadManagerState {
forked_from_thread_id: Option<ThreadId>,
thread_source: Option<ThreadSource>,
metrics_service_name: Option<String>,
initial_multi_agent_mode: Option<MultiAgentMode>,
inherited_environments: Option<TurnEnvironmentSnapshot>,
inherited_exec_policy: Option<Arc<crate::exec_policy::ExecPolicyManager>>,
environments: Option<Vec<TurnEnvironmentSelection>>,
@@ -1359,7 +1340,6 @@ impl ThreadManagerState {
thread_source,
Vec::new(),
metrics_service_name,
initial_multi_agent_mode,
inherited_environments,
inherited_exec_policy,
/*parent_trace*/ None,
@@ -1387,7 +1367,6 @@ impl ThreadManagerState {
let environments =
default_thread_environment_selections(self.environment_manager.as_ref(), &config.cwd);
let thread_source = initial_history.get_resumed_thread_source();
let initial_multi_agent_mode = initial_history.get_latest_effective_multi_agent_mode();
Box::pin(self.spawn_thread_with_source(
config,
initial_history,
@@ -1399,7 +1378,6 @@ impl ThreadManagerState {
thread_source,
Vec::new(),
/*metrics_service_name*/ None,
initial_multi_agent_mode,
inherited_environments,
inherited_exec_policy,
/*parent_trace*/ None,
@@ -1421,7 +1399,6 @@ impl ThreadManagerState {
thread_source: Option<ThreadSource>,
parent_thread_id: Option<ThreadId>,
forked_from_thread_id: Option<ThreadId>,
initial_multi_agent_mode: Option<MultiAgentMode>,
inherited_environments: Option<TurnEnvironmentSnapshot>,
inherited_exec_policy: Option<Arc<crate::exec_policy::ExecPolicyManager>>,
environments: Option<Vec<TurnEnvironmentSelection>>,
@@ -1440,7 +1417,6 @@ impl ThreadManagerState {
thread_source,
Vec::new(),
/*metrics_service_name*/ None,
initial_multi_agent_mode,
inherited_environments,
inherited_exec_policy,
/*parent_trace*/ None,
@@ -1465,7 +1441,6 @@ impl ThreadManagerState {
thread_source: Option<ThreadSource>,
dynamic_tools: Vec<codex_protocol::dynamic_tools::DynamicToolSpec>,
metrics_service_name: Option<String>,
initial_multi_agent_mode: Option<MultiAgentMode>,
parent_trace: Option<W3cTraceContext>,
environments: Vec<TurnEnvironmentSelection>,
thread_extension_init: ExtensionDataInit,
@@ -1483,7 +1458,6 @@ impl ThreadManagerState {
thread_source,
dynamic_tools,
metrics_service_name,
initial_multi_agent_mode,
/*inherited_environments*/ None,
/*inherited_exec_policy*/ None,
parent_trace,
@@ -1508,7 +1482,6 @@ impl ThreadManagerState {
thread_source: Option<ThreadSource>,
dynamic_tools: Vec<codex_protocol::dynamic_tools::DynamicToolSpec>,
metrics_service_name: Option<String>,
initial_multi_agent_mode: Option<MultiAgentMode>,
inherited_environments: Option<TurnEnvironmentSnapshot>,
inherited_exec_policy: Option<Arc<crate::exec_policy::ExecPolicyManager>>,
parent_trace: Option<W3cTraceContext>,
@@ -1598,7 +1571,6 @@ impl ThreadManagerState {
attestation_provider: self.attestation_provider.clone(),
external_time_provider: self.external_time_provider.clone(),
inherited_multi_agent_version: multi_agent_version,
initial_multi_agent_mode,
}))
.await?;
let new_thread = self
@@ -404,7 +404,6 @@ async fn start_thread_keeps_internal_threads_hidden_from_normal_lookups() {
thread_source: None,
dynamic_tools: Vec::new(),
metrics_service_name: None,
multi_agent_mode: None,
parent_trace: None,
environments: Vec::new(),
thread_extension_init: Default::default(),
@@ -545,7 +544,6 @@ async fn start_thread_seeds_extension_data_for_mcp_and_lifecycle_contributors()
thread_source: None,
dynamic_tools: Vec::new(),
metrics_service_name: None,
multi_agent_mode: None,
parent_trace: None,
environments: Vec::new(),
thread_extension_init: selected_root_init("selected-a", "env-a"),
@@ -561,7 +559,6 @@ async fn start_thread_seeds_extension_data_for_mcp_and_lifecycle_contributors()
thread_source: None,
dynamic_tools: Vec::new(),
metrics_service_name: None,
multi_agent_mode: None,
parent_trace: None,
environments: Vec::new(),
thread_extension_init: selected_root_init("selected-b", "env-b"),
@@ -654,7 +651,6 @@ async fn resume_and_fork_do_not_restore_thread_environments_from_rollout() {
thread_source: None,
dynamic_tools: Vec::new(),
metrics_service_name: None,
multi_agent_mode: None,
parent_trace: None,
environments: environments.clone(),
thread_extension_init: Default::default(),
@@ -938,7 +934,6 @@ async fn resume_stopped_thread_from_rollout_preserves_thread_source() {
thread_source: Some(ThreadSource::User),
dynamic_tools: Vec::new(),
metrics_service_name: None,
multi_agent_mode: None,
parent_trace: None,
environments: Vec::new(),
thread_extension_init: Default::default(),
@@ -132,7 +132,6 @@ async fn handle_spawn_agent(
fork_mode: args.fork_context.then_some(SpawnAgentForkMode::FullHistory),
parent_thread_id: Some(session.thread_id),
environments: Some(turn.environments.to_selections()),
initial_multi_agent_mode: None,
},
))
.await
@@ -26,7 +26,6 @@ use codex_model_provider_info::built_in_model_providers;
use codex_protocol::AgentPath;
use codex_protocol::ThreadId;
use codex_protocol::config_types::ApprovalsReviewer;
use codex_protocol::config_types::MultiAgentMode;
use codex_protocol::config_types::ServiceTier;
use codex_protocol::config_types::ShellEnvironmentPolicy;
use codex_protocol::models::BaseInstructions;
@@ -1152,7 +1151,6 @@ async fn multi_agent_v2_spawn_returns_path_and_send_message_accepts_relative_pat
.features
.enable(Feature::MultiAgentV2)
.expect("test config should allow feature update");
turn.multi_agent_mode = MultiAgentMode::Proactive;
set_turn_config(&mut turn, config);
let session = Arc::new(session);
@@ -1191,7 +1189,6 @@ async fn multi_agent_v2_spawn_returns_path_and_send_message_accepts_relative_pat
child_snapshot.session_source.get_agent_path().as_deref(),
Some("/root/test_process")
);
assert_eq!(child_snapshot.multi_agent_mode, MultiAgentMode::Proactive);
assert!(manager.captured_ops().iter().any(|(id, op)| {
*id == child_thread_id
&& matches!(
@@ -49,11 +49,6 @@ async fn handle_spawn_agent(
let arguments = function_arguments(payload)?;
let args: SpawnAgentArgs = parse_arguments(&arguments)?;
let fork_mode = args.fork_mode()?;
let multi_agent_mode = crate::session::multi_agents::effective_multi_agent_mode(
turn.multi_agent_version,
&turn.session_source,
turn.multi_agent_mode,
);
let role_name = args
.agent_type
.as_deref()
@@ -134,7 +129,6 @@ async fn handle_spawn_agent(
fork_mode,
parent_thread_id: Some(session.thread_id),
environments: Some(turn.environments.to_selections()),
initial_multi_agent_mode: multi_agent_mode,
},
),
)