Title: Windows Desktop: stale subagents remain Working and every child starts the full local stdio MCP suite

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

What version of the Codex App are you using (From “About Codex” dialog)?

Codex app package: OpenAI.Codex_26.803.5235.0_x64

What subscription do you have?

Three local stdio MCP servers configured globally:

What platform is your computer?

windows

What issue are you seeing?

Environment

Codex Desktop / ChatGPT Desktop on Windows

Codex app package: OpenAI.Codex_26.803.5235.0_x64

Three local stdio MCP servers configured globally:

MarkItDown

brain-memory

brain-knowledge

Summary

After using many subagents, completed child tasks remain permanently shown as Working in the Desktop subagent panel.

The parent agent reports that no subagents are active and that all work is complete. However, the Desktop UI still shows many children as Working, and local persisted state still records them as open.

This is not only a visual issue: the app-server keeps or recreates task-host and MCP processes.

Evidence

The subagent panel shows completed children as Working for more than one hour.

The active orchestration state has no active child agents; only the root task is active.

Local thread_spawn_edges state contains:

open = 160

closed = 5

After fully closing Codex, terminating the confirmed Codex MCP Python processes, and launching Codex again, the fresh app-server immediately created:

4 node_repl task hosts

24 Python processes

12 MarkItDown processes

8 brain-memory processes

4 brain-knowledge processes

This pattern indicates that each task host starts the full globally configured MCP suite, even for child tasks that do not use those tools.

Steps to reproduce

Configure several local stdio MCP servers globally.

Run a long-lived Codex Desktop session that launches many subagents.

Let the child tasks finish and return results.

Observe that some children remain Working in the subagent panel.

Ask the parent to stop or close completed subagents. It may report that no active agents exist.

Inspect local process tree and persisted subagent state.

Restart Codex and observe that task-host/MCP processes are recreated.

Expected behavior

A child agent that has returned its final result should transition to Done/Closed.

Its persisted lifecycle state should also be closed.

MCP processes created solely for that child should be terminated when the child closes.

A child agent should be able to use an explicit, minimal MCP allowlist instead of inheriting every heavy global stdio MCP server.

Desktop restart should not restore completed children as active or Working.

Impact

This makes subagent-heavy workflows unreliable on Windows Desktop:

memory usage grows rapidly;

many unnecessary local MCP processes are created;

the subagent panel becomes inaccurate;

stale children may appear to remain active after completion;

restarting the app does not clear the underlying stale state.

I can provide redacted process-tree output, screenshots, and timestamps if useful.

What steps can reproduce the bug?

Environment

Codex Desktop / ChatGPT Desktop on Windows

Codex app package: OpenAI.Codex_26.803.5235.0_x64

Three local stdio MCP servers configured globally:

MarkItDown

brain-memory

brain-knowledge

Summary

After using many subagents, completed child tasks remain permanently shown as Working in the Desktop subagent panel.

The parent agent reports that no subagents are active and that all work is complete. However, the Desktop UI still shows many children as Working, and local persisted state still records them as open.

This is not only a visual issue: the app-server keeps or recreates task-host and MCP processes.

Evidence

The subagent panel shows completed children as Working for more than one hour.

The active orchestration state has no active child agents; only the root task is active.

Local thread_spawn_edges state contains:

open = 160

closed = 5

After fully closing Codex, terminating the confirmed Codex MCP Python processes, and launching Codex again, the fresh app-server immediately created:

4 node_repl task hosts

24 Python processes

12 MarkItDown processes

8 brain-memory processes

4 brain-knowledge processes

This pattern indicates that each task host starts the full globally configured MCP suite, even for child tasks that do not use those tools.

Steps to reproduce

Configure several local stdio MCP servers globally.

Run a long-lived Codex Desktop session that launches many subagents.

Let the child tasks finish and return results.

Observe that some children remain Working in the subagent panel.

Ask the parent to stop or close completed subagents. It may report that no active agents exist.

Inspect local process tree and persisted subagent state.

Restart Codex and observe that task-host/MCP processes are recreated.

Expected behavior

A child agent that has returned its final result should transition to Done/Closed.

Its persisted lifecycle state should also be closed.

MCP processes created solely for that child should be terminated when the child closes.

A child agent should be able to use an explicit, minimal MCP allowlist instead of inheriting every heavy global stdio MCP server.

Desktop restart should not restore completed children as active or Working.

Impact

This makes subagent-heavy workflows unreliable on Windows Desktop:

memory usage grows rapidly;

many unnecessary local MCP processes are created;

the subagent panel becomes inaccurate;

stale children may appear to remain active after completion;

restarting the app does not clear the underlying stale state.

I can provide redacted process-tree output, screenshots, and timestamps if useful.

What is the expected behavior?

Environment

Codex Desktop / ChatGPT Desktop on Windows

Codex app package: OpenAI.Codex_26.803.5235.0_x64

Three local stdio MCP servers configured globally:

MarkItDown

brain-memory

brain-knowledge

Summary

After using many subagents, completed child tasks remain permanently shown as Working in the Desktop subagent panel.

The parent agent reports that no subagents are active and that all work is complete. However, the Desktop UI still shows many children as Working, and local persisted state still records them as open.

This is not only a visual issue: the app-server keeps or recreates task-host and MCP processes.

Evidence

The subagent panel shows completed children as Working for more than one hour.

The active orchestration state has no active child agents; only the root task is active.

Local thread_spawn_edges state contains:

open = 160

closed = 5

After fully closing Codex, terminating the confirmed Codex MCP Python processes, and launching Codex again, the fresh app-server immediately created:

4 node_repl task hosts

24 Python processes

12 MarkItDown processes

8 brain-memory processes

4 brain-knowledge processes

This pattern indicates that each task host starts the full globally configured MCP suite, even for child tasks that do not use those tools.

Steps to reproduce

Configure several local stdio MCP servers globally.

Run a long-lived Codex Desktop session that launches many subagents.

Let the child tasks finish and return results.

Observe that some children remain Working in the subagent panel.

Ask the parent to stop or close completed subagents. It may report that no active agents exist.

Inspect local process tree and persisted subagent state.

Restart Codex and observe that task-host/MCP processes are recreated.

Expected behavior

A child agent that has returned its final result should transition to Done/Closed.

Its persisted lifecycle state should also be closed.

MCP processes created solely for that child should be terminated when the child closes.

A child agent should be able to use an explicit, minimal MCP allowlist instead of inheriting every heavy global stdio MCP server.

Desktop restart should not restore completed children as active or Working.

Impact

This makes subagent-heavy workflows unreliable on Windows Desktop:

memory usage grows rapidly;

many unnecessary local MCP processes are created;

the subagent panel becomes inaccurate;

stale children may appear to remain active after completion;

restarting the app does not clear the underlying stale state.

I can provide redacted process-tree output, screenshots, and timestamps if useful.

Additional information

_No response_

View original on GitHub ↗

5 Comments

github-actions[bot] contributor · 21 days ago

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

  • #37299
  • #37222
  • #37042
  • #37041

Powered by Codex Action

leadingproblemsolver · 20 days ago

The open = 160 / closed = 5 split is useful because it suggests the durable edge table is being treated as authority when it should probably be a projection of lifecycle events plus live reconciliation.

I would separate three states that are currently easy to collapse:

execution_state   = running | returned | failed | cancelled
resource_state    = allocated | releasing | released
ui_state          = active | historical | stale

A child returning its final result should emit an immutable lifecycle event such as:

agent_id
parent_id
attempt_id
transition = returned
observed_at
source_runtime_id
final_turn_id
result_ref

Then cleanup emits a separate resource-release event. The thread_spawn_edges.open flag and Desktop "Working" badge become derived views, not independently mutable truths.

On startup/resume, run a bounded reconciliation pass:

  1. Rebuild each child's latest execution/resource state from the event stream.
  2. Compare that with live task-host/process ownership.
  3. If persisted state says running but no owning runtime/process/lease exists, mark it stale and do not recreate child resources automatically.
  4. Only restart/recreate a child when there is an explicit resumable-work record, not merely an old open edge.
  5. Render stale historical children distinctly from live work.

That last distinction also helps the MCP amplification problem. MCP ownership should attach to the child attempt/resource lease, so resource_state=released gives a deterministic teardown boundary. On restart, a historical child cannot accidentally become a reason to instantiate its full inherited MCP suite.

A useful invariant would be:

persisted lifecycle metadata may request reconciliation, but only current ownership evidence can establish running.

I have been working on the same general evidence-vs-projection boundary in a local-first operational-memory compiler: source observations are retained and human-facing state is derived/reconciled rather than treated as self-authenticating truth: https://github.com/leadingproblemsolver/living-context-engine

LCE is not an agent lifecycle manager, but this issue is a strong example of why derived state (open, Working) needs provenance and a reconciliation rule instead of becoming permanent authority.

MarkoAvreliy · 20 days ago

Additional confirmed reproduction:

A clean Codex Desktop launch starts with one MCP/node_repl stack.

Opening one historical parent chat with 51 stale subagents, without sending a message, causes thread/resume and creates additional full MCP stacks.

Opening old child threads changes their UI state from Working to Done and triggers further thread/resume calls.

Observed after one parent-chat load and inspection of a few children:

  • 8 node_repl.exe direct children
  • 8 MarkItDown MCP wrappers
  • 8 brain-memory MCP wrappers
  • 8 brain-knowledge MCP wrappers
  • 48 Python processes in the Codex process tree

Codex logs correlate the launches with app_server thread/resume requests and MCP tool catalog initialization.

This is reproducible without launching a new task, a new subagent, or an MCP tool call.

MarkoAvreliy · 19 days ago

Follow-up: local mitigation, validation, and architectural request

This is not a UI-only annoyance in my workflow.

I reproduced the historical-hydration path where completed children can be presented as Working again and local tool/runtime activity can be re-materialized without any new user message. My earlier per-child stdio MCP topology amplified the process symptom, but it was not the root cause.

Investigation cost

Approximate workflow telemetry for diagnosis, reproduction, patching, and validation:

  • 10h 51m active investigation;
  • 7.36M internal agent-processing tokens.

These are not exact billed API tokens or exact ChatGPT subscription-quota consumption; that cannot be reconstructed client-side. However, the incident materially affected productivity and forced a subscription-tier increase during the investigation period.

Practical comparison

I moved from Claude Code expecting comparable multi-agent capability with a more economical workflow. In my day-to-day Claude Code workflow, bounded subagent orchestration had been predictable and practical.

In Codex Desktop, the equivalent workflow became operationally unsafe: reopening historical chats could restore stale child state and create uncertainty about whether completed work had truly stopped. This is my field experience, not a universal benchmark claim, but it is a major regression for a user relying on many small workers.

Experimental local mitigation

I published a sanitized, reproducible checkpoint:

It does not disable MCP, browser control, computer use, Node tools, or subagents. Instead it keeps lifecycle boundaries intact:

  • historical display does not start MCP/tool runtime;
  • completed child status is restored without loading its runtime;
  • completed V2 child runtimes unload through the normal shutdown path;
  • stale legacy child edges are repaired without eagerly resuming the child;
  • tools still start normally for a real new foreground action.

Validation: 4 lifecycle tests and 3 lazy-resume MCP integration tests passed. Opening four historical parent chats with completed children produced 0 new Python, 0 new Node, and 0 new node_repl processes, and no history-triggered MCP, child-spawn/resume, or model-transport references.

This is an experimental local mitigation, not an official OpenAI fix or distributable Codex build.

IMPORTANT FOR CODEX USERS AND MAINTAINERS

HISTORICAL CHAT VIEWING MUST BE PASSIVE. A COMPLETED CHILD MUST NOT BE RESTORED AS A RUNNABLE RUNTIME JUST BECAUSE ITS PARENT CHAT WAS OPENED.

DEFAULT CHILDREN SHOULD BE LIGHTWEIGHT AND DENY-BY-DEFAULT FOR MCP SERVERS, PLUGINS, SKILLS, AND OTHER HEAVY TOOLING.

The orchestrator can retain its full toolset. Ordinary child workers should start with a minimal profile and bounded context; a specific MCP or plugin should be enabled only for the specialized child that actually needs it.

Suggested model:

  • orchestrator -> required full toolset;
  • general research / coding / QA child -> no heavy MCP by default;
  • document child -> only document MCP;
  • memory child -> only memory MCP;
  • knowledge child -> only knowledge MCP;
  • browser/computer child -> only the relevant capability.

If every child inherits the parent’s full tool surface and history by default, it creates an amplification risk: unnecessary process churn, configuration conflicts, avoidable context overhead, and potentially unnecessary agent/model usage.

Codex needs first-class lifecycle isolation and a safe lightweight-child default, while preserving deliberate opt-in to specialist tools.

Sythos · 14 days ago

Just asking but, isn't this issue a duplicate of the following?

#37042
#37041