Skip to content

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

Open

Description

@jaloveeye

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.

  2. 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:

    [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"
    
  2. 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:

Activity

  1. added
    CLIIssues related to the Codex CLI
    subagentIssues involving subagents or multi-agent features
    custom-modelIssues related to custom model providers (including local models)
    windows-osIssues related to Codex on Windows systems
    on Apr 13, 2026
  2. github-actions commented on Apr 13, 2026

    @github-actions
    Contributor
  3. removed
    windows-osIssues related to Codex on Windows systems
    CLIIssues related to the Codex CLI
    on Apr 13, 2026
  4. jaloveeye commented on Apr 13, 2026

    @jaloveeye
    Author

    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.

  5. iqdoctor commented on Jul 9, 2026

    @iqdoctor

    +1

  6. iqdoctor commented on Jul 9, 2026

    @iqdoctor

    Cross-linking the related main regression:

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

  7. niieani commented on Jul 11, 2026

    @niieani

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

  8. ZhongXinlin commented on Jul 26, 2026

    @ZhongXinlin

    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.

  9. DoNotBugPlz commented on Aug 21, 2026

    @DoNotBugPlz

    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.

  10. DoNotBugPlz commented on Aug 21, 2026

    @DoNotBugPlz

    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: #39299

  11. palvaleri commented on Aug 21, 2026

    @palvaleri

    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.

  12. DoNotBugPlz commented on Aug 22, 2026

    @DoNotBugPlz

    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.

  13. gNikro commented on Aug 22, 2026

    @gNikro

    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.

  14. DoNotBugPlz commented on Aug 22, 2026

    @DoNotBugPlz

    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.

  15. interconnectedMe commented on Aug 25, 2026

    @interconnectedMe

    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.
  16. pcordon commented on Aug 25, 2026

    @pcordon

    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?

  17. gNikro commented on Aug 26, 2026

    @gNikro

    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?
    3. 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.

  18. interconnectedMe commented on Aug 29, 2026

    @interconnectedMe

    Still reproducible on IDE 26.825.41651 / CLI 0.151.0-alpha.7.1

    I independently retested this on Linux using the newest marketplace Codex IDE extension in an isolated VS Code extension directory. The active pinned IDE profile was not changed.

    Environment:

    • Codex IDE extension: 26.825.41651
    • Bundled runtime: codex-cli 0.151.0-alpha.7.1
    • Parent: ChatGPT/OpenAI, gpt-5.6-sol
    • Custom child role: glm-52-ollama-worker
    • Child model: glm-5.2
    • Child provider: ollama_cloud_responses
    • Provider wire API: responses
    • Command mode: codex exec --ephemeral --enable multi_agent --disable multi_agent_v2
    • Sandbox: read-only

    The role was resolved and the child retained model=glm-5.2, but its configured provider was not used. Startup prewarm went through the ChatGPT/OpenAI backend and failed with:

    The 'glm-5.2' model is not supported when using Codex with a ChatGPT account.
    

    This is the same model-retained/provider-inherited failure previously observed on 0.149. It remains present in the newer 0.151.0-alpha.7.1 bundled runtime with V1 explicitly selected.

    The equivalent V2 probe encountered the separate ephemeral root-thread registration failure tracked in #41474.

  19. DoNotBugPlz commented on Aug 29, 2026

    @DoNotBugPlz

    Thanks for retesting this on 0.151.0-alpha.7.1. The explicit V1 run is especially useful: the child still keeps the custom model while inheriting the OpenAI provider, so the regression is still present beyond the 0.150 builds. Good call tracking the V2 ephemeral root-thread problem separately in #41474.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcustom-modelIssues related to custom model providers (including local models)subagentIssues involving subagents or multi-agent features

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions