Feature request: managed, enforceable allowlist of selectable models
What variant of Codex are you using?
CLI
What feature would you like to see?
What feature would you like to see?
A first-class, managed/enforceable allowlist of selectable models — a config
key that constrains which models a user may use, composes with Codex's existing
config-layering precedence, and cannot be widened by lower-priority layers.
Problem
There is currently no supported way to restrict which models a user can select.
Organizations that standardize on a specific model (or a small approved set) need
to guarantee every session uses an approved model regardless of what a user types,
picks in the picker, or sets in their own config.toml. The defining requirement
is enforcement: a forced default is not enough, because a user can still
switch models mid-session via the picker or /model.
Every existing model-related key falls short for this:
| Mechanism | Why it doesn't solve restriction |
|---|---|
| model (default) | Only sets the starting model; the user can still switch to any other model. Not enforcement. |
| Global policy model (cloud settings/policies) | Same limitation (a default, not a ceiling) — and per #24032 it is currently ignored by the CLI/app anyway. |
| model_provider / model_providers | Restricts the provider, not the model; a provider can expose many models. |
| model_catalog_json | Comes closest — a custom catalog replaces the built-in list, so a single-entry catalog does restrict the picker — but it requires authoring a complete model descriptor (every required field, including the full base_instructions system prompt) for each allowed model, kept byte-accurate against the bundled catalog and re-synced on every upgrade. It's a model-definition mechanism being misused for model-restriction. |
| Managed config (requirements.toml) | Can enforce approval policies, sandbox modes, permission profiles, web-search, network, feature flags, MCP allowlists, auto-review, command rules, hooks — but has no key for models. |
So there's an enforcement layer (requirements.toml) and a list-shaping
mechanism (model_catalog_json), but nothing that simply says *"restrict the
selectable models to this allowlist"* without redefining the models themselves.
Proposed solution
A key that takes a list of model slugs (the same identifiers the model key
already accepts), enforceable through the managed/requirements layer:
# Only these slugs are selectable — in the picker, via /model, and via the
# `model` key / `-c model=`. Selecting/defaulting outside the list is rejected
# with a clear error rather than silently falling back.
allowed_models = ["gpt-5.4"]
No full model descriptors — just slugs — so admins never reproducebase_instructions and it never drifts against the bundled catalog across
upgrades.
Layered behavior (the key part)
Slot into the documented precedence (user → profile → project → CLI → managed)
so it works across layers:
- Defaults layer (
managed_config.toml): sets a starting allowlist; lower
layers may narrow it.
- Enforcement layer (
requirements.toml): a hard ceiling. Lower layers may
narrow (intersect) but never widen. A user/project config naming a
model outside the enforced set has it filtered out, not honored.
- Effective set = intersection of every layer that specifies one. E.g. an
org enforces ["gpt-5.4", "gpt-5.5"]; a sensitive repo's project config
narrows to ["gpt-5.4"]; neither can escape an enforced constraint above it.
- Treat an enforced
allowed_modelsas a protected key (like
model_provider) that project-local .codex/config.toml cannot widen.
- Apply uniformly to the **picker,
/model, themodelkey, and-c
overrides** — and to exec/non-interactive paths, not just the picker.
Edge cases
- Empty intersection → fail with a clear error rather than silently allowing all.
- Unknown slug in the allowlist → warn and skip (degrade gracefully across
versions) but never expand availability.
- Disallowed models shouldn't appear in the picker at all.
- Surface the active constraint (e.g. in
codex doctor) so users understand why
a model is unavailable.
Alternatives considered
- Forcing a single default
model— insufficient; users can switch. - Restrictive
model_catalog_json— works mechanically but requires maintaining
full model descriptors (incl. system prompts) and re-syncing every upgrade.
- Per-provider filtering — too coarse; a provider may expose many models.
Additional information
Searched existing open issues before filing; nearest neighbors but no duplicate:
- #21594 —
model_aliasesmapping for gateway model names (naming/aliasing, not restriction). - #16248 — allow
[otel]via cloud-managed defaults (establishes the managed-defaults pattern, but for telemetry, not models). - #24032 — global-policy
modelis ignored by the app (a default-model bug;
reinforces that a default isn't enforcement and that the model field needs
managed-layer support that actually works).
- #19694 / #26308 —
model_catalog_jsonpicker/project-scope bugs (related to the workaround's fragility, not the feature itself).
Happy to refine the exact key name (allowed_models vs. e.g.model_allowlist / permitted_models) to match existing conventions.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗