agents.max_depth = 1 permits child-to-grandchild spawning in 0.144.1

Open 💬 3 comments Opened Jul 10, 2026 by EatMyTarts
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Codex version

Codex CLI 0.144.1, macOS arm64. This is the latest stable GitHub release as of 2026-07-10.

Configuration

[agents]
max_depth = 1
max_threads = 50

The configuration passes:

codex --strict-config --version

with:

codex-cli 0.144.1

There is no project-local Codex config overriding the user-level agents table.

Reproduction

  1. Start a fresh Codex task.
  2. Have the root thread spawn one direct child.
  3. Have that child make exactly one no-op subagent spawn attempt.
  4. Observe that the spawn succeeds and the grandchild runs.

Observed spawned path shape:

/root/explorer_depth_probe/noop

The grandchild returned only NOOP, so the probe made no repository or external changes.

Expected behavior

The official Subagents documentation says agents.max_depth defaults to 1, the root starts at depth 0, and max_depth = 1 lets the root spawn direct children while preventing those children from spawning deeper descendants:

https://developers.openai.com/codex/subagents

Actual behavior

A direct child successfully spawned a grandchild despite agents.max_depth = 1.

Additional verification

  • All custom agent TOMLs parse.
  • The user config contains exactly agents.max_depth = 1.
  • Codex strict config accepts the setting.
  • No custom agent file defines another agents table or overrides max_depth.
  • The no-op grandchild completed successfully, so this was not only a UI display artifact.

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #30692

Powered by Codex Action

adrianto-nanovest · 29 days ago

Still reproducible on 0.144.6, and I think I have the root cause. Short version: the depth check only exists in the V1 multi-agent handler, and the model catalog can silently put you on V2, which has no depth check at all.

Root cause

At tag rust-v0.144.6 (commit 5d1fbf26c43abc65a203928b2e31561cb039e06d):

core/src/tools/handlers/multi_agents/spawn.rs:64-71 — the V1 handler enforces:

let child_depth = next_thread_spawn_depth(&session_source);
let max_depth = turn.config.agent_max_depth;
if exceeds_thread_spawn_depth_limit(child_depth, max_depth) {
    return Err(FunctionCallError::RespondToModel(
        "Agent depth limit reached. Solve the task yourself.".to_string(),
    ));
}

core/src/tools/handlers/multi_agents_v2/spawn.rs — the V2 handler's complete set of depth references:

 4: use crate::agent::next_thread_spawn_depth;
61:     let child_depth = next_thread_spawn_depth(&session_source);
98:         child_depth,

It computes child_depth, records it into thread_spawn_source, and never calls exceeds_thread_spawn_depth_limit. So on V2, agents.max_depth is accepted, range-validated (agents.max_depth must be at least 1 fires for 0), and then has no effect. The depth is still recorded correctly, which is what makes this so easy to miss — thread_spawn_edges and each subagent's session_meta show depth: 1, 2, 3 faithfully while nothing enforces it.

Why you were on V2 without asking for it

codex features list reports multi_agent_v2 under development false, but the model catalog overrides that. codex debug models on 0.144.6:

gpt-5.6-sol    multi_agent_version: v2
gpt-5.6-terra  multi_agent_version: v2
gpt-5.6-luna   multi_agent_version: v1
gpt-5.5        multi_agent_version: null
gpt-5.4        multi_agent_version: null

Every turn of mine on the default gpt-5.6-sol recorded "multi_agent_version":"v2" in turn_context, despite the feature flag being false. This is the same mechanism reported in #31097.

Reproduction, both directions

codex exec, agents.max_depth=1 passed with --strict-config each time, chain verified from thread_spawn_edges rather than model self-report:

| Model | Runtime | Result |
|---|---|---|
| gpt-5.6-sol (default) | v2 | /root/c1/c2/c3 — depth 3 against max_depth=1 |
| gpt-5.6-luna | v1 | chain stops at depth 1 — correct |

Workaround, and a note on how V1 actually enforces

-m gpt-5.6-luna (or any model whose catalog multi_agent_version is v1) makes agents.max_depth work.

Worth noting for anyone debugging this: on V1 the enforcement is not the RespondToModel string above — it never appears. The collaboration tools are simply withheld from an agent at the depth limit. At max_depth=1 the depth-1 child's rollout contains zero occurrences of multi_agent_v1, send_input, close_agent, or resume_agent (vs 16/4/4/2 in the root's), and the child reports "No \spawn_agent\ tool is available.". At max_depth=3 that same child has the tools and reaches depth 2. That is arguably the better design — capability removal rather than asking the model to comply — so the fix here may be to give V2 the same treatment rather than to port the string check.

Suggested fix

Either add the depth guard to multi_agents_v2/spawn.rs, or (preferably) apply V1's tool-withholding to V2. Failing that, agents.max_depth should at minimum error at config load when the resolved runtime is V2, rather than accepting a setting it will ignore.

Environment: codex-cli 0.144.6, macOS arm64, codex exec, ~/.codex/config.toml sets no agents.* keys (all limits passed via -c).

darkkid0 · 27 days ago

Additional reproduction: Codex CLI 0.146.0 on Linux/WSL

I can reproduce the same failure on a current Linux/WSL installation, using the native collaboration tools (not a UI-only tree and not a nested codex exec process).

Environment:

  • Codex CLI: 0.146.0
  • Platform: WSL/Ubuntu
  • Root model: gpt-5.6-terra
  • Resolved collaboration runtime: multi_agent_version: "v2"
  • Configuration:

``toml
[agents]
max_depth = 1
``

A real run produced this sanitized tree:

root                                      depth 0
└── executor                              depth 1
    ├── independent-reviewer-a           depth 2
    └── independent-reviewer-b           depth 2

The corresponding session metadata contains source.subagent.thread_spawn.depth: 2 and records the depth-2 agents as native explorer subagents. The grandchildren completed successfully, so this is an actual dispatch result rather than a display artifact.

In the 0.146.0 binary/config description, agents.max_depth is marked (V1 only; ignored by V2), but the key is still accepted without a warning or configuration error while the resolved session is V2. This creates a particularly dangerous silent-failure mode: a user can verify that the setting parses and still receive a deeper tree than the declared limit.

Expected: with max_depth = 1, a depth-1 child must not be able to spawn a depth-2 descendant, or Codex should reject/warn that the setting is unsupported for the resolved V2 runtime and identify the supported replacement.

Actual: V2 accepts the setting, records depth 2, and allows the descendant to run.

This confirms that the issue remains present in 0.146.0 and is not limited to the original macOS/0.144.1 report. The GSD-side capability mismatch is tracked separately in open-gsd/gsd-core#2939.