Summary
databricks-codex no longer works with recent versions of the OpenAI Codex CLI (0.134.0+). Codex removed support for the legacy top-level profile = "..." selector and for reading [profiles.<name>] tables out of config.toml via --profile. Our config.toml patcher writes exactly the config shape Codex now rejects, so Codex refuses to start:
Error loading configuration: legacy `profile = "databricks-proxy"` config is no longer supported;
use `--profile databricks-proxy` with `databricks-proxy.config.toml` instead
This is a hard startup failure (Codex exits before doing anything), so any user on an up-to-date Codex CLI is fully blocked.
Repro
- Install a current Codex CLI (
>= 0.134.0).
- Run
databricks-codex (or databricks-agents codex).
- The patcher writes
profile = "databricks-proxy" + [profiles.databricks-proxy] into ~/.codex/config.toml, and Codex aborts with the error above.
Root cause
internal/codex/tomlconfig/tomlconfig.go patches ~/.codex/config.toml using the pre-0.134 profile model:
managedRootKeys = []string{"profile"} (tomlconfig.go:86) and patchRootKey(content, "profile", "\"databricks-proxy\"") (tomlconfig.go:107) write the top-level profile = "databricks-proxy" selector — now rejected outright.
buildProfileSection writes [profiles.databricks-proxy] (model_provider, model) into config.toml (tomlconfig.go:110-111,136-172). Even with the root profile key removed, --profile databricks-proxy no longer reads [profiles.*] from config.toml on new Codex, so the provider/model wiring would silently not apply.
What Codex changed (0.134.0+)
- The top-level
profile = "<name>" selector in config.toml is unsupported and errors.
--profile <name> no longer consumes [profiles.<name>] from config.toml. Instead Codex loads ~/.codex/config.toml, then overlays ~/.codex/<name>.config.toml.
- Migration per upstream: move per-profile settings into
~/.codex/<name>.config.toml, and remove the [profiles.<name>] table + profile = "<name>" selector from config.toml.
Refs: openai/codex#24076 (stop consuming legacy config profiles), openai/codex#24858 (legacy profile config errors instead of migrating/warning).
Proposed fix
Option A (recommended): configure the proxy as the top-level default provider — no profiles at all
Codex still supports selecting a default provider via the top-level model_provider key (unaffected by the profile deprecation — see config reference). We can drop the profile mechanism entirely and patch config.toml to:
model = "databricks-<...>"
model_provider = "databricks-proxy"
[model_providers.databricks-proxy]
name = "Databricks Proxy"
base_url = "http://127.0.0.1:<port>"
api_key = "databricks-proxy"
wire_api = "responses"
Concretely:
- Stop writing the root
profile key — drop "profile" from managedRootKeys and the patchRootKey call.
- Replace
[profiles.databricks-proxy] with top-level model_provider + model — write model_provider = "databricks-proxy" and model = "..." as managed root keys instead of a profile table. Keep [model_providers.databricks-proxy] and [otel] as-is.
- No
--profile injection needed — plain codex picks up the default provider directly.
Why this is preferred: it makes bare codex invocations route through the proxy with no argv injection. That's essential for the flows where we can't inject a flag — the hooks path ([features] hooks = true in config.toml; the user runs plain codex, which fires the SessionStart hook that spawns databricks-codex serve) and any daemon/detached spawn. Option B below can't cover those because the profile only activates when --profile is on the command line.
The trade-off: model_provider is a global default — we'd be pointing the user's default provider at the proxy while wrapped (the current restore-on-exit discipline already handles putting it back). Confirm this is acceptable vs. the scoping a profile gave.
Option B (fallback): per-profile overlay file + --profile injection
If we want to keep proxy config scoped to a named profile rather than flipping the global default:
- Stop writing the root
profile key.
- Move the profile body (
model_provider, model) into a wrapper-owned ~/.codex/databricks-proxy.config.toml overlay; keep [model_providers.databricks-proxy]/[otel] in config.toml.
- Inject
--profile databricks-proxy into the Codex child argv (wrapper mode via core.Run/CodexArgs and serve), unless the user passed their own --profile.
Limitation: does not fix the hooks/daemon-driven plain-codex path (no --profile there). If we go this route we'd need Option A's default-provider config in addition for those flows — which is why Option A alone is simpler and more complete.
Open questions / risks
- Version compat. Older Codex (
< 0.134.0) still accepts the old profile/[profiles.*] shape. Option A's top-level model_provider works on both old and new Codex, so a clean cut to Option A likely avoids any version branching — worth verifying against the oldest Codex we intend to support.
- Global-default scoping (Option A). Setting
model_provider at root changes the user's default provider for the duration of the wrapped session. The existing surgical patch/restore (or codex's patch-every-session model) must put the prior default back cleanly on exit.
- Restore semantics. Confirm the patcher's save-originals/restore logic correctly captures and restores a pre-existing root
model_provider/model (sentinel when absent), same discipline the current [profiles.*] patch uses.
- Update
internal/codex/tomlconfig/AGENTS.md, CLAUDE.md (codex config-patch description), and tests to match.
Integration
Folds into the unify epic (#196) work for databricks-codex. Should land on the feat/unity-agent-tooling integration branch.
Summary
databricks-codexno longer works with recent versions of the OpenAI Codex CLI (0.134.0+). Codex removed support for the legacy top-levelprofile = "..."selector and for reading[profiles.<name>]tables out ofconfig.tomlvia--profile. Ourconfig.tomlpatcher writes exactly the config shape Codex now rejects, so Codex refuses to start:This is a hard startup failure (Codex exits before doing anything), so any user on an up-to-date Codex CLI is fully blocked.
Repro
>= 0.134.0).databricks-codex(ordatabricks-agents codex).profile = "databricks-proxy"+[profiles.databricks-proxy]into~/.codex/config.toml, and Codex aborts with the error above.Root cause
internal/codex/tomlconfig/tomlconfig.gopatches~/.codex/config.tomlusing the pre-0.134 profile model:managedRootKeys = []string{"profile"}(tomlconfig.go:86) andpatchRootKey(content, "profile", "\"databricks-proxy\"")(tomlconfig.go:107) write the top-levelprofile = "databricks-proxy"selector — now rejected outright.buildProfileSectionwrites[profiles.databricks-proxy](model_provider,model) intoconfig.toml(tomlconfig.go:110-111,136-172). Even with the rootprofilekey removed,--profile databricks-proxyno longer reads[profiles.*]fromconfig.tomlon new Codex, so the provider/model wiring would silently not apply.What Codex changed (0.134.0+)
profile = "<name>"selector inconfig.tomlis unsupported and errors.--profile <name>no longer consumes[profiles.<name>]fromconfig.toml. Instead Codex loads~/.codex/config.toml, then overlays~/.codex/<name>.config.toml.~/.codex/<name>.config.toml, and remove the[profiles.<name>]table +profile = "<name>"selector fromconfig.toml.Refs: openai/codex#24076 (stop consuming legacy config profiles), openai/codex#24858 (legacy profile config errors instead of migrating/warning).
Proposed fix
Option A (recommended): configure the proxy as the top-level default provider — no profiles at all
Codex still supports selecting a default provider via the top-level
model_providerkey (unaffected by the profile deprecation — see config reference). We can drop the profile mechanism entirely and patchconfig.tomlto:Concretely:
profilekey — drop"profile"frommanagedRootKeysand thepatchRootKeycall.[profiles.databricks-proxy]with top-levelmodel_provider+model— writemodel_provider = "databricks-proxy"andmodel = "..."as managed root keys instead of a profile table. Keep[model_providers.databricks-proxy]and[otel]as-is.--profileinjection needed — plaincodexpicks up the default provider directly.Why this is preferred: it makes bare
codexinvocations route through the proxy with no argv injection. That's essential for the flows where we can't inject a flag — the hooks path ([features] hooks = trueinconfig.toml; the user runs plaincodex, which fires the SessionStart hook that spawnsdatabricks-codex serve) and any daemon/detached spawn. Option B below can't cover those because the profile only activates when--profileis on the command line.The trade-off:
model_provideris a global default — we'd be pointing the user's default provider at the proxy while wrapped (the current restore-on-exit discipline already handles putting it back). Confirm this is acceptable vs. the scoping a profile gave.Option B (fallback): per-profile overlay file +
--profileinjectionIf we want to keep proxy config scoped to a named profile rather than flipping the global default:
profilekey.model_provider,model) into a wrapper-owned~/.codex/databricks-proxy.config.tomloverlay; keep[model_providers.databricks-proxy]/[otel]inconfig.toml.--profile databricks-proxyinto the Codex child argv (wrapper mode viacore.Run/CodexArgsandserve), unless the user passed their own--profile.Limitation: does not fix the hooks/daemon-driven plain-
codexpath (no--profilethere). If we go this route we'd need Option A's default-provider config in addition for those flows — which is why Option A alone is simpler and more complete.Open questions / risks
< 0.134.0) still accepts the oldprofile/[profiles.*]shape. Option A's top-levelmodel_providerworks on both old and new Codex, so a clean cut to Option A likely avoids any version branching — worth verifying against the oldest Codex we intend to support.model_providerat root changes the user's default provider for the duration of the wrapped session. The existing surgical patch/restore (or codex's patch-every-session model) must put the prior default back cleanly on exit.model_provider/model(sentinel when absent), same discipline the current[profiles.*]patch uses.internal/codex/tomlconfig/AGENTS.md,CLAUDE.md(codex config-patch description), and tests to match.Integration
Folds into the unify epic (#196) work for
databricks-codex. Should land on thefeat/unity-agent-toolingintegration branch.