Simplify multi-agent mode controls (#29324)

## Why

Multi-agent delegation policy was split across `multiAgentMode`,
`features.multi_agent_mode`, and `usage_hint_enabled`. These controls
could disagree: a requested mode could be downgraded by the feature
flag, and disabling usage hints also disabled mode instructions.

Some clients also need multi-agent tools without adding
delegation-policy text to model context. The previous two-mode API could
not express that directly.

## What changed

`multiAgentMode` is now the only live delegation-policy control:

| Mode | Behavior |
| --- | --- |
| `none` | Keep multi-agent tools available without adding mode
instructions. |
| `explicitRequestOnly` | Only delegate after an explicit user request.
|
| `proactive` | Delegate when parallel work materially improves speed or
quality. |

- new threads default to `explicitRequestOnly`; omitting the mode on
later turns keeps the current value
- thread start, resume, fork, and settings responses always report the
concrete current mode instead of `null`
- mode selection remains sticky across turns and resume
- usage-hint text no longer controls whether mode instructions apply
- `features.multi_agent_mode` and `usage_hint_enabled` remain accepted
as ignored compatibility settings so existing configs continue to load
- app-server documentation and generated schemas describe the three-mode
API

## Tests

- `just test -p codex-core multi_agent_mode`
- `just test -p codex-core multi_agent_v2_config_from_feature_table`
- `just test -p codex-core spawn_agent_description`
- `just test -p codex-features`
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server multi_agent_mode`
This commit is contained in:
jif authored and GitHub committed 2026-06-22 10:05:36 +02:00
1 parent 6d15bb3d17
commit c03742ca0a
44 files changed
+253 -350

No files matched your search

-2
View File
@@ -10114,7 +10114,6 @@ max_concurrent_threads_per_session = 5
min_wait_timeout_ms = 2500
max_wait_timeout_ms = 120000
default_wait_timeout_ms = 30000
usage_hint_enabled = false
usage_hint_text = "Custom delegation guidance."
root_agent_usage_hint_text = "Root guidance."
subagent_usage_hint_text = "Subagent guidance."
@@ -10142,7 +10141,6 @@ non_code_mode_only = true
),
(None, Some(4))
);
assert!(!config.multi_agent_v2.usage_hint_enabled);
assert_eq!(
config.multi_agent_v2.usage_hint_text.as_deref(),
Some("Custom delegation guidance.")
-8
View File
@@ -241,8 +241,6 @@ You may also see them addressed as to=/root/..., which indicates your identity i
"#;
const DEFAULT_MULTI_AGENT_V2_SHARED_USAGE_HINT_TEXT: &str = r#"Note that collaboration tools cannot be called from inside `functions.exec`. Call `spawn_agent`, `send_message`, `followup_task`, `wait_agent`, `interrupt_agent`, and `list_agents` only as direct tool calls using the recipient shown in their tool definitions, such as `to=functions.spawn_agent` without a configured namespace or `to=functions.agents.spawn_agent` with `tool_namespace = "agents"`, since they are intentionally absent from the `functions.exec` `tools.*` namespace. Available tools in `functions.exec` are explicitly described with a `tools` namespace in the developer message.
The goal is to correctly solve the problem in as little time as possible. Therefore, if at any point you can parallelize work by delegating tasks to another agent, you should do so to save time.
All agents share the same directory. In detail:
- All agents have access to the same container and filesystem as you.
- All agents use the same current working directory.
@@ -1128,7 +1126,6 @@ pub struct MultiAgentV2Config {
pub min_wait_timeout_ms: i64,
pub max_wait_timeout_ms: i64,
pub default_wait_timeout_ms: i64,
pub usage_hint_enabled: bool,
pub usage_hint_text: Option<String>,
pub root_agent_usage_hint_text: Option<String>,
pub subagent_usage_hint_text: Option<String>,
@@ -1144,7 +1141,6 @@ impl MultiAgentV2Config {
min_wait_timeout_ms: DEFAULT_MULTI_AGENT_V2_MIN_WAIT_TIMEOUT_MS,
max_wait_timeout_ms: DEFAULT_MULTI_AGENT_V2_MAX_WAIT_TIMEOUT_MS,
default_wait_timeout_ms: DEFAULT_MULTI_AGENT_V2_DEFAULT_WAIT_TIMEOUT_MS,
usage_hint_enabled: true,
usage_hint_text: None,
root_agent_usage_hint_text: Some(default_multi_agent_v2_usage_hint_text(
DEFAULT_MULTI_AGENT_V2_ROOT_AGENT_USAGE_HINT_TEXT,
@@ -2492,9 +2488,6 @@ fn resolve_multi_agent_v2_config(config_toml: &ConfigToml) -> MultiAgentV2Config
let default_wait_timeout_ms = base
.and_then(|config| config.default_wait_timeout_ms)
.unwrap_or(default.default_wait_timeout_ms);
let usage_hint_enabled = base
.and_then(|config| config.usage_hint_enabled)
.unwrap_or(default.usage_hint_enabled);
let usage_hint_text = base
.and_then(|config| config.usage_hint_text.as_ref())
.cloned()
@@ -2523,7 +2516,6 @@ fn resolve_multi_agent_v2_config(config_toml: &ConfigToml) -> MultiAgentV2Config
min_wait_timeout_ms,
max_wait_timeout_ms,
default_wait_timeout_ms,
usage_hint_enabled,
usage_hint_text,
root_agent_usage_hint_text,
subagent_usage_hint_text,