Мост Factory Droid
Factory Droid — среда выполнения агента, а не документированный эндпоинт инференса, совместимый с OpenAI. Если пользовательский провайдер, направленный на внутренний URL Factory LLM, возвращает 403 Forbidden, одна лишь смена адаптера opencodex или добавление заголовков провайдера не превращает этот частный маршрут в поддерживаемый публичный API.
Рабочая интеграция выглядит так:
Text-only Responses client -> opencodex (http://127.0.0.1:10100/v1/responses) -> local Responses bridge (http://127.0.0.1:11435/v1/responses) -> official droid exec command -> Factory account and selected modelУчётные данные Factory при этом остаются в официальном клиенте Droid. OpenCodex получает отдельный токен моста, действующий только локально.
Что не сработало и почему
Заголовок раздела «Что не сработало и почему»| Симптом | Причина | Исправление |
|---|---|---|
403 Forbidden от URL Factory LLM |
URL не является документированным универсальным эндпоинтом OpenAI для сторонних клиентов | Вызывайте Factory через официальный CLI или SDK Droid |
404 по адресу /models/models |
Базовый URL провайдера уже заканчивался на /models |
Используйте корень API как baseUrl; не добавляйте путь обнаружения |
| Не работает поиск моделей | Мост не предоставляет полный актуальный каталог | Установите liveModels: false и задайте статический список models |
| Loopback-провайдер отклонён | Доступ к частной сети запрещён по умолчанию | Задавайте allowPrivateNetwork: true только для loopback-моста |
Не разрешается ${DROID_BRIDGE_TOKEN} |
Переменная отсутствует в окружении службы opencodex | Передайте её процессу службы, а не только интерактивной оболочке |
OutputTextDelta without active item |
Мост отправил текстовый фрагмент до открытия выходного элемента и части содержимого | Отправляйте полный жизненный цикл Responses SSE в правильном порядке |
Поэтому те же учётные данные Factory могут работать с droid exec, тогда как прямой запрос к недокументированному URL LLM возвращает 403. Эти результаты проверяют разные продукты и не противоречат друг другу.
Предварительные условия
Заголовок раздела «Предварительные условия»-
Установите Droid CLI и войдите в аккаунт.
-
Убедитесь, что ограниченный запрос без интерфейса работает:
Terminal window droid exec --model glm-5.2 --output-format json "Reply with DROID_OK only." -
Запустите локальный мост, вызывающий
droid exec(или официальный Droid SDK) и предоставляющий:GET /healthzGET /v1/modelsPOST /v1/responses
Factory документирует droid exec как интерфейс для неинтерактивной автоматизации и рекомендует вывод JSON для скриптов. Для более длительной интеграции Factory также описывает потоковый JSON-RPC и официальные SDK для TypeScript и Python в руководстве Droid Exec.
Контракт моста
Заголовок раздела «Контракт моста»Привяжите мост к 127.0.0.1, требуйте случайно сгенерированный bearer-токен, ограничьте размер запросов и используйте список разрешённых ID моделей. Минимальный мост принимает лишь следующие формы input в Responses:
- непустую строку; или
- массив, содержащий только элементы
message. Каждое сообщение должно иметь рольuser,developer,systemилиassistant, а его содержимое должно быть строкой либо состоять только из текстовых частей (input_textдля входных ролей иoutput_textдля истории ассистента).
Проверяйте весь запрос до вызова Droid. Если часть входа является изображением или файлом, tools содержит любое определение инструмента либо input содержит вызов инструмента или результат (function_call, function_call_output, custom_tool_call или custom_tool_call_output), верните HTTP 400 с ошибкой invalid_request_error в формате Responses. Используйте стабильный код моста, например unsupported_bridge_input, и укажите в сообщении отклонённое поле. Сделайте это до запуска SSE, даже при stream: true; никогда не отбрасывайте неподдерживаемое содержимое и не превращайте его в строку или плоский текст промпта.
{ "error": { "type": "invalid_request_error", "code": "unsupported_bridge_input", "param": "tools", "message": "The minimal Droid bridge does not accept tool definitions." }}Для принятого запроса мост должен:
- преобразовать принятый Responses
inputв промпт; - вызвать
droid exec --model <id> --output-format json <prompt>; - разобрать итоговые
resultиsession_id; - вернуть оболочку OpenAI Responses; и
- сопоставить
previous_response_idс ID сессии Droid, когда нужно продолжение.
Для потоковых ответов отправляйте события в таком порядке:
response.createdresponse.output_item.addedresponse.content_part.addedresponse.output_text.deltaresponse.output_text.doneresponse.content_part.doneresponse.output_item.doneresponse.completedНе открывайте мост на 0.0.0.0 и не используйте учётные данные Factory повторно как bearer-токен моста.
Конфигурация провайдера OpenCodex
Заголовок раздела «Конфигурация провайдера OpenCodex»Создайте пользовательского провайдера с явным ID droid:
ocx provider add droid \ --adapter openai-responses \ --base-url http://127.0.0.1:11435/v1 \ --default-model glm-5.2 \ --allow-private-networkКоманда создаёт запись конфигурации providers.droid. В дашборде откройте Providers → droid → Edit
JSON и замените значение этого провайдера на:
{ "adapter": "openai-responses", "baseUrl": "http://127.0.0.1:11435/v1", "responsesPath": "/responses", "allowPrivateNetwork": true, "authMode": "key", "apiKey": "${DROID_BRIDGE_TOKEN}", "liveModels": false, "models": ["glm-5.2", "glm-5.2-fast", "kimi-k3"], "defaultModel": "glm-5.2"}ID моделей приведены для примера. Оставьте только модели, доступные через droid exec для аккаунта Factory, в который выполнен вход. Не добавляйте этому провайдеру заголовки вывода, специфичные для Factory: его вышестоящий сервер — локальный мост, а не HTTP-эндпоинт Factory.
После сохранения провайдера или изменения статического каталога синхронизируйте и перезапустите Codex, чтобы новые сессии прочитали обновлённый каталог:
ocx sync --restart-codexocx doctor--restart-codex перезапускает подходящие app-server и полностью закрывает и заново открывает настольное приложение Codex, завершая активные беседы. Используйте --restart-app-server-only, чтобы оставить настольное приложение работающим. Перезапускайте только после завершения или сохранения этих сессий.
Проверка полного маршрута
Заголовок раздела «Проверка полного маршрута»Проверяйте каждую границу отдельно:
curl -fsS http://127.0.0.1:11435/healthzocx doctorocx access test droid/glm-5.2 --protocol responsesСтрока провайдера или запись в списке выбора модели доказывает только видимость в каталоге. Интеграция работает лишь тогда, когда проверочный запрос Responses возвращается через маршрут droid/<model>.
Текущее ограничение
Заголовок раздела «Текущее ограничение»Описанный минимальный мост переводит текст и жизненный цикл Responses SSE. Он не реализует полный двусторонний протокол вызовов функций и инструментов Codex. Codex App и codex exec обычно отправляют определения инструментов, даже если в промпте сказано не вызывать инструменты, а в текущем CLI Codex нет общего флага для их удаления. Минимальный мост должен отклонять такие запросы по описанному выше контракту 400. Для определений, вызовов и результатов инструментов, разрешений, отмены и расширенных событий Droid нужен мост с состоянием на основе потокового JSON-RPC Factory или официального Droid SDK. Успех ocx access test подтверждает текстовый маршрут, а не работу агента Codex или маршрута инструментов.

