Skip to content

bug: Collab subagents leak spawn slots, lack cascading cancellation, and wait is wait-any #13947

Closed

Description

@William17738

Summary

The collab multi-agent system has several lifecycle management issues that compound under real-world usage: completed agents permanently occupy spawn slots, parent cancellation doesn't propagate to children, and the wait tool only returns on the first agent completion rather than all.

Finding 1: Completed agents still occupy spawn slots

Files:

  • codex-rs/core/src/agent/control.rs:385-427 (completion watcher)
  • codex-rs/core/src/agent/guards.rs:68 (release_spawned_thread)

The maybe_start_completion_watcher() spawns a detached task that injects a <subagent_notification> into the parent when a child agent reaches a final status. However, it does not call release_spawned_thread(). The spawn slot remains occupied until the model explicitly calls close_agent → shutdown_agent() (control.rs:290-296).

Impact: With the default agent_max_threads=6, if the model spawns 6 agents that all complete but doesn't close them, all subsequent spawn_agent calls fail with AgentLimitReached.

Finding 2: spawn_agent can permanently leak a spawn slot

File: codex-rs/core/src/agent/control.rs:177-190

line 180:  reservation.commit()     // slot is now permanently reserved
line 187:  self.send_input(...)     // can fail
line 188:  self.maybe_start_completion_watcher(...)

commit() at line 180 sets SpawnReservation.active = false, disabling the RAII Drop cleanup. If send_input() at line 187 then fails for any reason other than InternalAgentDied, the slot is consumed forever:

  • The thread is registered in ThreadManagerState but may never complete.
  • No code path releases the slot.
  • The only recovery is global ThreadManager shutdown.

Finding 3: No cascading cancellation from parent to child

File: codex-rs/core/src/thread_manager.rs:366

When a parent session is interrupted or shut down, child agents are not automatically cancelled. Only ThreadManager::remove_and_close_all_threads() (the global shutdown path) cleans up all threads.

Impact: A parent agent that is interrupted mid-task leaves its children running, consuming API tokens and spawn slots, until the entire session ends.

Finding 4: wait implements wait-any, not wait-all

File: codex-rs/core/src/tools/handlers/multi_agents.rs:583-604

match timeout_at(deadline, futures.next()).await {
    Ok(Some((thread_id, status))) => {
        statuses.insert(thread_id, status);
        break;  // ← returns after FIRST completion
    }

The wait tool returns as soon as any one of the listed agents reaches a final status. It then drains other immediately-available results with now_or_never() (line 604), but fundamentally the model must call wait repeatedly to collect all results. Combined with MIN_WAIT_TIMEOUT_MS = 10_000 (line 41), waiting for N agents takes at minimum N × 10 seconds of wall time.

Finding 5: No per-agent execution timeout

File: codex-rs/core/src/tools/handlers/multi_agents.rs:102-108

spawn_agent accepts no max_runtime parameter. Collab agents can run indefinitely. By contrast, batch jobs have DEFAULT_AGENT_JOB_ITEM_TIMEOUT = 30 minutes (agent_jobs.rs:40) and reap_stale_active_items() for enforcement.

Suggested improvements

  1. Have the completion watcher call release_spawned_thread() when the child reaches a final status, or add a config option for auto-release.
  2. On send_input failure after commit(), explicitly release the slot.
  3. Propagate interrupt/shutdown from parent session to child agents.
  4. Add a wait_all mode or mode: "any" | "all" parameter to the wait tool.
  5. Add an optional max_runtime_ms parameter to spawn_agent.

I have a fix ready and can submit a PR if invited.

Activity

  1. added
    bugSomething isn't working
    CLIIssues related to the Codex CLI
    tool-callsIssues related to tool calling
    on Mar 8, 2026
  2. added
    agentIssues related to the core agent loop
    and removed
    CLIIssues related to the Codex CLI
    tool-callsIssues related to tool calling
    on Mar 8, 2026
  3. jif-oai commented on Mar 16, 2026

    @jif-oai
    Contributor

    Please, do not just post Codex analysis here...

    • Finding 1: this is on purpose. Completion != closed
    • Finding 2: this is wrong
    • Finding 3: this is on purpose. We don't want to enforce a parent-child link
    • Finding 4: this is not finding, just an observation. And this is by design
    • Finding 5: same thing, this is just an observation... and once again this is by design
  4. William17738 commented on Mar 17, 2026

    @William17738
    Author

    "Hi @jif-oai,just hit agent spawn failed again. No diagnostic info exposed - only see 'Agent spawn failed' with the task description. Can't even tell if it's slot exhaustion or something else.

  5. added
    subagentIssues involving subagents or multi-agent features
    and removed
    agentIssues related to the core agent loop
    on Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsubagentIssues involving subagents or multi-agent features

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions