Codex CLI — консольный агент OpenAI для работы с кодом — в версии 0.154 требует явной настройки провайдера модели через файл ~/.codex/config.toml. Переменная OPENAI_BASE_URL, к которой привыкли пользователи OpenAI SDK, полностью игнорируется: Codex всё равно стучится на api.openai.com и возвращает 401 Unauthorized. Единственный способ перенаправить запросы на сторонний сервер — описать секцию model_providers.

Минимальный рабочий конфиг выглядит так: в секции [model_providers.myproxy] указываются name, base_url с суффиксом /v1, env_key с именем переменной окружения (не сам ключ) и wire_api = "responses". В основной части файла задаются model — идентификатор модели ровно так, как его понимает endpoint, model_provider — имя секции, и model_reasoning_effort — сколько модель думает перед ответом. Без строки model_provider Codex пойдёт в api.openai.com, даже если секция описана. Проверка подключения: codex exec "Ответь одним словом: работает" — в ответе должно быть одно слово и строка tokens used.

Поле конфигаНазначениеТипичная ошибка
modelID модели, как его понимает endpointНеизвестный ID — Codex подставляет fallback-метадату
model_providerИмя секции провайдераБез строки Codex идёт в api.openai.com
base_urlАдрес endpoint с /v1 на концеБез /v1 Codex стучится в /responses и получает HTML
env_keyИмя переменной окружения с ключомПеременная не экспортирована — ошибка Missing environment variable
wire_apiПротокол обменаwire_api = "chat" больше не поддерживается

Девять способов сломать конфиг. Первый: попытка использовать OPENAI_BASE_URL — переменная проигнорирована, в ошибке виден url api.openai.com. Второй: wire_api = "chat" — Codex не запустится вообще, endpoint обязан реализовывать /responses, что отсекает старые прокси и самописные шлюзы. Третий: опечатка в wire_api — сообщение об ошибке будет невнятным, как и за любую опечатку в enum-поле. Четвёртый: base_url без /v1 — Codex дописывает /responses и получает HTML главной страницы, пять попыток переподключения и мусор в терминале. Пятый: переменная с ключом не экспортирована — env_key читает окружение процесса, а не файлы.env. Шестой: модель, о которой Codex не знает — срабатывает fallback-метадата, запрос всё равно уйдёт на endpoint, но с запасными параметрами. Седьмой: supports_websockets = true на прокси без WebSocket — каждый ход начинается с неудачного рукопожатия 426 Upgrade Required, после чего Codex молча падает на HTTPS. Восьмой: requires_openai_auth = true — в 0.154 с заданным env_key строка ничего не меняет, но вводит в заблуждение. Девятый: experimental_bearer_token — ключ лежит открытым текстом в конфиге, который легко скопировать на новую машину или случайно закоммитить вместе с dotfiles.

Для подключения к стороннему endpoint нужна секция [model_providers.<имя>] с полями base_url, env_key и wire_api.

Практический вывод: перед правкой конфига проверьте, что ваш прокси отдаёт /v1/responses, а не только /chat/completions. Ключ передавайте через env_key — тот же результат, что и experimental_bearer_token, но без риска утечки. Если endpoint не заявляет WebSocket явно, не включайте supports_websockets. Диагностика большинства ошибок сводится к одному: смотреть на url в конце сообщения об ошибке — он показывает, куда именно ушёл запрос.

Контекст: Codex CLI — не единственный агент с собственным форматом конфига. Claude Code, например, использует переменные окружения для указания endpoint, а Codex выбрал TOML-файл с десятком полей. Такой подход даёт больше контроля, но и больше способов ошибиться: половина полей ломает подключение молча, без внятного сообщения. Для команд, которые разворачивают Codex за корпоративным прокси или в изолированной среде, это означает необходимость проверять конфиг на каждом обновлении версии — формат и допустимые значения полей меняются.