Codex app subagent cards can remain stuck/visible after close while close/readback reports no live agent

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

Summary

In the Codex app, completed or closed subagents can appear to remain visible/stuck in the UI for a long time even after the supported close/readback path reports that there is no live agent handle left.

Component

Codex app / Desktop on macOS.

I do not know the exact app version from the UI at the time of filing.

What happened

A workflow used several subagents for bounded helper work. After the helpers completed, attempts to close them by exact returned agent IDs produced a mix of:

  • a completed previous status,
  • a running or pending previous status followed by successful disappearance from readback,
  • or not_found for handles that were already gone from the live route.

Even after those close/readback results, the app UI could still make it look like subagents were present or stuck. In one child/subagent view, the UI showed a banner asking the parent to resume the sub-agent to continue the conversation, which suggests the child was closed, but the surrounding UI state still made it unclear whether a subagent was active, closed, or stale.

Expected behavior

After a subagent completes and is closed, the Codex app should make the lifecycle state unambiguous:

  • closed/completed subagent cards should update or disappear from active/open UI surfaces,
  • stale IDs should be shown as already closed rather than appearing stuck,
  • the parent thread should have a clear way to see that no live subagent remains,
  • and not_found after close/readback should not leave the user thinking an agent is still running or consuming an active slot.

Actual behavior

The live close/readback route can indicate that no live handle remains, while the UI still appears to show stale/open subagent state or a closed-child resume banner. This makes it hard to tell whether work is still running, whether slots are still occupied, or whether the UI is stale.

Impact

This is confusing during long-running work and makes it difficult to trust whether background/subagent work has actually stopped. It can lead to repeated close attempts and uncertainty about whether resources or subagent slots are still in use.

Request

Please clarify or fix the Codex app subagent lifecycle UI so the app reliably reflects completed/closed/stale states after subagent close/readback, especially when close returns not_found for an already-gone handle or when a child thread shows the parent-resume banner.

View original on GitHub ↗

12 Comments

github-actions[bot] contributor · 2 months ago

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

  • #23700
  • #23219
  • #22744
  • #23292

Powered by Codex Action

omarpinarecords · 2 months ago

Thanks. I reviewed the duplicate candidates from the bot.

This looks closest to #23700 and #23219, but I am leaving this issue open because it narrows the symptom to Codex Desktop/app UI lifecycle state: the live close/readback path no longer exposes a running subagent handle, while the app can still show stale/resumable subagent cards or stale open rows. #22744 and #23292 also look related on subagent status/rendering or parent-thread waiting behavior.

If maintainers prefer this tracked under #23700 instead, I can close this as a duplicate.

adpena contributor · 1 month ago

Additional datapoint from another current Desktop session:

  • Codex App: 26.519.41501 (3044)
  • Platform: Darwin 25.4.0 arm64 arm
  • Date observed: 2026-05-23
  • Symptom: the app right rail still showed named subagents plus “Show 67 more” after cleanup/close attempts, while the live close route no longer recognized several exact agent IDs as live handles.
  • Local readback/checkpoint state in the same workflow showed 0 live nonterminal agents after closeout; the stale rows were historical/terminal, not active work.

This makes the issue look less like a live subagent leak and more like a Desktop UI/cache/state propagation problem: closed or already-gone subagents remain rendered as if attached/active in the thread side panel. I am not attaching the screenshot because it includes workspace/thread details, but the visible UI symptom was the Subagents section still listing entries such as Rawls/Linnaeus/Kuhn/Ptolemy and “Show 67 more” after the lifecycle state was terminal.

omarpinarecords · 1 month ago

Additional public cross-link/update after checking the related stale UI / active-turn chain:

  • #24287 now has multiple public datapoints where Codex Desktop can show stale or frozen active-turn state while backend work appears to continue, including goal/multi-window and long-running-session observations.
  • This looks related to the same broader state/observability family as this issue: visible Desktop state can diverge from backend lifecycle state.
  • Related public chain already being tracked from this issue: #23700, #23219, #22744, #23292, #23937, #24281, #23296, #24287, and #24342.

I am keeping this issue open because the specific symptom here remains stale subagent UI/lifecycle rendering after close/readback shows no live agent. #24287 strengthens the adjacent Desktop state-desync signal, but it does not replace this exact subagent-card lifecycle report unless maintainers prefer a different canonical issue.

omarpinarecords · 1 month ago

Additional datapoint from today:

  • A subagent named Kuhn with role explorer was closed from the parent thread.
  • A later close attempt returned a pending_init previous-status style result.
  • The Codex Desktop Subagents panel still showed Kuhn (explorer) afterward.

This matches the stale subagent lifecycle/UI symptom tracked here: the user-facing panel can keep showing a subagent after the parent-side lifecycle action has already been taken.

omarpinarecords · 1 month ago

Additional datapoint from another current Codex Desktop session:

The Subagents panel showed multiple final-pass subagents still listed, including Pauli (final_synthesis_gate), Fermat (final_word_packet_auditor), final_counteruse_confidentiality_auditor, final_authority_source_force_auditor, final_service_procedure_auditor, and Banach (final_fact_pin_auditor).

This is the same stale subagent lifecycle/UI symptom: completed or closed helper agents remain visible in the Desktop Subagents panel, making it unclear which agents are still active versus stale UI entries.

omarpinarecords · 1 month ago

Additional datapoint from another current Codex Desktop session:

The Subagents panel showed a long list of final-pass subagents still visible, including Mill (final_synthesis_gate), Sartre (final_word_packet_auditor), Kuhn (final_fact_pin_auditor), Bernoulli (final_synthesis_gate), Euler (final_word_packet_auditor), Faraday (final_fact_pin_auditor), and truncated unnamed role entries for final_counteruse_confidentiality_auditor, final_authority_source_force_auditor, and final_service_procedure_auditor.

The panel also showed Show less, which means the stale/visible subagent list had expanded beyond the first visible group. This is another example of completed or stale helper agents remaining visible in the Desktop Subagents panel, making active versus stale state unclear.

omarpinarecords · 1 month ago

Additional root-cause clue from local state inspection:

  • The persisted thread_spawn_edges table had stale rows marked open for old subagent children even after the live close route no longer had a handle for those children.
  • For one affected parent session, close_agent changed one child edge from open to closed, while several sibling children still returned not found from the live close route and remained marked open in persisted state.
  • After changing the stale persisted rows to closed locally, the affected parent sessions showed zero open subagent edges in local state.

This supports the theory that the Desktop panel can render from persisted spawn-edge state that may not be reconciled when a child is already gone from the live close route.

omarpinarecords · 1 month ago

Additional confirmed datapoint after local repair and multiple app restarts:

The local Codex state database now shows all subagent spawn edges as closed:

  • SQLite integrity check: ok
  • thread_spawn_edges status count: closed=549, open=0
  • affected parent threads checked locally, with full identifiers intentionally omitted from this public comment
  • checker result: 0 open state spawn edges in the affected scope

Despite that, after restarting Codex Desktop multiple times, the Subagents panel still visually shows stale subagent cards.

This makes the remaining symptom look like Desktop UI/cache/rendering state surviving restart even when persisted lifecycle state reports no open edges, rather than an active subagent/lifecycle leak.

grnbtqdbyx-create · 1 month ago

I added a small evidence packer for this subagent lifecycle/state-reconciliation class in trace-to-skill@0.1.66:

npx trace-to-skill@0.1.66 demo subagent-lifecycle
npx trace-to-skill@0.1.66 codex-report ./runs --output openai-codex-subagents.md

Not a fix, just a report-shaping helper. It tries to make future reports include Codex version, OS/surface, model/workspace, root thread id, subagent ids/nicknames/roles, spawn/close/list actions, close_agent results, list_agents or /agents output, thread_spawn_edges status counts, registry/max_threads/quota evidence, recent-list/sidebar behavior, child archive/top-level state, last-progress/halt reason, MCP state, compaction/resume timing, restart/reload behavior, and whether stale agents are UI-only or still block spawns.

Release: https://github.com/grnbtqdbyx-create/trace-to-skill/releases/tag/v0.1.66

yaanfpv · 1 month ago

Adding a root cause from the source, since this reproduces deterministically across an app restart and the mechanism looks like a listing-filter gap rather than a problem with close_agent itself.

Repro

  1. Spawn a subagent and let it finish.
  2. close_agent it. It disappears from the Subagents panel.
  3. Quit and reopen the app. The closed subagent is back in the panel.

In state_N.sqlite after step 2 the child row is thread_spawn_edges.status = 'closed' but threads.archived = 0. Setting threads.archived = 1 for that exact child id by hand makes it stay gone across a restart, which points at where the listing reads.

Root cause, as I read it

  • close_agent (codex-rs/core/src/agent/control.rs) only calls set_thread_spawn_edge_status(child, Closed). It does not touch threads.archived.
  • The recent-thread listing that repopulates the panel runs through push_thread_filters (codex-rs/state/src/runtime/threads.rs), whose WHERE clause filters on threads.archived but not on thread_spawn_edges.status (nor thread_source). So a closed subagent (edge closed, archived = 0) still satisfies the listing and comes back on the rebuild.
  • The live agent-tree resume already filters spawn children on Open (resume_agent_from_rollout). So it is specifically the thread-listing path that does not know the subagent is closed.

On the fix direction
archived looks like the user-facing archive action (mark_archived / mark_unarchived, ThreadArchivedNotification, and the archive RPC cascades to subagent descendants), distinct from the subagent lifecycle that thread_spawn_edges.status tracks. So having close_agent set archived = 1 would make a lifecycle event perform a user archive and pull the thread out of history and search. Filtering the subagent listing on the spawn-edge status instead keeps the two separate, which also lines up with the direction in #25112. #25341 captures the same data-side mismatch.

Happy to help however is useful.

Environment: Codex Desktop on macOS, version 26.601.21317 (released Jun 3, 2026).

ehendrix23 · 20 days ago

Seen same issue. Feedback: 019f04ff-b2ce-7302-be1a-b511e0ee7cc1