Native subagent orchestration does not work correctly with non-OpenAI custom providers

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

What version of Codex CLI is running?

0.120.0

What subscription do you have?

ChatGPT Pro

Which model were you using?

gpt-5.4

What platform is your computer?

Linux 5.19.0-43-generic x86_64 x86_64, Linux 6.6.87.2-microsoft-standard-WSL2 x86_64 x86_64

What terminal emulator and version are you using (if applicable)?

Windows Terminal using WSL and PowerShell

What issue are you seeing?

In codex-cli 0.120.0, native subagents do not work correctly with a non-OpenAI custom provider.

I observed two related failures:

  1. When the parent session uses OpenAI and the child subagent is configured with a non-OpenAI custom provider, the child rollout is created, but the child keeps the parent OpenAI config instead of applying the custom provider config.
  1. When the parent session itself uses the non-OpenAI custom provider, native subagent orchestration does not happen at all. No spawn_agent call appears in the rollout, no child rollout is created, and the parent answers directly.

OpenAI-only native subagents work correctly in the same environment, so this appears to be specific to native subagents with non-OpenAI custom providers.

What steps can reproduce the bug?

  1. Configure a working non-OpenAI custom provider in ~/.codex/config.toml, for example:

```toml
[model_providers.company_local]
name = "Company Local LLM"
env_key = "LOCAL_LLM_API_KEY"
wire_api = "responses"

[profiles.local_main]
model_provider = "company_local"
model = "code-fast"

[profiles.local_fast]
model_provider = "company_local"
model = "code-fast"

  1. Verify that direct execution works:

``
codex exec -p local_main --skip-git-repo-check --json "Reply with exactly: LOCAL_OK"
``

  1. Add a custom subagent config like:
name = "local_llm_worker"
model_provider = "company_local"
model = "code-fast"
model_reasoning_effort = "medium"
sandbox_mode = "read-only"
developer_instructions = """
Use the local LLM provider for read-only code exploration.
"""
  1. Reproduce failure case 1, OpenAI parent to custom-provider child:
codex --enable multi_agent_v2 exec -p openai_heavy --skip-git-repo-check --json "Use the local_llm_worker subagent for read-only exploration only. If the subagent runs, end with exactly LOCAL_WORKER_OK. If unavailable, end with exactly LOCAL_WORKER_UNAVAILABLE."
  1. Reproduce failure case 2, custom-provider parent session:
codex --enable multi_agent_v2 exec -p local_main --skip-git-repo-check --json "You must use the local_llm_worker subagent via native subagent spawning, not by answering yourself. Read-only exploration only. End with exactly LOCAL_PARENT_LOCAL_CHILD_OK or LOCAL_PARENT_LOCAL_CHILD_UNAVAILABLE."
  1. Optionally repeat the same test with another custom-provider parent profile such as local_fast.

What is the expected behavior?

Native subagents should work consistently with non-OpenAI custom providers.

Expected behavior:

  • If a child subagent specifies:
  • model_provider = "company_local"
  • model = "code-fast"
  • model_reasoning_effort = "medium"

then the spawned child session should reflect those values in its effective config.

  • If the parent session uses a non-OpenAI custom provider, native subagent orchestration should still occur normally:
  • spawn_agent should appear in the rollout
  • a child rollout should be created
  • the parent should not answer directly instead of spawning the child

This should behave analogously to OpenAI-only native subagents, which work correctly in the same environment.

Additional information

What works:

  • Direct execution with the custom provider works correctly
  • OpenAI-only native subagents work correctly
  • A custom subagent with:
  • model_provider = "openai"
  • model = "gpt-5.4-mini"

correctly produces a child rollout with the expected provider/model/effort values

Observed failure details:

  • In the OpenAI parent -> custom-provider child case:
  • child rollout is created
  • agent identity and developer instructions are applied
  • but child config remains on parent OpenAI values:
  • model_provider = openai
  • turn_context.model = gpt-5.4
  • collaboration_mode.settings.model = gpt-5.4
  • effort = high
  • In the custom-provider parent case:
  • parent starts correctly on company_local / code-fast
  • no spawn_agent call appears in the rollout
  • no child rollout file is created
  • parent answers directly

This makes it look like native subagent support is incomplete or broken for non-OpenAI custom providers, both in child config merging and in orchestration from a custom-provider parent.

Related issues:

  • #11701
  • #13204
  • #14039
  • #15170
  • #13849

View original on GitHub ↗

15 Comments

github-actions[bot] contributor · 4 months ago

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

  • ##16548
  • ##16893

Powered by Codex Action

jaloveeye · 4 months ago

Thank you for pointing these out.

After reviewing #16548 and #16893, I believe this issue is related, but not an exact duplicate.

My understanding is that those issues are primarily about subagents not respecting a requested model override within Codex/OpenAI model flows, particularly around explorer and gpt-5.4-mini.

In this case, the main problem seems to be slightly different: role-based/native subagents do not appear to inherit or honor the active custom/local provider or profile correctly, and instead fall back away from the configured local provider path.

Because of that, this may be closer to #13204, and possibly related to the broader subagent configuration inheritance / runtime override issues discussed in #15170 and #14039.

I’m happy to close this if maintainers believe it should be consolidated elsewhere, but at the moment it does not look like a clean duplicate of #16548 or #16893.

iqdoctor · 1 month ago

+1

iqdoctor · 1 month ago

Cross-linking the related main regression:

This looks like part of the same local/custom-provider subagent failure family.

niieani · 1 month ago

This also breaks tools like caara, which give codex the ability to run claude code and antigravity as native subagents.

ZhongXinlin · 1 month ago

I can reproduce a related but narrower failure on macOS with a newer build: the custom-provider child is created with the requested provider/model, but the dynamic task payload is not delivered.

Environment

  • Codex Desktop bundled CLI: codex-cli 0.146.0-alpha.3.1
  • Parent: gpt-5.6-sol
  • Child provider: non-OpenAI custom provider
  • Child models tested: MiniMax-M3 and MiniMax-M2.7-highspeed
  • wire_api = "responses"
  • multi_agent = true
  • multi_agent_v2 = false

Sanitized provider shape:

[model_providers.minimax]
name = "MiniMax"
base_url = "https://api.minimax.io/v1"
wire_api = "responses"

[model_providers.minimax.auth]
command = ["<redacted command-backed token helper>"]

Preconditions

  • The custom roles are discovered by native spawn_agent.
  • Child rollout metadata records model_provider = minimax and the requested MiniMax role/model.
  • Direct stateless /v1/responses and /v1/chat/completions canaries both return an exact unique marker.
  • A default same-provider child spawned from the same parent receives and executes a fresh bounded task correctly.
  • Codex was fully restarted before the recovery test.

Reproduction

Spawn a fresh MiniMax child with fork_turns = "none" and a unique marker in message:

Delegation-ID:
minimax-restart-canary-20260727-A

Need:
Sort the distinct inline words and return the count.

Boundaries:
Read-only; no tools or files.

Deliverable:
Echo the Delegation-ID and return the exact result.

Observed

  • The parent rollout contains minimax-restart-canary-20260727-A.
  • MiniMax child session 019f9f6d-ea86-7a02-b1fb-41fa47971973 does not contain the marker.
  • The child returns the local fail-closed sentinel TASK_PAYLOAD_MISSING.
  • Tool calls: 0; edit calls: 0.
  • One evidence-triggered resend through followup_task also does not deliver the assignment.

Control

A fresh default same-provider child received same-provider-control-20260727-C, echoed the ID, executed the corresponding inline sorting/sum task exactly, and used no tools. Control session: 019f9f6f-6b0f-7381-bb8b-b1b4bde2a794.

This localizes the current failure to dynamic spawn_agent.message / followup_task.message delivery for the non-OpenAI custom-provider child. Unlike the original report, the child provider/model selection itself is now observable and correct; task delivery is the failing stage.

DoNotBugPlz · 7 days ago

Additional macOS regression data point: 0.148 works, 0.149 falls back to openai

This matches failure case 1 in the original report, with a version A/B and two different non-OpenAI child providers.

Environment
  • macOS, Codex Desktop
  • ChatGPT-authenticated OpenAI parent
  • Working bundled CLI: 0.148.0-alpha.15
  • Regressed bundled CLI: 0.149.0-alpha.4
  • Two personal custom agents, each configured with its own Responses-compatible model_provider and model:
  • xAI-backed child using grok-4.6
  • Anthropic-backed child using claude-opus-5
  • fork_turns = "1"
Version A/B from rollout metadata

Under 0.148.0-alpha.15, both children ran successfully from the same long-lived parent thread:

agent_role=grok_lane    model_provider=<custom-grok-provider>    model=grok-4.6
agent_role=claude_lane  model_provider=<custom-claude-provider>  model=claude-opus-5

After Desktop updated to 0.149.0-alpha.4, the same spawn_agent shape preserved the role and model but overwrote the provider:

agent_role=grok_lane    model_provider=openai  model=grok-4.6
agent_role=claude_lane  model_provider=openai  model=claude-opus-5

The children then failed before producing a usable custom-provider turn.

Two observable failure paths

Fresh 0.149.0-alpha.4 thread:

session_startup_prewarm: startup websocket prewarm setup failed:
The 'grok-4.6' model is not supported when using Codex with a ChatGPT account.

The same occurs for claude-opus-5.

Long/resumed thread:

Error running remote compact task:
The 'grok-4.6' model is not supported when using Codex with a ChatGPT account.

Again, the same occurs for claude-opus-5.

Temporarily enabling multi_agent_v2 for one fresh Grok-only reproduction did not change the result; startup prewarm still used the ChatGPT/OpenAI route.

Controls
  • Direct Responses canaries through both custom providers succeed.
  • The local provider model catalog exposes both model IDs with the expected owners.
  • The provider service is healthy and loopback-only.
  • The relevant Grok provider, plugin switch, custom-agent file, and non-Claude provider configuration are unchanged relative to the pre-regression state.
Expected behavior

The custom-agent configuration layer, especially model_provider, should be applied before startup prewarm and remote compaction choose their transport/auth route. A ChatGPT-authenticated parent should not cause a custom-provider child model ID to be validated against the ChatGPT model entitlement path.

This looks like a 0.149.0-alpha.4 provider-application-order regression rather than a model entitlement failure.

Related: #37858 and #35751.

DoNotBugPlz · 7 days ago

Source trace: the 0.149 behavior is introduced by #39299

I traced the 0.148 -> 0.149 change to #39299 (1a6e07a4febcc0ecfa04464f5e95cb47144cd746), merged on 2026-08-18: “Restrict agent roles to bounded configuration overrides.”

The PR's stated design is that an agent role may customize model behavior but must not change the provider configuration inherited from its parent session.

The implementation replaces full role config-layer application with a typed AgentRoleOverrides allowlist. That allowlist includes model, reasoning settings, instructions, personality, service tier, and capability reductions, but excludes model_provider.

The new tests explicitly assert:

child.model_provider_id == parent.model_provider_id
child.model_provider    == parent.model_provider
child.model_providers   == parent.model_providers

They also assert that the projected role layer does not contain model_provider.

This precisely explains the rollout A/B reported above:

0.148: role=grok_lane    model=grok-4.6       provider=<custom-grok-provider>
0.148: role=claude_lane  model=claude-opus-5  provider=<custom-claude-provider>

0.149: role=grok_lane    model=grok-4.6       provider=openai
0.149: role=claude_lane  model=claude-opus-5  provider=openai

The startup-prewarm and remote-compaction entitlement errors are downstream symptoms: the role's external model override is retained, while its provider override is intentionally dropped, so the external model ID is sent through the parent's ChatGPT/OpenAI route.

I did not find an open PR or issue specifically addressing this #39299 cross-provider consequence.

I understand the authority concern behind #39299, and I am not suggesting restoring unrestricted role config overlays. The remaining product gap could be addressed safely by either:

  1. an explicit parent-approved provider/profile allowlist or capability for named agents; or
  2. fail-closed spawn validation when a role requests a provider different from its parent, with a clear error explaining that cross-provider roles are disallowed.

The current behavior silently drops model_provider, keeps the incompatible model ID, and surfaces a misleading ChatGPT entitlement error. The current custom-agent documentation should also state that provider selection is parent-owned if that is now the intended contract.

PR: https://github.com/openai/codex/pull/39299

palvaleri · 6 days ago

Additional GLM-5.3/ZAI data point: bundled 0.148 works; bundled and stable 0.149 fall back to openai

I can independently reproduce the same cross-provider regression on macOS with a ChatGPT-authenticated parent and a read-only custom child role:

name = "glm53"
model_provider = "ZAI"
model = "glm-5.3"
model_reasoning_effort = "max"
sandbox_mode = "read-only"
Rollout A/B

Last observed working bundled runtime:

cli_version=0.148.0-alpha.21
agent_role=glm53
model_provider=ZAI
model=glm-5.3
task_complete.error=null

First observed regressed bundled runtime:

cli_version=0.149.0-alpha.4
agent_role=glm53
model_provider=openai
model=glm-5.3

The child then fails before producing a response:

The 'glm-5.3' model is not supported when using Codex with a ChatGPT account.
Stable CLI control

I also reproduced this independently with public stable codex-cli 0.149.0: a ChatGPT/OpenAI parent used native subagent spawning with the configured glm53 role. Startup prewarm retained model=glm-5.3, routed it through the inherited OpenAI/ChatGPT provider, and returned the same 400 error.

Provider/model health control

A direct ephemeral read-only codex exec using the same glm-5.3 model with explicit model_provider="ZAI" completed successfully and returned an exact marker. This confirms that the custom provider endpoint, authentication, and model are healthy; the failing boundary is role-to-child provider application.

This independently confirms the cross-provider consequence described above for a third external model/provider combination and shows that it affects stable CLI 0.149.0, not only Desktop's bundled alpha build.

The behavior is consistent with #39299: the role model override survives while the role provider override is intentionally excluded. At minimum, spawn should fail closed with an explicit cross-provider-role diagnostic instead of sending the external model ID through the parent's ChatGPT entitlement path. A parent-approved provider/profile allowlist would preserve the security boundary while restoring trusted cross-provider roles.

DoNotBugPlz · 6 days ago

Thanks — this is a very useful independent reproduction, especially the stable 0.149.0 control. The ZAI/GLM-5.3 result shows that the regression is not specific to the Grok/Claude providers and strengthens the #39299 cross-provider diagnosis.

gNikro · 5 days ago

Additional Windows / Ollama-compatible A/B: 0.148.0-alpha.21 works, 0.149.0-alpha.4 inherits openai

I can independently reproduce the same cross-provider regression on Windows with a ChatGPT-authenticated parent and two custom child roles: a worker and a read-only explorer.

The roles use a Responses-compatible custom provider backed by an Ollama-compatible local proxy, with model deepseek-v4-flash:cloud.

Last confirmed working runtime
cli_version=0.148.0-alpha.21
agent_role=<custom-worker-or-explorer>
model_provider=<custom-ollama-provider>
model=deepseek-v4-flash:cloud
task_complete.error=null

The child completed through the custom provider.

Regressed runtime

With the same global provider definition and unchanged role files:

cli_version=0.149.0-alpha.4
agent_role=<custom-worker-or-explorer>
model_provider=openai
model=deepseek-v4-flash:cloud

Both role types then fail before processing the task:

The 'deepseek-v4-flash:cloud' model is not supported when using Codex with a ChatGPT account.
Controls
  • The custom provider endpoint remains healthy.
  • Its model catalog still exposes deepseek-v4-flash:cloud.
  • Direct provider requests work.
  • Role discovery itself works: the child is created with the requested role and model.
  • Only the provider changes from the configured custom provider to openai across the version boundary.

This confirms the 0.148 -> 0.149 behavior described above for another platform and for Ollama-based routing. It is also consistent with the bounded role override behavior introduced by #39299: the role's model override survives while its model_provider override is discarded.

The security goal of keeping provider authority parent-owned makes sense, but the current partial application is unsafe and misleading. At minimum, spawn should fail closed with an explicit cross-provider-role diagnostic. A parent-approved allowlist for trusted user-level providers would preserve the authority boundary without removing mixed OpenAI-parent / local-child workflows.

DoNotBugPlz · 5 days ago

Thanks, this is a useful repro. Seeing the same 0.148 -> 0.149 break on Windows, through an Ollama-compatible provider, and with both worker and explorer roles rules out a lot of setup-specific noise. The controls are clean too. Appreciate you taking the time to document it.

interconnectedMe · 3 days ago

Confirming this regression independently on Linux with custom native subagents.

Regression matrix:

  • VS Code extension 26.818.22352, bundled CLI 0.148.0-alpha.21, with features.multi_agent_v2=false: the custom worker completed successfully.
  • Marketplace extension 26.818.61809, bundled CLI 0.149.0-alpha.4.3, using default V1 (multi_agent_v2=false): failed.
  • The same 0.149.0-alpha.4.3 build with features.multi_agent_v2=true: failed identically.

The custom-agent configuration retained:

model = "deepseek-v4-flash"
model_provider = "opencode_go_responses"
It also contained the matching [model_providers.opencode_go_responses] definition.

On the failing build, the child produced:

The 'deepseek-v4-flash' model is not supported when using Codex with a ChatGPT account.
This is consistent with the child retaining the custom model name while losing or resetting its custom provider and being routed through the ChatGPT/OpenAI backend.

The regression affects both V1 and V2. Forcing V1 works only on the older known-good build.
pcordon · 2 days ago

Sorry for the noise from the issue I opened earlier and then closed. Didn’t realize this existing issue was the better place to add the finding.

I think #39299 may explain the current OpenAI-parent → custom-provider-child failure.

Before that PR, agent role configs could override model_provider. Then #39299 changed role handling so the child inherits the parent provider, while fields like model can still be overridden.

That creates a bad state where a child role like:

model = "testmodel01"
model_provider = "custom_provider"

effectively becomes:

model = testmodel01
model_provider = <parent provider>

So if the parent is using the ChatGPT/OpenAI provider, the child’s custom model name is sent through that inherited provider and fails with:

The 'testmodel01' model is not supported when using Codex with a ChatGPT account.

What makes this especially confusing is that #14039 was closed as completed with an official statement saying:

“Subagents support model, reasoning, provider, and role configuration.”

But 13 days later, #39299 changed the behavior so a child role can no longer override model_provider.

So from a user perspective, the current behavior appears to directly contradict the way #14039 was resolved.

Is cross-provider subagent routing still intended to be supported?

If the provider inheritance in #39299 is intentional for security reasons, could there be an explicit parent-side opt-in or allowlist for child providers instead of removing the capability entirely?

gNikro · 1 day ago

Still reproducible on Desktop 26.820.7780 / CLI 0.150.0-alpha.8

I retested the same two cross-provider custom roles after updating:

  • one worker role;
  • one read-only explorer role.

Both children were created, but neither reached its task.

Expected effective child configuration:

model_provider=<custom-ollama-provider>
model=deepseek-v4-flash:cloud

Observed in both child rollouts:

cli_version=0.150.0-alpha.8
model_provider=<parent-provider>
model=deepseek-v4-flash:cloud

Both failed with:

The 'deepseek-v4-flash:cloud' model is not supported when using Codex with a ChatGPT account.

This confirms that the role model override still survives while the role
model_provider is discarded and replaced with the parent provider.

Could a maintainer clarify the intended contract after #39299?

  1. Is cross-provider subagent routing intentionally unsupported now?
  2. If so, should this be documented and rejected explicitly at spawn time

instead of retaining the external model and producing a misleading
ChatGPT entitlement error?

  1. If cross-provider roles are still intended to work, which issue or PR is

tracking the regression?

The last confirmed working bundled runtime remains 0.148.0-alpha.21.