TUI /agent accumulates ghost subagent threads; stale entries open blank while API returns 'agent not found'

Resolved 💬 3 comments Opened Mar 28, 2026 by palvaleri Closed Mar 29, 2026

Summary

After upgrading to codex-cli 0.117.0, persistent subagent/collab workflows can accumulate ghost thread entries in /agent.

The broken behavior has two visible symptoms at the same time:

  1. /agent shows many historical subagent threads instead of only the currently live ones.
  2. Some of those entries open as blank/empty threads with no transcript, while the tool/API layer already treats the same thread ids as dead (agent with id ... not found).

This makes it hard to tell which subagent threads are actually alive, and long-running orchestrated workflows start to degrade because the UI/thread list diverges from live thread state.

Possibly related, but not identical, to:

  • #14162
  • #15306

Environment

  • Codex: codex-cli 0.117.0
  • Platform: macOS 15.7.4 (Darwin 24.6.0, arm64)
  • Auth: ChatGPT account via normal local Codex auth
  • Workflow: TUI collab / persistent subagent threads (/agent, spawn_agent, send_input, wait_agent)

What I’m seeing

In a persistent collab/orchestrator workflow, old subagent handles become invalid after restart/resume or after enough respawn churn. That part is survivable because the orchestrator can respawn them.

The problem is that the /agent UI keeps showing many stale historical threads anyway. Some of those stale entries open as blank threads with no visible content. Meanwhile the tool layer already returns errors such as:

  • agent with id 019d25da-1d65-7621-b753-6adf4fc7b52f not found
  • agent with id 019d25e8-a744-7331-9e73-c303db8c0c31 not found
  • agent with id 019d25f6-7cc2-7f70-ad91-b331b1645c6b not found
  • agent with id 019d2604-c1a3-7020-9398-3d371cd16e74 not found

So there is a state split:

  • UI/thread picker still surfaces the dead entries
  • API/tool layer already considers them gone
  • opening some of those entries gives an empty/blank thread view instead of a clear stale-thread error or automatic pruning

Repro sketch

I do not have a tiny standalone repro yet, but this reproduces reliably in a long-running collab setup:

  1. Start a persistent multi-subagent workflow in TUI.
  2. Reuse the same subagent roles across multiple cycles (send_input + wait_agent).
  3. Restart/reattach the TUI at least once, or continue long enough that some stored handles become invalid and need respawn.
  4. Let the orchestrator respawn stale threads when it gets agent ... not found.
  5. Open /agent.

Observed result:

  • /agent now contains many historical/stale thread entries.
  • some of them open as blank/empty threads.
  • only a subset correspond to actually live handles.

Expected behavior

Any of these would be acceptable, but the current split-brain state is not:

  1. /agent should only show live/rehydratable threads.
  2. If a thread id is already dead, the UI should mark it stale or remove it automatically.
  3. Opening a stale entry should show an explicit stale-thread error, not a blank thread.
  4. Respawning a role thread should not leave ghost entries that look selectable but are not backed by a live thread.

Local evidence

During cleanup/reset, I had to close current live threads and recreate only four fresh ones. After cleanup, the live handles were:

  • architect: 019d340b-7a50-7481-a6d0-1450441bd84c
  • planner: 019d340c-b77d-79f2-b6a5-25868eeb8112
  • coder: 019d340d-a216-7190-a0a4-cefe6697a779
  • reviewer: 019d340e-9969-7d30-b27b-f2259475c0f1

Recent local audit log excerpts still show the churn that preceded the ghost entries:

architect:
28.03.2026 10:22:39  019d3351-78d9-7062-90b5-a47c8699d646  respawn
28.03.2026 12:10:23  019d33b4-8150-7842-a1d8-9f2ea9b8fdec  respawn
28.03.2026 13:45:37  019d340b-7a50-7481-a6d0-1450441bd84c  respawn  cleanup_reset

planner:
28.03.2026 10:36:59  019d335e-b8ef-7c51-8559-2942c757175d  respawn
28.03.2026 13:18:48  019d33f2-5dd3-7121-87fb-7b50cdefb8d7  respawn
28.03.2026 13:46:36  019d340c-b77d-79f2-b6a5-25868eeb8112  respawn  cleanup_reset

coder:
28.03.2026 10:51:01  019d336b-ebe4-7001-b397-78bd522d679f  respawn
28.03.2026 11:41:05  019d3399-b60a-7db0-a453-4f0feb98f987  respawn
28.03.2026 13:47:41  019d340d-a216-7190-a0a4-cefe6697a779  respawn  cleanup_reset

reviewer:
28.03.2026 10:17:58  019d2604-c1a3-7020-9398-3d371cd16e74  respawn
28.03.2026 11:50:54  019d33a2-f32b-7e81-b302-fc7957c986b8  respawn
28.03.2026 13:49:25  019d340e-9969-7d30-b27b-f2259475c0f1  respawn  cleanup_reset

Why this matters

This is not just cosmetic. In a long-running orchestration flow, the operator cannot trust /agent anymore:

  • some visible threads are dead
  • some dead threads open blank
  • the live set is smaller than what the UI suggests
  • cleanup becomes guesswork

If needed, I can add a screenshot of the /agent list showing the ghost entries and the blank thread behavior.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗