Add configurable agent spawn depth (#12251)

Summary
- expose `agents.max_depth` in config schema and toml parsing, with
defaults and validation
- thread-spawn depth guards and multi-agent handler now respect the
configured limit instead of a hardcoded value
- ensure documentation and helpers account for agent depth limits
This commit is contained in:
jif-oai
2026-02-19 18:40:41 +00:00
committed by GitHub
parent d54999d006
commit d87cf7794c
6 changed files with 86 additions and 16 deletions

View File

@@ -111,6 +111,7 @@ pub use codex_git::GhostSnapshotConfig;
/// the context window.
pub(crate) const PROJECT_DOC_MAX_BYTES: usize = 32 * 1024; // 32 KiB
pub(crate) const DEFAULT_AGENT_MAX_THREADS: Option<usize> = Some(6);
pub(crate) const DEFAULT_AGENT_MAX_DEPTH: i32 = 1;
pub const CONFIG_TOML_FILE: &str = "config.toml";
@@ -309,6 +310,9 @@ pub struct Config {
/// Maximum number of agent threads that can be open concurrently.
pub agent_max_threads: Option<usize>,
/// Maximum nesting depth allowed for spawned agent threads.
pub agent_max_depth: i32,
/// User-defined role declarations keyed by role name.
pub agent_roles: BTreeMap<String, AgentRoleConfig>,
@@ -1217,6 +1221,11 @@ pub struct AgentsToml {
#[schemars(range(min = 1))]
pub max_threads: Option<usize>,
/// Maximum nesting depth allowed for spawned agent threads.
/// Root sessions start at depth 0.
#[schemars(range(min = 1))]
pub max_depth: Option<i32>,
/// User-defined role declarations keyed by role name.
///
/// Example:
@@ -1692,6 +1701,17 @@ impl Config {
"agents.max_threads must be at least 1",
));
}
let agent_max_depth = cfg
.agents
.as_ref()
.and_then(|agents| agents.max_depth)
.unwrap_or(DEFAULT_AGENT_MAX_DEPTH);
if agent_max_depth < 1 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"agents.max_depth must be at least 1",
));
}
let agent_roles = cfg
.agents
.as_ref()
@@ -1934,6 +1954,7 @@ impl Config {
.collect(),
tool_output_token_limit: cfg.tool_output_token_limit,
agent_max_threads,
agent_max_depth,
agent_roles,
memories: cfg.memories.unwrap_or_default().into(),
codex_home,
@@ -4148,6 +4169,7 @@ model = "gpt-5.1-codex"
let cfg = ConfigToml {
agents: Some(AgentsToml {
max_threads: None,
max_depth: None,
roles: BTreeMap::from([(
"researcher".to_string(),
AgentRoleToml {
@@ -4390,6 +4412,7 @@ model_verbosity = "high"
project_doc_fallback_filenames: Vec::new(),
tool_output_token_limit: None,
agent_max_threads: DEFAULT_AGENT_MAX_THREADS,
agent_max_depth: DEFAULT_AGENT_MAX_DEPTH,
agent_roles: BTreeMap::new(),
memories: MemoriesConfig::default(),
codex_home: fixture.codex_home(),
@@ -4506,6 +4529,7 @@ model_verbosity = "high"
project_doc_fallback_filenames: Vec::new(),
tool_output_token_limit: None,
agent_max_threads: DEFAULT_AGENT_MAX_THREADS,
agent_max_depth: DEFAULT_AGENT_MAX_DEPTH,
agent_roles: BTreeMap::new(),
memories: MemoriesConfig::default(),
codex_home: fixture.codex_home(),
@@ -4620,6 +4644,7 @@ model_verbosity = "high"
project_doc_fallback_filenames: Vec::new(),
tool_output_token_limit: None,
agent_max_threads: DEFAULT_AGENT_MAX_THREADS,
agent_max_depth: DEFAULT_AGENT_MAX_DEPTH,
agent_roles: BTreeMap::new(),
memories: MemoriesConfig::default(),
codex_home: fixture.codex_home(),
@@ -4720,6 +4745,7 @@ model_verbosity = "high"
project_doc_fallback_filenames: Vec::new(),
tool_output_token_limit: None,
agent_max_threads: DEFAULT_AGENT_MAX_THREADS,
agent_max_depth: DEFAULT_AGENT_MAX_DEPTH,
agent_roles: BTreeMap::new(),
memories: MemoriesConfig::default(),
codex_home: fixture.codex_home(),