Make subagents follow the root service tier (#41308)

## What changed

- Share the root thread's current service tier across its agent tree.
- Apply that tier to each subagent request when the selected child model supports it, including remote compaction requests.
- Propagate root service-tier updates to existing and newly spawned subagents without rewriting child-owned settings.
- Remove per-spawn and role-level service-tier overrides so routing remains controlled by the root thread.

## Testing

- Cover supported and unsupported child models, full-history forks, live tier changes, remote compaction, new subagents, and reloaded subagents.

GitOrigin-RevId: 6c299e224e90b41a558788fb7aa4d5f336fa383a
This commit is contained in:
jif authored and copyberry committed 2026-08-28 09:48:13 +00:00
1 parent 94311d4475
commit dc2ccc6843
19 files changed
+521 -274

No files matched your search

+28 -1
View File
@@ -1649,6 +1649,9 @@ impl Session {
previous_permission_profile != updated_permission_profile;
let mcp_inputs_changed =
self.mcp_inputs_differ(&state.session_configuration, &updated, &updates);
let root_service_tier_changed = updated.parent_thread_id.is_none()
&& state.session_configuration.step_settings.service_tier
!= updated.step_settings.service_tier;
if mcp_inputs_changed {
self.mark_mcp_runtime_dirty();
}
@@ -1665,6 +1668,15 @@ impl Session {
.update_thread_config(&environment_config);
}
state.session_configuration = updated;
if root_service_tier_changed {
self.services.agent_control.set_root_service_tier(
state
.session_configuration
.step_settings
.service_tier
.clone(),
);
}
let new_config = notify_config_contributors
.then(|| self.build_effective_session_config(&state.session_configuration));
let commit = SessionSettingsCommit {
@@ -3320,7 +3332,22 @@ impl Session {
) -> CodexResult<Arc<StepContext>> {
// Capture once before asynchronous planning; all request consumers
// retain this immutable settings version even if the turn is updated.
let settings = turn_context.current_settings.load_full();
let mut settings = turn_context.current_settings.load_full();
if matches!(
turn_context.session_source,
SessionSource::SubAgent(SubAgentSource::ThreadSpawn { .. })
) {
let root_service_tier = self.services.agent_control.root_service_tier();
if settings.selected().service_tier != root_service_tier {
let mut selected = settings.selected().clone();
selected.service_tier = root_service_tier;
settings = Arc::new(ResolvedStepSettings::new(
Arc::new(selected),
Arc::clone(&settings.model_info),
self.features.enabled(Feature::FastMode),
));
}
}
let token_budget = token_budget::resolve_token_budget(
turn_context.configured_token_budget.as_ref(),
turn_context.use_model_token_budget_defaults,
+9
View File
@@ -715,6 +715,15 @@ impl Session {
.parent_thread_id
.or_else(|| initial_history.get_resumed_parent_thread_id());
session_configuration.parent_thread_id = parent_thread_id;
if parent_thread_id.is_none() {
agent_control.set_root_service_tier(
session_configuration
.step_settings
.service_tier
.clone()
.or_else(|| config.service_tier.clone()),
);
}
let is_paginated_subagent = matches!(
session_configuration.history_mode,
ThreadHistoryMode::Paginated