feat: catalog multi-agent v2 config (#26254)

## Why

Model metadata can now select multi-agent v2 even when a user has not
enabled `features.multi_agent_v2` in their config. Some existing configs
still set the legacy `agents.max_threads` knob for v1 multi-agent
behavior, so treating every v2 runtime as incompatible with
`agents.max_threads` would break users whose only v2 signal came from
the model catalog.

The incompatible configuration is specifically enabling
`features.multi_agent_v2` while also setting `agents.max_threads`.
Catalog-forced v2 should use the v2 concurrency setting and ignore the
legacy v1 cap instead of rejecting the config.

## What changed

- Split config validation from runtime concurrency calculation:
`effective_agent_max_threads` now just returns the effective cap for the
resolved multi-agent runtime.
- Added explicit validation for `features.multi_agent_v2` +
`agents.max_threads` at session startup.
- Preserved catalog-selected v2 behavior when `features.multi_agent_v2`
is disabled, so existing configs with `agents.max_threads` keep
starting.
- Updated model-runtime selector coverage so a catalog v2 model still
exposes v2 tools even when `agents.max_threads` is set and the config
flag is disabled.

## Validation

- `cargo check -p codex-core --lib`
- `just test -p codex-core --lib -E
"test(multi_agent_v2_feature_rejects_agents_max_threads) |
test(catalog_v2_allows_agents_max_threads_when_feature_disabled)"`
This commit is contained in:
jif
2026-06-04 00:24:40 +02:00
committed by GitHub
Unverified
parent 2ca3810005
commit 11bceb8f8b
6 changed files with 62 additions and 36 deletions
+2 -5
View File
@@ -557,11 +557,8 @@ impl Codex {
.await;
let multi_agent_version =
resolve_multi_agent_version(&conversation_history, inherited_multi_agent_version);
let startup_multi_agent_version = multi_agent_version
.or(model_info.multi_agent_version)
.unwrap_or_else(|| config.multi_agent_version_from_features());
let _ = config
.effective_agent_max_threads(startup_multi_agent_version)
config
.validate_multi_agent_v2_config()
.map_err(|err| CodexErr::InvalidRequest(err.to_string()))?;
let base_instructions = config
.base_instructions