codex - 💡(How to fix) Fix Subagent child threads are counted as top-level recent conversations and can leave stale open spawn edges

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Subagent child threads appear to be persisted as normal threads and returned by the ordinary recent conversation listing. When many subagents have been used, those child threads consume the global recent-conversation slots, so older real parent/user conversations look like they have disappeared from the sidebar even though they are still present locally.

There also appears to be stale lifecycle metadata: some rows in thread_spawn_edges can remain open long after the corresponding subagent work appears inactive.

Root Cause

In the inspected state, 51 unarchived child threads inflated the recent-list population while the actual unarchived non-child conversation count was only 63. This interacts badly with recent-conversation pagination/capping and makes real conversations appear to disappear.

Code Example

select status, count(*)
from thread_spawn_edges
group by status;

select c.archived, count(*)
from thread_spawn_edges e
join threads c on c.id = e.child_thread_id
group by c.archived;

with child as (
  select child_thread_id from thread_spawn_edges
)
select 'unarchived_threads', count(*) from threads where archived = 0
union all
select 'subagent_children_unarchived', count(*) from threads where archived = 0 and id in child
union all
select 'normal_unarchived_excluding_subagent_children', count(*) from threads where archived = 0 and id not in child;
RAW_BUFFERClick to expand / collapse

Summary

Subagent child threads appear to be persisted as normal threads and returned by the ordinary recent conversation listing. When many subagents have been used, those child threads consume the global recent-conversation slots, so older real parent/user conversations look like they have disappeared from the sidebar even though they are still present locally.

There also appears to be stale lifecycle metadata: some rows in thread_spawn_edges can remain open long after the corresponding subagent work appears inactive.

Environment

  • Platform: Linux
  • Client: VS Code extension / desktop-style Codex UI
  • Local state DB inspected: ~/.codex/state_5.sqlite

Anonymized Local Evidence

From one local state DB:

  • Total threads: 553
  • Unarchived threads: 114
  • Subagent child threads linked by thread_spawn_edges: 61
  • Unarchived subagent child threads: 51
  • Unarchived non-child threads: 63
  • Parents with subagents: 14
  • thread_spawn_edges.status: 56 closed, 5 open
  • jobs, agent_jobs, and agent_job_items were empty
  • Process inspection did not show many active subagent workers, only the normal app-server process

No private thread titles, paths, or thread IDs are included here.

Queries Used

select status, count(*)
from thread_spawn_edges
group by status;

select c.archived, count(*)
from thread_spawn_edges e
join threads c on c.id = e.child_thread_id
group by c.archived;

with child as (
  select child_thread_id from thread_spawn_edges
)
select 'unarchived_threads', count(*) from threads where archived = 0
union all
select 'subagent_children_unarchived', count(*) from threads where archived = 0 and id in child
union all
select 'normal_unarchived_excluding_subagent_children', count(*) from threads where archived = 0 and id not in child;

Observed Behavior

  1. Use subagents over time so child threads are created.
  2. The child threads are stored in threads and linked from thread_spawn_edges.
  3. Many child threads remain archived = 0.
  4. The recent conversation list includes those child threads as ordinary top-level conversations.
  5. These child threads consume recent-list slots, making older parent/user conversations look missing from the sidebar.
  6. Some spawn edges remain open even when there is no obvious active agent job or worker process.

Expected Behavior

  • Subagent child threads should not be surfaced as top-level recent conversations by default, or should be grouped under the parent thread.
  • Subagent child threads should not consume the global recent-conversation page limit.
  • Completed/inactive subagent edges should reliably transition to closed, or stale open rows should be ignored/cleaned up.
  • Sidebar/search behavior should keep real parent/user conversations discoverable even when many subagents exist.

Why This Matters

In the inspected state, 51 unarchived child threads inflated the recent-list population while the actual unarchived non-child conversation count was only 63. This interacts badly with recent-conversation pagination/capping and makes real conversations appear to disappear.

Possibly Related Issues

  • #15368
  • #19197
  • #16817
  • #21128

This may be the connection between the recent-list cap and subagent lifecycle/state persistence: child subagent threads are counted as normal recent conversations, and some spawn edges remain stale-open.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix Subagent child threads are counted as top-level recent conversations and can leave stale open spawn edges