Skip to content

feat(codex): the gateway's model is in the picker, and titles go through the gateway - #918

Merged
badcuban merged 3 commits into
mainfrom
feat/codex-gateway-model
Nov 14, 2026
Merged

badcuban merged 3 commits into
mainfrom
feat/codex-gateway-model

Conversation

@badcuban

@badcuban badcuban commented Nov 14, 2026 •

Copy link
Copy Markdown
Collaborator

When Codex runs on a gateway (its config's model_provider is not OpenAI), the model picker offered only OpenAI's models and started new threads on one the gateway may not serve. Titles and commit messages written by Codex also went to OpenAI: those one-shot codex exec runs leave out the user's config on purpose, so that their MCP servers and notify hooks don't fire for a title, and the gateway went with it.

What changed

  • The gateway's model is in the picker. The status check reads Codex's config when the default provider is not OpenAI. The model it names is in the list as the one default, shown once even when the user had added it by hand.
  • Titles and commit messages go through the gateway. A run on a gateway gets a Codex home of its own: a folder only its owner can open, holding a config with the provider alone, removed when the run ends. Nothing from the provider's definition is a process argument. The home stands in for --ignore-user-config: it has no user config to ignore.
  • Errors lose the gateway's secrets. Codex's error output can repeat a failed request's address. The provider's token, headers, query values and address password are struck from the error before it is logged or shown.
  • A refused model gets one more try on the model from Codex's config, since the built-in pick for titles is an OpenAI model.
  • A run never guesses at startup. With no recent answer about the provider, a run waits five seconds for the instance's first status check, then asks Codex itself (two reads of its own config). A remembered gateway survives a check that could not ask Codex, lapses after 15 minutes unconfirmed, and is forgotten at once when Codex says it is on OpenAI.

Where a run stays on OpenAI, as before

  • A provider that signs in with what Codex's own home stores: requires_openai_auth, a gateway's OAuth, Amazon Bedrock or Google Cloud. A home made for one run has no sign-in. (A provider built into Codex runs in Codex's own home, named by its id.)
  • A Codex agent answering on the side in a room (locked-down home, borrowed ChatGPT sign-in). Not part of this PR.

History of the design

The first commit passed the definition as -c overrides with a name-based secret filter. The security review flagged that a credential under an unlisted name (query_params.code) still reached the process list. The second commit replaces that channel with the private home; the third covers what a home of its own loses.

Checked

  • vp fmt, vp lint, vp run typecheck, full unit suite, browser suite (one unrelated chat timeline spec failed under load and passes alone).
  • Live on Codex 0.169 against a stand-in gateway that logs requests: a chat on the gateway's model; a title through the gateway with a literal token, a literal header and a key in a query parameter all applied (also when the gateway refuses the default title model); no MCP server or notify hook started by the title run; no secret in the server log or the status cache; no temp home left behind.
  • Not tested live: a real gateway, a built-in non-OpenAI provider, the Windows path, and the direct question to Codex when the first check is slow.

@vercel

vercel Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadlines Ready Ready Preview Nov 14, 2026 7:47pm UTC

Request Review

…ugh the gateway

When Codex runs on a gateway (its config's `model_provider` is not OpenAI),
the model picker offered only OpenAI's models and started new threads on one
the gateway may not serve, and titles and commit messages written by Codex
went to OpenAI: those one-shot `codex exec` runs leave out the user's config
on purpose (so their MCP servers and notify hooks don't fire for a title),
and the gateway went with it.

- The status check reads Codex's config when the default provider is not
  OpenAI. The model it names is in the model list as the one default, shown
  once even when the user had added it by hand.
- One-shot runs are handed the gateway alone as `-c` overrides, beside
  `--ignore-user-config`. A plain token or header in the provider's
  definition travels in the run's environment (through `env_key` and
  `env_http_headers`), never in its arguments.
- No routing where it can't be done safely, which leaves the run on OpenAI as
  before: a secret only arguments could carry (a credential in the address or
  `query_params`, or among the `auth` command's arguments), and a Codex that
  starts through cmd.exe, where the settings' quotes could act as commands.
- A run the gateway refuses for its model is tried once more on the config's
  model: the built-in pick for titles is an OpenAI model.
- A run asked for before the instance's first status check ends waits for it,
  up to 20 seconds. A remembered gateway survives a check that could not ask
  Codex, lapses after 15 minutes unconfirmed, and is forgotten at once when
  Codex says it is on OpenAI.

Not included: a Codex agent answering on the side in a room still runs on
OpenAI with the borrowed ChatGPT sign-in.
…e, never as arguments

The gateway's definition went to `codex exec` as `-c` overrides, with a
name-based filter for what looked like a secret. A credential under a name the
filter did not know (an Azure Functions `code` key in `query_params`) still
ended up in the process list.

A run on a gateway now gets a Codex home of its own: a folder only its owner
can open, holding a config with the provider alone, removed when the run ends.
Nothing from the definition is an argument, so there is nothing to filter, no
variable names to invent, and nothing for cmd.exe to misread. The home stands
in for --ignore-user-config: it has no user config to ignore.

A home made for one run has no sign-in, so a provider that signs in with what
Codex's own home stores (`requires_openai_auth`, a gateway's OAuth) gets no
routing and its runs stay on OpenAI, as before.
…teway's secrets, and a slow start asks Codex

Follow-ups to running one-shot Codex runs on a gateway from a home of their own.

- A provider Codex has built in has no definition to hand over and may sign
  in with what Codex's own home stores: it runs there, named by its id beside
  --ignore-user-config. Amazon Bedrock and Google Cloud providers, whose
  credentials Codex keeps in its home too, get no routing, like the ones that
  need a ChatGPT sign-in or a gateway's OAuth.
- Codex's error output can repeat the address of a failed request, and with
  it a key the address carries. The provider's token, headers, query values
  and address password are struck from the error before it is logged or shown.
- A run that finds no recent answer about the provider no longer goes to
  OpenAI after waiting out the first status check: it waits five seconds for
  that check, then asks Codex itself (two reads of its own config, none of a
  status check's calls to OpenAI).
- The sweep of leftover temp homes runs before the first gateway home is made,
  so one a killed server left does not wait for a room side answer to clear it.
@badcuban
badcuban force-pushed the feat/codex-gateway-model branch from 1905dcf to 93177c1 Compare November 14, 2026 19:47
@badcuban
badcuban added this pull request to the merge queue Nov 14, 2026
Merged via the queue into main with commit 6433d76 Nov 14, 2026
24 checks passed
@badcuban
badcuban deleted the feat/codex-gateway-model branch November 14, 2026 19:58

This branch was successfully deployed

1 active deployment
Preview — 93177c14 Deployed Nov 14, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant