Загрузка 0
ПОДЕЛИТЬСЯ

Мой блог

Листай вниз

Настройка Codex CLI через свой эндпоинт: разбор файла config.toml и 9 популярных ошибок

Настройка Codex CLI через свой эндпоинт: разбор файла config.toml и 9 популярных ошибок

Ранее я подробно разбирал особенности маршрутизации и управления ключами в Claude Code. Инструмент Codex CLI устроен совершенно иначе. В нем не предусмотрена стандартная переменная окружения для простой подмены базового адреса API. Вместо этого вся конфигурация задается через файл config.toml. В нем содержится множеств полей, неверное заполнение которых ведет к неявным сбоям и молчаливому падению утилиты.

В этом материале я собрал готовый рабочий конфиг, а также наглядно продемонстрировал девять способов его сломать. Все тесты и ошибки я лично воспроизвел в изолированном окружении CODEX_HOME на версии Codex CLI 0.154. В примерах логов реальный домен прокси заменен на api.example.com.

Минимальный рабочий конфиг

Для подключения Codex CLI к собственному прокси или стороннему эндпоинту необходимо сформировать файл по адресу ~/.codex/config.toml со следующим содержимым:

Реклама
model = "gpt-5.4-mini"
model_provider = "myproxy"
model_reasoning_effort = "low"

[model_providers.myproxy]
name = "My proxy"
base_url = "https://api.example.com/v1"
env_key = "MYPROXY_API_KEY"
wire_api = "responses"

Далее в той же сессии командной строки, где планируется запуск CLI, экспортируем секретный ключ:

export MYPROXY_API_KEY=sk-...

Разбор назначений полей:

  • model — идентификатор модели в том виде, в котором его принимает ваш API-эндпоинт.
  • model_provider — наименование секции провайдера. Если опустить эту строку, Codex CLI по умолчанию отправит запрос на api.openai.com, даже если ниже детально описан блок провайдера.
  • model_reasoning_effort — глубина размышления модели перед генерацией ответа.
  • base_url — базовый URL, обязательно оканчивающийся на /v1. К этому пути Codex автоматически добавляет суффикс /responses.
  • env_key — имя переменной окружения, содержащей авторизационный токен (а не сам текст ключа).
  • wire_api — используемый сетевой протокол взаимодействия. В версии 0.154 поддерживается фиксированное значение, которое стоит указывать явно.

Проверить корректность выполненных настроек можно простой командой:

codex exec "Ответь одним словом: работает"

Если в консоли отображается односложный ответ и строка с количеством потраченных токенов (tokens used), интеграция выполнена успешно.

Девять способов сломать конфигурацию

1. Использование переменной OPENAI_BASE_URL

Разработчики, привыкшие к стандартному OpenAI SDK, часто пытаются переопределить эндпоинт привычным путем через переменные окружения:

OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.example.com/v1
codex exec "..."

В результате консоль выдает ошибку авторизации 401 Unauthorized со связкой с серверами api.openai.com. Переменная OPENAI_BASE_URL полностью игнорируется Codex CLI. Единственный рабочий способ перенаправить трафик — использование секции model_providers.

Реклама

2. Указание wire_api = “chat”

Если используемый прокси-сервер поддерживает исключительно классический роут /chat/completions, утилита отказывается работать. При запуске возникает ошибка вида:

Error loading config.toml: `wire_api = "chat"` is no longer supported.
How to fix: set `wire_api = "responses"` in your provider config.

Codex CLI принудительно требует поддержки спецификации /responses. Это делает несовместимыми многие устаревшие шлюзы и самописные прокси. Перед настройкой убедитесь, что ваш шлюз обрабатывает запросы к /v1/responses.

3. Опечатка в значении wire_api

При вводе некорректного значения (например, response вместо responses) CLI вернет ошибку распарсивания TOML:

Error loading config.toml: unknown variant `response`, expected `responses`

Подобные сообщения выводятся при любой ошибке в перечисляемых типах (enum), однако в других полях диагностика может оказаться менее очевидной.

4. Указание base_url без /v1

Если записать адрес сервера как base_url = "https://api.example.com", CLI прибавит к нему роут и попытается обратиться по адресу https://api.example.com/responses. Чаще всего веб-серверы возвращают по этому URL стандартную HTML-страницу ошибки 404:

ERROR: Reconnecting... 1/5
...
ERROR: Reconnecting... 5/5
ERROR: unexpected status 404 Not Found: <!DOCTYPE html>..., url: https://api.example.com/responses

После пяти неудачных попыток повторного соединения в терминал выведется исходный HTML-код. При поиске причин всегда проверяйте финальный URL в хвосте логирования. Наличие или отсутствие завершающего слэша (/v1/) на корректность работы не влияет.

5. Переменная с ключом не экспортирована

При отсутствии переменной окружения возникает ошибка:

ERROR: Missing environment variable: `MYPROXY_API_KEY`.

Распространенный сценарий: API-ключ прописан в локальном файле .env, но Codex CLI запущен в терминале без предварительного экспорта переменных. Параметр env_key считывает только переменные текущего процесса ОС.

6. Указание неизвестной модели

Если передать идентификатор модели, отсутствующий во встроенной базе утилиты (например, gpt-5-codex), появится предупреждение:

warning: Model metadata for `gpt-5-codex` not found. Defaulting to fallback metadata; this can degrade performance and cause issues.

В Codex CLI зашита таблица параметров известного модельного ряда (размеры контекста, поддержка reasoning, лимиты). Для незнакомого id применяются резервные настройки. Запрос уйдет на прокси, и если на стороне сервера такой модели нет, вернется ошибка эндпоинта.

7. Включение supports_websockets = true на прокси без WebSocket

При принудительном включении веб-сокетов на эндпоинте без их поддержки консоль зафиксирует ошибку подключения:

ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 426 Upgrade Required

После этого утилита автоматически переключится на протокол HTTPS и выполнит задачу. Однако на каждый шаг будет теряться время из-за рукопожатия WebSockets. Не включайте этот флаг без уверенности в поддержке протокола сервером.

8. Параметр requires_openai_auth = true

В некоторых руководствах рекомендуют добавлять данную строку для совместимости. В актуальной версии 0.154 при заданном env_key этот параметр никак не влияет на передачу ключа и заголовки. Строка не ломает процесс выполнения, но является избыточной.

9. Использование experimental_bearer_token

Вы можете прописать секретный токен напрямую в конфигурационном файле:

experimental_bearer_token = "sk-..."

Способ рабочий, но создающий серьезные риски безопасности. Файл ~/.codex/config.toml легко случайно закоммитить в репозиторий с dot-файлами или скопировать на другую машину. Безопаснее использовать env_key.

Совет: Если передан недействительный или обрезанный токен, прокси вернет статус 401 Unauthorized с указанием конечного URL .../v1/responses. Это самый простой метод убедиться, что сетевой запрос доходит до вашего сервера.

Сколько стоит слово «работает»: анализ расхода токенов

Для оценки реального расхода ресурсов я заново выполнил команду с флагом вывода JSON-структуры codex exec --json и проверил событие turn.completed:

{"usage":{"input_tokens":14809,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":66,"reasoning_output_tokens":57}}

Даже при элементарном запросе из одного слова входной контекст составил 14 809 токенов. Этот объем складывается из системного промпта, описания инструментов, доступных навыков (skills) и окружения рабочей среды. Из 66 токенов ответа 57 ушло на процесс рассуждения (reasoning) на уровне low.

В рамках длительной рабочей сессии итоговые затраты определяются не столько ценой модели за 1K токенов, сколько эффективностью кэширования этого массивного системного контекста.

При тестировании кэша выявился важный нюанс. Прямое обращение к эндпоинту через curl демонстирует корректное кэширование: повторный запрос считывает 7424 токена из кэша. Однако при продолжении сессии через codex exec resume --last параметр cached_input_tokens составил 0 при 15 306 входных токенах.

Проверить поведение кэширования на своем эндпоинте можно последовательными командами:

codex exec --json "Тест"
codex exec --json resume --last "Продолжение"

После этого достаточно сравнить значения cached_input_tokens в объектах turn.completed.

Итоговый чек-лист настройки

  • Значение model_provider строго совпадает с именем секции в конфиге.
  • Параметр base_url оканчивается на /v1.
  • В wire_api указано "responses", а сервер корректно обрабатывает роут /v1/responses.
  • Авторизация настроена через env_key, а переменная экспортирована в терминале.
  • Флаги supports_websockets и requires_openai_auth отключены или удалены.
  • Идентификатор модели проверен непосредственно на вашем API-эндпоинте.
  • После завершения правки выполнен тестовый запрос через codex exec --json для контроля поля usage.

Непокрытые сценарии

В рамках данного материала я не тестировал работу с профилями (флаг -p), подключение локальных моделей через параметр --oss, а также специфику поведения CLI в среде Windows. Если вы сталкивались с нюансами работы в этих сценариях, делитесь наблюдениями в комментариях.

Источник: habr.com

01.