What version of the Codex App are you using (From “About Codex” dialog)?
Codex App 26.810.41047, build 6570. The associated rollout metadata reports Codex 0.148.0-alpha.9
The source checkout used for the analysis exactly matched upstream main at 2ca575026cef066a58c70f6bdee4feafa6e63d3a
What subscription do you have?
ChatGPT paid plan. The exact tier is omitted from this public report because the failure is a local capability-boundary issue and does not appear plan-dependent
What platform is your computer?
Darwin 25.5.0 arm64 arm, macOS 26.5.1 build 25F80
What issue are you seeing?
A real multi-agent child, after a third-party OMO/LazyCodex SubagentStop continuation hook incorrectly promoted the completed worker into the root plan orchestrator, used inherited Codex App dynamic tools to create two independent, user-owned Desktop tasks
The user had requested ordinary plan execution through subagents, not separate Desktop tasks. The OMO hook explains why the child attempted further delegation; it does not supply explicit user authorization to create user-owned tasks
The source conversation was a normal depth-1 SessionSource::SubAgent(ThreadSpawn) child with an incoming spawn edge and a parent thread. Its persisted SessionMeta.dynamic_tools nevertheless contained the complete codex_app namespace, including:
create_thread
fork_thread
handoff_thread
send_message_to_thread
set_thread_archived
set_thread_pinned
set_thread_title
- the thread listing, reading, waiting, navigation, automation, and project functions
The tool description for create_thread correctly says: Create a separate task only when the user explicitly asks for a new task. However, that rule is only natural-language guidance. There is no hard runtime capability check preventing a subagent from calling it
The immediate orchestration trigger was OMO 4.19.4's start-work-continuation hook. On the worker's SubagentStop, the hook matched the parent/root session id stored in Boulder state, injected the remaining root plan into the completed child, and instructed it to delegate the next checkbox through native multi-agent tools. This is a separate OMO identity/scope bug
During the incident, the child entered Code Mode exec and searched for agent/collaboration capabilities. Native multi-agent functions were not exposed through that Code Mode catalog, but the inherited codex_app namespace was. The child discovered codex_app__create_thread, called it twice in parallel despite the tool's explicit-user-request rule, and both calls returned new thread IDs
The upstream issue is therefore a hard capability-boundary failure, not a claim that Codex independently invented the desire to delegate. A third-party hook and a model/tool-selection error triggered the calls; Codex still exposed and accepted root task-management operations from a known non-root caller
The resulting state rows were not subagents:
source = vscode
thread_source = user
forked_from_id = null
- no
agent_path, agent_role, or agent_nickname
- no incoming spawn edge
They appeared as normal independent tasks in the Desktop sidebar, continued under separate lifecycles, used independent permission profiles, and spawned their own descendants. This looked like subagents had escaped their parent, but the metadata shows that the child had actually created new root tasks
One generated task used an on-request restricted profile while the other used never with the sandbox disabled. This also explains why permission requests appeared independently and repeatedly instead of following the original subagent lifecycle
Later cross-task messages displayed Sent by ChatGPT from another task. That marker itself is behaving correctly: the installed App renders it for messages carrying codexDelegation and links back to the source thread. The bug is that a non-root child could create and coordinate user-owned tasks in the first place
Full session IDs and prompts are redacted from this public report. I can provide the local metadata through a private channel if useful; no raw prompts, credentials, command bodies, or user content are required to reproduce the capability problem
What steps can reproduce the bug?
OMO is not required for reproduction. It supplied the concrete trigger in this incident, but the upstream defect exists whenever any prompt, hook, orchestration error, or adversarial input causes a non-root session to attempt one of these user-owned task operations
A source-level and runtime reproduction is:
- Start a Codex App project task with multi-agent support and the normal
codex_app dynamic tool catalog
- Spawn a full-history subagent
- Inspect the child session metadata or Code Mode
ALL_TOOLS
- Observe that the child still has
codex_app__create_thread and the other user-owned task-management functions
- From the child, invoke
codex_app__create_thread with a valid project target
- Observe that the returned thread is a new
source = vscode, thread_source = user root task with no spawn-edge parent and its own permission/lifecycle state
The relevant source path is deterministic:
- A fork loads the parent rollout, including session metadata, into the child history:
- When no explicit dynamic tool list is supplied, session startup restores dynamic tools from the inherited conversation history without consulting
SessionSource:
- Tool planning registers every dynamic tool unconditionally even though it already has the turn context:
- Code Mode intentionally makes deferred or hidden dynamic tools discoverable through
ALL_TOOLS and callable:
This means deferLoading changes presentation, not authorization
Codex already provides SessionSource::is_non_root_agent(), which could support the missing restriction:
There is also precedent for hard source-aware capability enforcement in the App Server: direct input is explicitly rejected for multi-agent v2 child sources
What is the expected behavior?
A non-root agent should not be able to create, fork, hand off to, mutate, archive, or directly message user-owned Codex App tasks merely because those dynamic tools were persisted in the root conversation and inherited through a history fork
This must be enforced even when a third-party hook incorrectly broadens the child's scope, the model selects the wrong tool, or an adversarial prompt attempts the operation. Those circumstances are exactly why a host-side authorization boundary is needed
Subtasks should remain on the multi-agent control plane. A separate user-owned task should be creatable only from a root or user turn with explicit user intent
I suggest enforcing this in both layers:
- Filter or reject user-owned task mutation tools for
SessionSource::SubAgent and other internal non-root sessions
- Apply the policy to ordinary tool specs, tool search, Code Mode
ALL_TOOLS, and direct or forged dynamic calls
- Add defense in depth in the App dynamic-tool handler so
create_thread, fork_thread, handoff_thread, send_message_to_thread, and set_thread_* reject non-root callers unless a host-created explicit-user-intent capability is present
- Keep safe read-only App utilities available separately where intended instead of dropping the whole namespace
- Keep legitimate root-to-task delegation and the
Sent by ChatGPT from another task marker working
A regression test should start a root App thread with dynamic tools, fork both v1 and v2 children using full-history and last-N inheritance, and assert that forbidden task-management functions are absent or rejected across every exposure path. It should also verify that an explicitly user-authorized root call still works
Additional information
A follow-up transcript audit established the complete causal chain:
- The scoped LazyCodex worker completed its assigned task
- OMO's
SubagentStop continuation hook incorrectly injected the root plan's next checkbox into that child
- The hook instructed native subagent delegation, not creation of separate Desktop tasks
- The child searched Code Mode
ALL_TOOLS, found inherited codex_app task controls, and called create_thread
- Codex accepted both calls and created user-owned root tasks with independent permission and lifecycle state
OMO's documented isolated Codex CLI reviewer was not invoked, and its Codex App team-mode transport was not activated. The accidental reviewer was one of the two Desktop tasks created by the child
This narrows responsibility without removing the upstream defect: OMO needs to stop resuming completed children as root orchestrators, while Codex must reject root-only task operations from non-root sessions regardless of what prompted the call
The incident occurred while model traffic was routed through Codex Pooler, so I audited its recently completed Agents v2 compatibility work before attributing the App capability failure to Codex
Codex Pooler only preserves canonical encrypted agent_message handoffs between agent paths. Its public implementation validates the NEW_TASK and MESSAGE envelopes here:
That gateway behavior cannot invoke a local App dynamic tool, insert a source = vscode user thread, create a sidebar conversation, select a local permission profile, or attach codexDelegation metadata. The source and target state records rule out the proxy handoff path, and the missing capability boundary is present in current upstream Codex source independently of Codex Pooler
Both accidentally created tasks eventually emitted explicit task_complete. This is not a report about permanently live threads. It is about unauthorized root-task creation, independent permissions, and a lifecycle/resource multiplier from a non-root agent
I searched open and closed issues and open pull requests for codex_app, create_thread, inherited dynamic tools, user-owned threads, and the delegation marker and did not find an existing report
What version of the Codex App are you using (From “About Codex” dialog)?
Codex App
26.810.41047, build6570. The associated rollout metadata reports Codex0.148.0-alpha.9The source checkout used for the analysis exactly matched upstream
mainat2ca575026cef066a58c70f6bdee4feafa6e63d3aWhat subscription do you have?
ChatGPT paid plan. The exact tier is omitted from this public report because the failure is a local capability-boundary issue and does not appear plan-dependent
What platform is your computer?
Darwin 25.5.0 arm64 arm, macOS26.5.1build25F80What issue are you seeing?
A real multi-agent child, after a third-party OMO/LazyCodex
SubagentStopcontinuation hook incorrectly promoted the completed worker into the root plan orchestrator, used inherited Codex App dynamic tools to create two independent, user-owned Desktop tasksThe user had requested ordinary plan execution through subagents, not separate Desktop tasks. The OMO hook explains why the child attempted further delegation; it does not supply explicit user authorization to create user-owned tasks
The source conversation was a normal depth-1
SessionSource::SubAgent(ThreadSpawn)child with an incoming spawn edge and a parent thread. Its persistedSessionMeta.dynamic_toolsnevertheless contained the completecodex_appnamespace, including:create_threadfork_threadhandoff_threadsend_message_to_threadset_thread_archivedset_thread_pinnedset_thread_titleThe tool description for
create_threadcorrectly says:Create a separate task only when the user explicitly asks for a new task.However, that rule is only natural-language guidance. There is no hard runtime capability check preventing a subagent from calling itThe immediate orchestration trigger was OMO 4.19.4's
start-work-continuationhook. On the worker'sSubagentStop, the hook matched the parent/root session id stored in Boulder state, injected the remaining root plan into the completed child, and instructed it to delegate the next checkbox through native multi-agent tools. This is a separate OMO identity/scope bugDuring the incident, the child entered Code Mode
execand searched for agent/collaboration capabilities. Native multi-agent functions were not exposed through that Code Mode catalog, but the inheritedcodex_appnamespace was. The child discoveredcodex_app__create_thread, called it twice in parallel despite the tool's explicit-user-request rule, and both calls returned new thread IDsThe upstream issue is therefore a hard capability-boundary failure, not a claim that Codex independently invented the desire to delegate. A third-party hook and a model/tool-selection error triggered the calls; Codex still exposed and accepted root task-management operations from a known non-root caller
The resulting state rows were not subagents:
source = vscodethread_source = userforked_from_id = nullagent_path,agent_role, oragent_nicknameThey appeared as normal independent tasks in the Desktop sidebar, continued under separate lifecycles, used independent permission profiles, and spawned their own descendants. This looked like subagents had escaped their parent, but the metadata shows that the child had actually created new root tasks
One generated task used an
on-requestrestricted profile while the other usedneverwith the sandbox disabled. This also explains why permission requests appeared independently and repeatedly instead of following the original subagent lifecycleLater cross-task messages displayed
Sent by ChatGPT from another task. That marker itself is behaving correctly: the installed App renders it for messages carryingcodexDelegationand links back to the source thread. The bug is that a non-root child could create and coordinate user-owned tasks in the first placeFull session IDs and prompts are redacted from this public report. I can provide the local metadata through a private channel if useful; no raw prompts, credentials, command bodies, or user content are required to reproduce the capability problem
What steps can reproduce the bug?
OMO is not required for reproduction. It supplied the concrete trigger in this incident, but the upstream defect exists whenever any prompt, hook, orchestration error, or adversarial input causes a non-root session to attempt one of these user-owned task operations
A source-level and runtime reproduction is:
codex_appdynamic tool catalogALL_TOOLScodex_app__create_threadand the other user-owned task-management functionscodex_app__create_threadwith a valid project targetsource = vscode,thread_source = userroot task with no spawn-edge parent and its own permission/lifecycle stateThe relevant source path is deterministic:
agent/control/spawn.rs#L657-L686SessionSource:session/mod.rs#L656-L660tools/spec_plan.rs#L147-L166tools/spec_plan.rs#L1220-L1247ALL_TOOLSand callable:code_mode.rs#L5503-L5665This means
deferLoadingchanges presentation, not authorizationCodex already provides
SessionSource::is_non_root_agent(), which could support the missing restriction:protocol.rs#L2700-L2708There is also precedent for hard source-aware capability enforcement in the App Server: direct input is explicitly rejected for multi-agent v2 child sources
turn_processor.rs#L19-L31What is the expected behavior?
A non-root agent should not be able to create, fork, hand off to, mutate, archive, or directly message user-owned Codex App tasks merely because those dynamic tools were persisted in the root conversation and inherited through a history fork
This must be enforced even when a third-party hook incorrectly broadens the child's scope, the model selects the wrong tool, or an adversarial prompt attempts the operation. Those circumstances are exactly why a host-side authorization boundary is needed
Subtasks should remain on the multi-agent control plane. A separate user-owned task should be creatable only from a root or user turn with explicit user intent
I suggest enforcing this in both layers:
SessionSource::SubAgentand other internal non-root sessionsALL_TOOLS, and direct or forged dynamic callscreate_thread,fork_thread,handoff_thread,send_message_to_thread, andset_thread_*reject non-root callers unless a host-created explicit-user-intent capability is presentSent by ChatGPT from another taskmarker workingA regression test should start a root App thread with dynamic tools, fork both v1 and v2 children using full-history and last-N inheritance, and assert that forbidden task-management functions are absent or rejected across every exposure path. It should also verify that an explicitly user-authorized root call still works
Additional information
A follow-up transcript audit established the complete causal chain:
SubagentStopcontinuation hook incorrectly injected the root plan's next checkbox into that childALL_TOOLS, found inheritedcodex_apptask controls, and calledcreate_threadOMO's documented isolated Codex CLI reviewer was not invoked, and its Codex App team-mode transport was not activated. The accidental reviewer was one of the two Desktop tasks created by the child
This narrows responsibility without removing the upstream defect: OMO needs to stop resuming completed children as root orchestrators, while Codex must reject root-only task operations from non-root sessions regardless of what prompted the call
The incident occurred while model traffic was routed through Codex Pooler, so I audited its recently completed Agents v2 compatibility work before attributing the App capability failure to Codex
Codex Pooler only preserves canonical encrypted
agent_messagehandoffs between agent paths. Its public implementation validates theNEW_TASKandMESSAGEenvelopes here:continuity_payload.ex#L41-L61That gateway behavior cannot invoke a local App dynamic tool, insert a
source = vscodeuser thread, create a sidebar conversation, select a local permission profile, or attachcodexDelegationmetadata. The source and target state records rule out the proxy handoff path, and the missing capability boundary is present in current upstream Codex source independently of Codex PoolerBoth accidentally created tasks eventually emitted explicit
task_complete. This is not a report about permanently live threads. It is about unauthorized root-task creation, independent permissions, and a lifecycle/resource multiplier from a non-root agentI searched open and closed issues and open pull requests for
codex_app,create_thread, inherited dynamic tools, user-owned threads, and the delegation marker and did not find an existing report