Skip to content

[Bug] Per-role model_fallback causes Codex 0.146.0 to reject custom agent TOML #1190

Closed

Description

@eingo19

Client or integration

Codex CLI and Codex App

Area

Proxy and routing / Catalog and models / Documentation

Summary

OpenCodex documents the per-role model_fallback field in $CODEX_HOME/agents/*.toml as the second source in its spawned-worker fallback priority:

  1. requested primary model
  2. the role's model_fallback
  3. global subagentModelFallback

However, Codex CLI 0.146.0 strictly deserializes custom-agent TOML files. If a role contains model_fallback, Codex reports it as an unknown field and skips the entire role definition. The role therefore never enters the multi_agent_v1 runtime registry, so OpenCodex cannot apply the documented fallback chain.

This appears to be a compatibility defect between OpenCodex's documented per-role fallback extension and Codex's native custom-agent schema, rather than a provider-specific model failure.

Related feature: #374
Current documentation: https://opencodex.me/guides/sub-agent-surface/#fallback-chains

Reproduction

The failure was reproduced in an isolated temporary CODEX_HOME; the working global configuration was not modified.

  1. Create $CODEX_HOME/config.toml:
[features]
multi_agent = true
  1. Create $CODEX_HOME/agents/test_worker.toml:
name = "test_worker"
description = "Minimal fallback compatibility test"
model = "opencode-go/deepseek-v4-flash"
model_fallback = ["deepseek/deepseek-v4-flash", "gpt-5.6-luna"]

developer_instructions = """
Return a short result.
"""
  1. Run:
$env:CODEX_HOME = "C:\path\to\isolated-codex-home"
codex doctor --all --no-color --ascii
  1. Observe that Codex loads config.toml successfully but skips test_worker.toml.

  2. Remove only the model_fallback line and restart Codex.

  3. The role is then registered and appears in the current task's multi_agent_v1 Available roles.

Real configuration impact

The original setup contained five custom roles:

  • luna_worker.toml: no model_fallback; registered successfully
  • deepseekflash_go_worker.toml: had model_fallback; not registered
  • deepseekflash_worker.toml: had model_fallback; not registered
  • glm52_worker.toml: had model_fallback; not registered
  • kimik3_worker.toml: had model_fallback; not registered

After removing only model_fallback from the four affected files and fully restarting Codex, all five custom roles were present in the live runtime registry:

deepseekflash_go_worker
deepseekflash_worker
glm52_worker
kimik3_worker
luna_worker

Version

  • OpenCodex: 2.10.0
  • Codex CLI: 0.146.0
  • Codex installation: npm package
  • Multi-agent mode: v1
  • agents.enabled: true

Operating system

Windows 11, build 26200, x86_64

Provider and model

The deserialization failure happens before model routing, so it is not provider-specific.

The affected real-world roles used:

  • opencode-go/deepseek-v4-flash
  • deepseek/deepseek-v4-flash
  • opencode-go/glm-5.2
  • opencode-go/kimi-k3
  • fallback target gpt-5.6-luna

Logs or error output

Configuration
  [!!] config       config loaded
      config.toml parse        ok
      startup warnings         1
      startup warning          Ignoring malformed agent role definition: failed to deserialize agent role file at C:\path\to\isolated-codex-home\agents\test_worker.toml: unknown field `model_fallback`

The isolated codex doctor run exited non-zero because the temporary home intentionally contained no authentication credentials. That is unrelated to the agent parsing warning; config.toml parse was ok, and the exact startup warning above was emitted before any model request.

Expected behavior

A per-role fallback mechanism documented by OpenCodex should not invalidate the underlying Codex custom-agent definition.

At minimum, OpenCodex should detect that the installed Codex runtime rejects model_fallback and provide a clear compatibility warning or migrate the fallback metadata elsewhere.

Actual behavior

Codex rejects the complete custom-agent TOML before the role can be registered. From the user's perspective:

  1. the TOML file exists;
  2. the configured primary and fallback models both exist;
  3. the role is nevertheless absent from multi_agent_v1 Available roles;
  4. spawning with that agent_type is rejected as an unregistered role.

Removing the documented fallback field fixes registration, but loses the per-role proxy fallback metadata.

Root-cause analysis

Codex's agent-role TOML schema denies unknown fields. model_fallback is an OpenCodex extension, but it is stored in the same TOML document that Codex must deserialize before exposing the role.

The proxy may be able to read this field independently, but Codex rejects the role first. As a result, the documented fallback feature prevents the role from reaching the spawn surface it is meant to protect.

Suggested fixes

Prefer keeping OpenCodex-only metadata outside files parsed by native Codex. For example:

  1. Store per-role fallback chains in ~/.opencodex/config.json, keyed by role name or agent TOML path.
  2. Use a separate OpenCodex sidecar metadata file.
  3. Add a version/schema compatibility check and refuse to configure unsupported per-role TOML fields.
  4. Provide an ocx doctor diagnostic that scans $CODEX_HOME/agents/*.toml and warns that model_fallback will make affected Codex versions skip the role.
  5. If future Codex versions add a native fallback field, gate direct TOML emission on confirmed schema support.

The global subagentModelFallback mechanism can remain in OpenCodex config because it does not contaminate Codex-owned role TOML.

Workaround

Remove model_fallback from every $CODEX_HOME/agents/*.toml file, restart Codex completely, and define fallback behavior through:

  • OpenCodex's global fallback configuration; or
  • main-agent routing instructions that explicitly retry a fallback role/model.

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.
  • The failure was reproduced in an isolated temporary CODEX_HOME.
  • Registration was verified again after removing only the unsupported field.

Activity

  1. github-actions commented on Aug 7, 2026

    @github-actions
    Contributor

    Automated translation bookkeeping — detected language: English.

  2. Ingwannu commented on Aug 8, 2026

    @Ingwannu
    Owner

    Confirmed: native Codex rejects the OpenCodex-only model_fallback key before the custom role can register. Draft PR #1210 tracks the correct architectural fix by moving per-role fallback metadata into OpenCodex config and retaining a doctor warning/migration path for legacy TOML. The PR author has not marked its own readiness checklist complete and CI remains queued, so this issue stays open until review and merge; removing the unsupported TOML key remains the safe workaround.

  3. Wibias commented on Aug 9, 2026

    @Wibias
    Contributor

    Resolved on dev.

    The architectural fix from #1210 has been landed directly rather than merged through the PR.

    The landed implementation:

    • moves supported per-model fallback chains into OpenCodex configuration via subagentModelFallbackByModel;

    • stops recommending the Codex-incompatible model_fallback field in $CODEX_HOME/agents/*.toml;

    • retains legacy TOML reading only as a compatibility/migration path;

    • adds ocx doctor diagnostics for agent TOML files that still contain model_fallback;

    • preserves the intended fallback order as:

      primary → keyed OpenCodex fallback → global fallback → legacy TOML fallback

    The main landed change is ba5215021, together with the contributor's follow-up doctor/parser commits and corrective precedence commit fc17327b3.

    PR #1210 was subsequently closed because its implementation had already been landed on dev.

    Closing this issue as completed.

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 working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions