Area
Proxy and routing
What are you trying to accomplish?
I run a large routed catalog (10-20+ models across several OpenAI-compatible providers plus anthropic/responses adapters) and need a stable, deterministic order for the Codex model picker across the whole catalog. I want to pin the full picker order once and have it survive catalog rebuilds (ocx sync, ocx service restart, version upgrades), the same way a user would arrange a long provider/model list and expect it to stay put.
What prevents this today?
There is no supported way to control the model-picker order for more than 5 routed models.
PUT /api/subagent-models (the dashboard "featured / sub-agent models" path) hard-caps the list to 5 with .slice(0, 5), and that same list is the only input the catalog builder uses to assign per-model priority. Every non-featured routed model is emitted with the same fallback priority (routed slugs all get 5), so their relative order in the picker is undefined and reshuffles on each catalog rebuild.
The 5-slot cap conflates two separate concerns: (a) the spawn_agent model-override candidates (MAX_MODEL_OVERRIDES_IN_SPAWN_AGENT = 5, a real upstream limit) and (b) the visual ordering of the whole picker (no upstream limit; priority is just an integer sort key).
Evidence (code path):
src/server/management/agent-settings-routes.ts (PUT /api/subagent-models): const chosen = Array.isArray(body.models) ? body.models.filter(...).slice(0, 5) : []; -- the 5-cap is applied here, at the only user-facing write path.
src/codex/convergence.ts: const featured = config.subagentModels ?? []; then orderForSubagents(enabled, featured) -- subagentModels is the sole ordering input.
src/codex/catalog/sync.ts (buildObservedCatalogEntries): featured models get priority = featuredRank * priorityStride + selectorIndex; every other routed model falls through to ((featured?.length ?? 0) + nativeIndex) * ... + selectorIndex, and routed rows otherwise default to priority = 5. Comment at the same site notes: "Codex's models-manager sorts by priority ASC ... Catalog ARRAY order is discarded."
orderForSubagents itself has no length limit -- it happily ranks an arbitrarily long array -- but the only supported way to populate subagentModels truncates to 5. Writing a longer list directly into config.json works until the next dashboard interaction rewrites and re-truncates it.
What should OpenCodex do?
Either provide a way to declare a full ordering for the picker (independent of the 5-slot spawn_agent candidate list), or document that ordering beyond 5 models is intentionally unsupported so integrators stop trying to drive it through subagentModels.
Concretely, any one of these resolves it:
- Add a separate, uncapped ordering field (e.g.
config.modelPickerOrder: string[]) that orderForSubagents consumes for picker priority, while subagentModels keeps its 5-slot spawn_agent semantics; or
- Lift the
.slice(0, 5) on subagentModels for ordering purposes and only apply the 5-cap when deriving spawn_agent candidates downstream; or
- If ordering beyond 5 is intentionally out of scope, document that clearly so integrators do not build fragile catalog-rewrite workarounds.
Example usage or interface
A dedicated ordering field consumed by the catalog builder would look like:
{
"modelPickerOrder": [
"combo/JD",
"jd-chat/kimi-k3-joybuilder",
"jd-responses/GPT-5.6-Sol-joybuilder",
"jd-chat/GLM-5.2-joybuilder",
"jd-claude/Claude-Sonnet-5-joybuilder",
"tyler/deepseek-v4-pro"
]
}
with subagentModels still limited to 5 for spawn_agent candidates. Today the equivalent effect can only be forced by rewriting every model's priority in the generated catalog after each sync, which is not a supported interface.
Alternatives or workarounds
A post-sync script rewrites every model's priority in ~/.codex/opencodex-catalog.json and models_cache.json directly, reproducing the intended full order. It must be re-run after every ocx sync, ocx service restart, and version upgrade, because catalog rebuild resets all routed priorities back to the flat default. This is brittle and easy to forget: an out-of-order restart silently reverts the picker.
Additional context
- Version: opencodex 2.14.2 (
ocx --version); running local service confirmed via GET /healthz.
- Operating system: macOS 26.5.1 (25F80).
- Providers/models: multiple OpenAI-compatible routed providers (10+ routed models across chat / responses / anthropic adapters). Not provider-specific; reproducible with any catalog of more than 5 routed models.
Area
Proxy and routing
What are you trying to accomplish?
I run a large routed catalog (10-20+ models across several OpenAI-compatible providers plus anthropic/responses adapters) and need a stable, deterministic order for the Codex model picker across the whole catalog. I want to pin the full picker order once and have it survive catalog rebuilds (
ocx sync,ocx servicerestart, version upgrades), the same way a user would arrange a long provider/model list and expect it to stay put.What prevents this today?
There is no supported way to control the model-picker order for more than 5 routed models.
PUT /api/subagent-models(the dashboard "featured / sub-agent models" path) hard-caps the list to 5 with.slice(0, 5), and that same list is the only input the catalog builder uses to assign per-modelpriority. Every non-featured routed model is emitted with the same fallbackpriority(routed slugs all get5), so their relative order in the picker is undefined and reshuffles on each catalog rebuild.The 5-slot cap conflates two separate concerns: (a) the spawn_agent model-override candidates (
MAX_MODEL_OVERRIDES_IN_SPAWN_AGENT = 5, a real upstream limit) and (b) the visual ordering of the whole picker (no upstream limit;priorityis just an integer sort key).Evidence (code path):
src/server/management/agent-settings-routes.ts(PUT/api/subagent-models):const chosen = Array.isArray(body.models) ? body.models.filter(...).slice(0, 5) : [];-- the 5-cap is applied here, at the only user-facing write path.src/codex/convergence.ts:const featured = config.subagentModels ?? [];thenorderForSubagents(enabled, featured)--subagentModelsis the sole ordering input.src/codex/catalog/sync.ts(buildObservedCatalogEntries): featured models getpriority = featuredRank * priorityStride + selectorIndex; every other routed model falls through to((featured?.length ?? 0) + nativeIndex) * ... + selectorIndex, and routed rows otherwise default topriority = 5. Comment at the same site notes: "Codex's models-manager sorts bypriorityASC ... Catalog ARRAY order is discarded."orderForSubagentsitself has no length limit -- it happily ranks an arbitrarily long array -- but the only supported way to populatesubagentModelstruncates to 5. Writing a longer list directly intoconfig.jsonworks until the next dashboard interaction rewrites and re-truncates it.What should OpenCodex do?
Either provide a way to declare a full ordering for the picker (independent of the 5-slot spawn_agent candidate list), or document that ordering beyond 5 models is intentionally unsupported so integrators stop trying to drive it through
subagentModels.Concretely, any one of these resolves it:
config.modelPickerOrder: string[]) thatorderForSubagentsconsumes for picker priority, whilesubagentModelskeeps its 5-slot spawn_agent semantics; or.slice(0, 5)onsubagentModelsfor ordering purposes and only apply the 5-cap when deriving spawn_agent candidates downstream; orExample usage or interface
A dedicated ordering field consumed by the catalog builder would look like:
{ "modelPickerOrder": [ "combo/JD", "jd-chat/kimi-k3-joybuilder", "jd-responses/GPT-5.6-Sol-joybuilder", "jd-chat/GLM-5.2-joybuilder", "jd-claude/Claude-Sonnet-5-joybuilder", "tyler/deepseek-v4-pro" ] }with
subagentModelsstill limited to 5 for spawn_agent candidates. Today the equivalent effect can only be forced by rewriting every model'spriorityin the generated catalog after each sync, which is not a supported interface.Alternatives or workarounds
A post-sync script rewrites every model's
priorityin~/.codex/opencodex-catalog.jsonandmodels_cache.jsondirectly, reproducing the intended full order. It must be re-run after everyocx sync,ocx servicerestart, and version upgrade, because catalog rebuild resets all routed priorities back to the flat default. This is brittle and easy to forget: an out-of-order restart silently reverts the picker.Additional context
ocx --version); running local service confirmed viaGET /healthz.