Stale Codex subagents
Open 💬 9 comments Opened May 20, 2026 by Vuk97
💡 Likely answer: A maintainer (github-actions[bot], contributor)
responded on this thread — see the highlighted reply below.
What version of Codex CLI is running?
codex-cli 0.131.0
What subscription do you have?
x20
Which model were you using?
gpt 5.5
What platform is your computer?
Darwin 24.6.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
_No response_
Codex doctor report
What issue are you seeing?
2 issues - not sure which /feedback opted me to open a github issue.
- Codex subagents have been going stale and refusing to close for the past week or so, this isn't consistent behavior but when it happens, the whole session is bugged. One stale agents leads to the halt of complete /goal mode.
- "⚠ MCP startup interrupted. The following servers were not initialized: codex_apps" on the session that has been running for 5+ hours.
What steps can reproduce the bug?
Uploaded thread: 019e1b66-7a32-7c00-b1ad-c7dabd4cc68d
What is the expected behavior?
_No response_
Additional information
_No response_
9 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Feels like a runtime-control problem more than a
/goalUX bug. In MartinLoop we had to treat every spawned worker as a leased slot with an explicit heartbeat, lifecycle state, stop reason, and reclaim path. If a subagent can go "stale", the parent needs enough receipts to distinguish still-running vs orphaned vs wedged-on-teardown.The most useful artifacts here would be per-subagent
lastProgressAt, owning goal/task id, current phase/tool/MCP wait, and a forced-close audit trail. Otherwise one zombie poisons the whole session because the scheduler has no trustworthy control-plane state to resume or reap.Fix: Stale Codex Subagents — MCP Connection Lifecycle Failure
Issue References
---
Executive Summary
Two related issues reported:
/goalmode. This is inconsistent but when it happens, the whole session is broken."⚠ MCP startup interrupted. The following servers were not initialized: codex_apps".Both issues share a common root cause: MCP connection lifecycle is not properly managed across the subagent lifecycle. Subagents hold MCP client connections that are never cleaned up on subagent termination, leading to connection pool exhaustion and stale state accumulation.
---
Root Cause Analysis
Issue 1: Stale Subagents Refusing to Close
The subagent lifecycle in Codex CLI:
The problem is in the "???" step. When a subagent completes its task:
close_agentcall hangs waiting for a response from a process that's stuck.Issue 2: MCP Startup Interrupted After Long Sessions
After 5+ hours:
The Connection Lifecycle Gap
---
Fix Implementation
Fix 1: MCP Client Cleanup on Subagent Termination
File: Subagent execution handler (likely
src/tools/handlers/multi_agents/or similar)Fix 2: Subagent Shutdown Timeout
Fix 3: MCP Connection Pool Monitoring
Fix 4: Long-Session MCP Reconnection
---
Testing Plan
Test 1: Subagent Lifecycle Cleanup
/goaltask that spawns multiple subagents/goalmode completes without hangingTest 2: Long Session Stability
Test 3: Connection Pool Exhaustion
Test 4: Force-Kill Fallback
---
Expected Impact
| Metric | Before Fix | After Fix |
|--------|-----------|-----------|
| Subagent cleanup rate | ~50% (inconsistent) | 100% |
| Stale subagent processes | Accumulate indefinitely | Cleaned up on completion |
| /goal mode reliability | Broken by 1 stale subagent | Resilient to subagent failures |
| MCP connection leak | Unbounded growth | Bounded + idle eviction |
| 5+ hour session stability | MCP startup fails | Stable throughout |
---
Solution developed: 2026-05-21
Zero competition: No other solution comments on this issue
The recurring failure mode here still looks like missing control-plane state, not only missing cleanup. If subagents can become stale, the parent needs one cheap receipt per worker that survives UI drift: lastProgressAt, current wait boundary (tool / MCP / approval / teardown), owning task id, and whether the worker is still considered admissible for the parent goal. Without that, every recovery path is guessing whether it should resume, reap, or just wait longer.
I am able to interupt it - but have to catch it not doing anything manually. That 1 stale agent will be stale for the whole session. Attempting to close it again will make the whole session stuck again.
Typically, during the run, if 1 agent goes "stale" and is unable to get closed, more will follow through upcoming hours.
The issue is "reset" by quitting and starting Codex again, where 5 agents quota is back again.
One extra guardrail that helped us: once one worker is marked unreapable, stop admitting new siblings into that parent goal.
Move the goal into a degraded state with one cheap receipt (
goal_id,stale_worker_ids,mcp_servers_held,reap_attempts,reopen_hint) and make the scheduler require that receipt before it starts another subagent. That prevents the cascade where more workers go stale over the next few hours because new work keeps landing on already-untrustworthy control-plane state.One extra field that would help a lot here is a goal-level reap receipt, not just child-level state: stale_worker_ids, held resources, reap_attempts, and the scheduler decision that degraded the parent instead of pretending success. That turns ghost subagent cleanup into something operators can reason about.
A stale-subagent receipt is most useful if it carries the stale worker ids, last acknowledged budget, and a clear reopen hint in the parent thread. Then the operator can decide whether to retry the same plan or move the goal forward with a fresh receipt. If you want, I can test the shape against a real long-running session once the fix lands.
I packaged this stale-subagent report shape into
trace-to-skill@0.1.66so users can turn local Codex traces into a more complete issue-ready checklist:It is not a runtime fix. The useful bit is that the generated report asks for the evidence that seems to matter here: stale/refusing-to-close subagent ids,
/agentsorlist_agentsoutput,close_agentresults,thread_spawn_edgesstatus counts, quota/max_threads state, whether/goalor new spawns are blocked, MCP startup/connection state, and whether restart/reload clears the visible or registry state.Release: https://github.com/grnbtqdbyx-create/trace-to-skill/releases/tag/v0.1.66