Background subprocesses/subagents do not wake the calling agent on completion
What version of Codex CLI is running?
codex-cli 0.116.0
What subscription do you have?
API Key
Which model were you using?
gpt-5.3-codex medium
What platform is your computer?
Linux 6.8.0-101-generic x86_64 x86_64
What terminal emulator and version are you using (if applicable)?
tmux
What issue are you seeing?
Long-running background sub-processes and sub-agents do not inform the calling agent when they complete. Instead the calling agent must either:
- Block the message thread by continuously polling for a result; or
- Wait for the user to request an update
What steps can reproduce the bug?
In interactive mode, prompt the agent with:
Use `exec_command` to run the following script in a background terminal: `sleep 15; echo "print the whale emoji"`
or
Run a subagent in the background with the following prompt: `wait for 15 seconds then respond with the whale emoji"`
In both cases, the agent spins up the sub-task, responds to the user, and then does nothing after the sub-task returns.
What is the expected behavior?
Agents should be informed when long-running sub-processes return so they can take autonomous action.
Additional information
In other agent harnesses, watcher scripts can be used to automate agent actions. An agent can run a script in the background that polls an external endpoint without blocking the main interaction loop. When the script returns, the agent is able to respond autonomously without user intervention. Codex agents cannot implement this pattern because sub-processes do not appear to queue a message for the agent.
12 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Candidate fix pushed in my fork. Compare link: https://github.com/openai/codex/compare/main...JaysonGeng:codex:fix/auto-wake-on-async-completion
GitHub shows the branch as cleanly mergeable, but this repo is invitation-only for PRs from non-collaborators.
Root cause:
Patch summary:
Local validation: targeted unified-exec/subagent tests, just fmt, just fix -p codex-core, and git diff --check.
This should also cover #15461, #14314, and #14303.
I hit what looks like the same issue, and my logs make the boundary a bit clearer.
In my case, the child subagents did complete successfully. The important detail was:
task_completethread as a
<subagent_notification>So from the user side it looked like: the child finished and the parent technically received the result, but nothing visibly happened until I manually prompted the parent again
That makes this feel like more than “background work has no notification”. The completion did land, but the calling agent was not really resumed/woken in a user-visible way. I think the ideal agent UX is that the parent gets triggered to msg a response so i dont sit there going 'hey check again plz' over and over.
See also #13733 for the token cost angle
I hit this same class of long-run handoff problem from the user side: background work finishes or a window becomes usable again, but the selected user-facing session does not reliably move forward unless I manually poke it.
I built a small macOS userland bridge around this workflow for Claude/Codex, mainly to keep long runs observable and resumable: running / waiting for me / stuck are shown in the MacBook notch, and a selected session can receive a configured continuation prompt when it is ready to continue.
Not a core fix for this issue. I agree the proper solution is still a real wake/resume event in Codex, like the
trigger_turn = truedirection described above. Leaving it here as related prior art / workaround:https://github.com/tristan666666/agent-island
The wake should be runtime-owned, not model-discovered.
When a background process or subagent completes, the runtime can enqueue a completion receipt: origin id, parent turn id, exit status, output ref, finished_at, and whether it should trigger a new assistant turn. The model should consume that receipt only after something changed.
That keeps completion separate from polling. A child finishing should be able to wake the parent once, while a still-running child with no new output stays local and costs no extra model turn.
---
_Generated with ax._
@Necmttn agreed. The important distinction is "completion as data" vs "completion as a prompt to poll again".
A runtime-owned receipt also gives Codex a safer dedupe/recovery boundary. The parent should not need to rediscover child state by reading logs; it should receive one structured event with something like:
That also keeps token cost under control. A long-running child can stay invisible while nothing changes, then wake the parent exactly once when there is a terminal transition worth acting on.
+1
A completion-driven continuation needs a little more than a notification. Completion notifications should be delivered as durable, deduplicated session events and trigger exactly one continuation turn only when the owning session is idle. If the session is busy, defer and coalesce completion events until a safe turn boundary.
This avoids both polling and a burst of redundant model turns when several background processes or subagents finish close together. A receipt should at least preserve the origin ID, parent turn/session ID, terminal status, completion time, and a bounded result or output reference so delivery can be safely recovered after reconnect or resume.
Adding a Codex Desktop / ChatGPT integration perspective: I have encountered the same orchestration gap in multi-step, DAG-style workflows.
Sub-agent delegation itself works well, but if the parent agent finishes its turn or becomes idle while a child is still running, the child’s terminal event does not reliably resume the parent workflow. This affects successful completion, timeout, failure/exception, and abnormal termination. The child result may be available, but the next dependent step is not scheduled until the user sends another message.
For reliable multi-agent workflows, terminal child-task events should durably notify and, when appropriate, wake the owning parent/orchestrator so it can evaluate dependency/join conditions and continue without manual intervention. This should be idempotent to avoid duplicate downstream execution.
Claude Code’s event-driven background-task lifecycle handling is a useful UX reference here: completion, timeout, failure, and sub-agent events promptly return control to the coordinating agent. Comparable behavior in Codex would make long-running and DAG-based workflows much more reliable.
Consolidated PoC update for an explicit, one-shot subagent completion callback:
StatPan/codex:poc/multi-agent-v2-completion-callback-queue30ba5885ccopenai/codex:mainThe PoC adds a separate
register_completion_callbackfunction. It returns immediately; when the watched subagent reaches a terminal state, its existing bounded completion envelope is queued for the registering parent and the existing pending-work scheduler starts exactly one continuation once that parent is idle. This avoids both unconditional wake-up on every child completion and explicitwait_agentpolling.The public-path integration test covers:
A live TUI/service smoke test also completed that sequence without calling
wait_agent.Validation caught an important issue in the first draft: it modified the reserved
collaboration.wait_agentschema and the live API rejected the request with HTTP 400. That change was removed. The corrected branch preserves all reserved collaboration tool schemas and exposes callback registration as an ordinary function.Current scope is deliberately limited to the direct parent/subagent completion path. Registration is still in memory and does not survive restart/resume, so this is a behavior PoC rather than a production-ready durability design. No upstream PR has been opened.
Follow-up after implementing and live-testing the PoC: this supersedes the explicit
register_completion_callbackapproach described in my previous comment.The cleaner contract is runtime-owned completion delivery rather than asking the model to discover and call a separate registration tool:
write_stdinand the async watcher share a claim state so polling cannot race with, or duplicate, automatic delivery.For unified exec, the PoC uses an explicit
on_exit: wakepolicy. This keeps callbacks optional, while making the requested callback a runtime guarantee rather than a prompt to poll again.One important correctness case is ordinary POSIX background syntax. When the model honors a background-work request by emitting a normal
cmd &, the outer shell can exit before the actual job. Watching only the outer shell therefore loses the meaningful completion boundary and produces surprising behavior: a foreground long command wakes correctly, while the equivalent background command does not.The callback contract should therefore include the ordinary
&form that the model naturally uses:The validated sequence is:
The implementation detects the shell background operator syntactically, rather than using a string match, so
&&, quoted ampersands, redirections such as2>&1, and arithmetic expressions are not misclassified.This is not intended to supervise processes that the user explicitly fully detaches with mechanisms such as
nohup,disown, orsetsid; those need a different ownership contract. The scope here is the normal background syntax Codex itself is likely to generate while promising a completion callback.The direct subagent flow, unified-exec completion flow, and the raw POSIX
&flow all passed integration coverage and a live TUI test with nowait_agent/write_stdinpolling. Restart/resume durability is still outside this PoC, so I would stage an upstream implementation as runtime receipt/wake semantics first, unified-exec opt-in delivery second, and POSIX&lifecycle correctness as acceptance coverage for that exec contract.No upstream PR has been opened.