MultiAgentV2: queue-only message to a completed agent pins a residency slot

Open 💬 0 comments Opened Jul 11, 2026 by zhibisora

What version of Codex CLI is running?

Observed with codex-cli 0.144.0 bundled in Conductor. I also checked codex-cli 0.144.1 and current main (5c19155cbd93bfa099016e7487259f61669823ff); the relevant v2 residency and message-delivery logic is unchanged.

What platform is your computer?

Darwin 25.5.0 arm64 arm

Surface: Codex app-server / MultiAgentV2, accessed through Conductor 0.74.0.

What issue are you seeing?

A completed MultiAgentV2 subagent can indefinitely occupy a resident thread slot when it has a pending queue-only mailbox message. Once the other resident slots are active, a new spawn_agent fails even though the number of actively running subagents is below the configured limit:

collab spawn failed: agent thread limit reached

This is not cumulative thread exhaustion. In the observed session, spawning succeeded again later after the pinned mailbox was consumed. The same AgentLimitReached error currently represents active concurrency exhaustion and residency exhaustion, so the parent cannot tell which condition occurred or which agent is blocking eviction.

What steps can reproduce the bug?

Use a small v2 capacity so the behavior is visible:

[features.multi_agent_v2]
max_concurrent_threads_per_session = 4

The value includes the root agent, leaving three subagent resident slots.

  1. Spawn subagent A and let it reach Completed.
  2. Call send_message targeting A. In v2 this is queue-only and does not trigger a new turn.
  3. Spawn subagents B and C with tasks that remain active.
  4. Attempt to spawn subagent D.
  5. D fails with collab spawn failed: agent thread limit reached, although only B and C are active.
  6. Call followup_task on A so it wakes, consumes its mailbox, and completes again. Retry the spawn; it can now succeed.

The production occurrence was the race-shaped variant: the root called send_message near A's completion boundary. A completed about one second later, leaving the queue-only message pending. With B and C active, spawning D failed.

What is the expected behavior?

A queue-only message should not leave a completed agent as a hidden, indefinitely non-evictable resident.

Any of these behaviors would avoid the deadlock:

  • reject send_message to an already completed agent and tell the caller to use followup_task;
  • automatically trigger a follow-up turn when a queue-only message crosses the target's completion boundary;
  • persist the mailbox independently so the completed thread can be unloaded and resumed later;
  • expose an explicit close/drain operation for completed v2 agents.

At minimum, AgentLimitReached should distinguish active concurrency from residency pressure and report data such as max, residents, active, and pending_mailbox_blockers with an actionable recovery hint.

Additional information

Current main makes the interaction explicit:

Related but distinct:

  • #22779 covers completed subagents continuing to count against the older/open-thread quota. This report is specifically about v2 residency, where ordinary completed agents are evictable but completed agents with pending queue-only mail are not.
  • #23479 requests capacity/status preflight; reporting mailbox blockers would address this failure mode.
  • #24508 requests safe cleanup of completed subagents, but v2 currently has no direct close tool in the exposed delegation toolset.

Increasing features.multi_agent_v2.max_concurrent_threads_per_session reduces the frequency but does not fix the pinned-mailbox lifecycle bug.

View original on GitHub ↗