СейчасЧто такое codex app-server
- Что такое codex app-server
- Что выбрать: SDK, exec, MCP или app-server
- Запуск и транспорты
- Протокол и схема сообщений
- Жизненный цикл: инициализация, потоки, ходы
- Карта методов
- События и ошибки
- Подтверждения и sandbox
- Удалённый доступ и авторизация
- Полезные сценарии
- «Спросить Codex» прямо внутри своего продукта
- Codex остаётся дома, вы работаете с ноутбука
- Обновление Codex CLI без сюрпризов
- Проверка результата
- Ограничения и когда не подходит
- Официальные источники
- Следующий шаг
- Связанные материалы
Практическое руководство по codex app-server: двунаправленному JSON-RPC интерфейсу, через который расширение Codex для VS Code и другие клиенты управляют агентом. Разберём запуск и транспорты, инициализацию, работу с потоками и ходами, подтверждения действий и безопасный удалённый доступ.
Содержание
- Что такое codex app-server
- Что выбрать: SDK, exec, MCP или app-server
- Запуск и транспорты
- Протокол и схема сообщений
- Жизненный цикл: инициализация, потоки, ходы
- Карта методов
- События и ошибки
- Подтверждения и sandbox
- Удалённый доступ и авторизация
- Полезные сценарии
- Проверка результата
- Ограничения и когда не подходит
- Официальные источники
Что такое codex app-server
codex app-server — подкоманда Codex CLI, которая поднимает сервер с двунаправленным протоколом JSON-RPC 2.0 (формат удалённого вызова процедур поверх JSON). Через него клиент получает возможности полноценного интерфейса Codex: аутентификацию, историю диалогов, потоковые события агента, выполнение команд в sandbox и подтверждения действий.
Именно этот протокол использует расширение Codex для VS Code, поэтому app-server подходит для собственных IDE-интеграций, веб-приложений и десктопных клиентов. Реализация открыта: каталог codex-rs/app-server в репозитории openai/codex.
Язык клиента не ограничен: достаточно читать и писать по одному JSON-сообщению в строке. Подойдут TypeScript, Python, Go, Rust и другие языки.
Что выбрать: SDK, exec, MCP или app-server
| Инструмент | Задача | Причина выбора |
| Codex SDK | Автоматизация задач, CI, скрипты | Проще и стабильнее, без ручной работы с протоколом |
| codex exec | Разовый неинтерактивный запуск из терминала | Не нужен сервер и постоянное соединение |
| Codex как MCP server | Отдать инструменты Codex другому агенту | Стандартный протокол MCP |
| codex app-server | Свой клиент с историей, стримингом и подтверждениями | Полный доступ к harness Codex: тот же протокол, что у VS Code extension |
Запуск и транспорты
npm install -g @openai/codex
# stdio (по умолчанию): одна строка = одно JSON-сообщение
codex app-server
# WebSocket на loopback-интерфейсе
codex app-server --listen ws://127.0.0.1:4500
# Unix-сокет по умолчанию
codex app-server --listen unix://| Транспорт | Флаг | Формат и статус |
| stdio | --listen stdio:// | JSONL по stdin/stdout; режим по умолчанию для дочерних процессов |
| WebSocket | --listen ws://IP:PORT | Одно сообщение на текстовый фрейм; experimental, для production не поддерживается |
| Unix socket | --listen unix:// или unix://PATH | WebSocket-подключение через сокет с HTTP Upgrade |
| off | --listen off | Локальный транспорт не открывается |
WebSocket-листенер дополнительно отвечает на HTTP-проверки: GET /readyz возвращает 200 OK, когда сервер принимает соединения; GET /healthz возвращает 200 OK для запросов без заголовка Origin, а запросы с Origin отклоняются с 403 Forbidden.
Протокол и схема сообщений
Как и MCP, app-server работает поверх JSON-RPC 2.0, но заголовок "jsonrpc": "2.0" на проводе опускается.
Запрос содержит method, params и id:
{ "method": "thread/start", "id": 10, "params": { "model": "gpt-5.4" } }Ответ повторяет id и содержит result или error:
{ "id": 10, "result": { "thread": { "id": "thr_123" } } }Уведомление идёт без id:
{ "method": "turn/started", "params": { "turn": { "id": "turn_456" } } }Схему сообщений не нужно переписывать вручную: CLI генерирует TypeScript-типы или JSON Schema из вашей установленной версии, и артефакты гарантированно ей соответствуют.
codex app-server generate-ts --out ./schemas
codex app-server generate-json-schema --out ./schemasmodel/list, не зашивая конкретные идентификаторы в код клиента.Жизненный цикл: инициализация, потоки, ходы
Протокол строится на трёх примитивах:
- поток (thread) — диалог пользователя с агентом, состоит из ходов;
- ход (turn) — один запрос пользователя и работа агента по нему;
- элемент (item) — единица ввода или вывода: сообщение, запуск команды, правка файла, вызов инструмента.
Порядок работы соединения:
- Клиент отправляет
initializeсclientInfo(имя, заголовок, версия клиента) и ждёт ответ. - Клиент отправляет уведомление
initialized. До этого рукопожатия сервер отвечает ошибкойNot initialized, повторныйinitializeна том же соединении даётAlready initialized. - Клиент открывает диалог:
thread/startдля нового,thread/resumeдля продолжения по сохранённому id,thread/forkдля ветвления истории. - Клиент запускает ход:
turn/startсthreadIdи входными элементами (текст, изображение по URL или локальный файл). - Во время хода клиент читает поток уведомлений:
item/started, дельты текста,item/completed. Добавить реплику в активный ход можно черезturn/steer, остановить — черезturn/interrupt. - Ход завершается уведомлением
turn/completedсо статусомcompleted,interruptedилиfailed.
В initialize.params.capabilities клиент может подписаться на экспериментальные методы (experimentalApi: true) и отключить ненужные уведомления по точным именам (optOutNotificationMethods).
experimentalApi сервер отклоняет экспериментальные методы и поля ошибкой вида <descriptor> requires experimentalApi capability. Опт-ин фиксируется один раз на всё время жизни соединения.Карта методов
| Группа | Основные методы |
| Потоки | thread/start, thread/resume, thread/fork, thread/read, thread/list, thread/archive, thread/unarchive, thread/delete, thread/compact/start, thread/goal/set |
| Ходы | turn/start, turn/steer, turn/interrupt, review/start |
| Команды и процессы | command/exec с write/resize/terminate; process/* — experimental, вне sandbox |
| Модели и флаги | model/list, experimentalFeature/list, permissionProfile/list |
| Конфигурация | config/read, config/value/write, config/batchWrite, configRequirements/read |
| Файлы | fs/readFile, fs/writeFile, fs/readDirectory, fs/watch и другие методы fs/* |
| Навыки и плагины | skills/list, skills/config/write, marketplace/*; plugin/list, plugin/install и соседние пока в разработке |
| Приложения (коннекторы) | app/list, вызов через маркер $demo-app в тексте ввода и элемент mention с путём app://demo-app |
| Аккаунт | account/read, account/login/start (API key, ChatGPT browser flow, device code), account/logout, account/rateLimits/read, account/usage/read |
События и ошибки
После старта или возобновления потока клиент постоянно читает уведомления транспорта. Ключевые:
thread/started,thread/archived,thread/closed,thread/status/changed— жизненный цикл диалога;turn/started,turn/completed,turn/diff/updated,turn/plan/updated— ход работы;item/startedиitem/completed— начало и финал каждого элемента; финальное состояние элемента берите изitem/completed;item/agentMessage/delta,item/reasoning/summaryTextDelta,item/commandExecution/outputDelta— потоковые дельты текста, рассуждений и вывода команд;thread/tokenUsage/updated— расход токенов по активному потоку.
При сбое хода сервер отправляет error с полем codexErrorInfo и завершает ход статусом failed. Типичные значения: ContextWindowExceeded, UsageLimitExceeded, HttpConnectionFailed, ResponseStreamDisconnected, SandboxError. Если доступен HTTP-статус от вышестоящего сервиса, он приходит в httpStatusCode.
Отдельный случай — перегрузка. При заполнении входящей очереди сервер отклоняет новые запросы кодом -32001 и сообщением Server overloaded; retry later. Клиенту следует повторять запрос с экспоненциальной задержкой и джиттером.
Подтверждения и sandbox
В зависимости от настроек пользователя выполнение команд и правка файлов могут требовать подтверждения. Сервер отправляет клиенту запрос, клиент отвечает решением.
Порядок сообщений для команды:
item/startedс элементомcommandExecution.- Запрос
item/commandExecution/requestApprovalсitemId,threadId,turnIdи деталями команды. - Ответ клиента:
accept,acceptForSession,declineилиcancel; для команд есть ещё вариантacceptWithExecpolicyAmendment: принять команду и заодно дописать правило в политику execpolicy. serverRequest/resolvedфиксирует, что запрос закрыт.item/completedс финальным статусомcompleted,failedилиdeclined.
Для правок файлов схема та же: item/fileChange/requestApproval и те же решения. Если в запросе есть networkApprovalContext, это запрос сетевого доступа к конкретному хосту и протоколу: показывайте сетевой диалог, а не превью shell-команды.
Политика изоляции задаётся в sandboxPolicy при старте потока или хода: readOnly, workspaceWrite с явными writableRoots, externalSandbox (если изоляцию уже обеспечивает ваш контур) или dangerFullAccess. Политика подтверждений — в approvalPolicy.
thread/shellCommand выполняется вне sandbox с полным доступом и не наследует политику потока. Показывайте его в клиенте только для явно инициированных пользователем команд. То же относится к экспериментальному process/*.Встроенный инструмент request_permissions приходит запросом item/permissions/requestApproval. В ответе передавайте только запрошенное подмножество прав и явно выбирайте область действия: scope: "turn" на ход или "session" на сессию.
Удалённый доступ и авторизация
App-server можно запустить на одной машине, а терминальный интерфейс Codex подключить с другой:
# на хосте
codex app-server --listen ws://127.0.0.1:4500
# на клиенте
codex --remote ws://127.0.0.1:4500Опция --remote принимает endpoint ws://, wss:// и unix://. Для небезопасного канала держите листенер на loopback или пробрасывайте порт по SSH. Для удалённого соединения включите авторизацию и TLS, а токен передавайте через переменную окружения:
export CODEX_REMOTE_TOKEN="$(cat "$HOME/.codex/app-server-token")"
codex --remote wss://remote-host:4500 \
--remote-auth-token-env CODEX_REMOTE_TOKEN--ws-auth: capability-token с --ws-token-file или --ws-token-sha256, либо signed-bearer-token с --ws-shared-secret-file. Не передавайте сырой токен аргументом командной строки.Полезные сценарии
«Спросить Codex» прямо внутри своего продукта
Задача: у команды есть свой рабочий инструмент (админка, редактор, внутренний портал), и хочется, чтобы сотрудник мог задать вопрос Codex, не выходя из него: с историей диалога, живой печатью ответа и кнопками «разрешить/отклонить» для действий агента.
Условия: установленный Codex CLI на машине, где работает сервис, и немного кода на любом языке: протоколу достаточно чтения и записи JSON построчно.
Что делать: сервис запускает codex app-server как дочерний процесс, проходит рукопожатие initialize и initialized, открывает поток через thread/start и отправляет вопрос пользователя через turn/start. Ответ агента приходит дельтами item/agentMessage/delta и сразу показывается в интерфейсе. Когда агент просит разрешения на команду или правку, интерфейс получает обычный запрос и отвечает решением пользователя.
Минимальный клиент на Node.js выглядит так:
import { spawn } from "node:child_process";
import readline from "node:readline";
const proc = spawn("codex", ["app-server"], {
stdio: ["pipe", "pipe", "inherit"],
});
const rl = readline.createInterface({ input: proc.stdout });
const send = (message: unknown) => {
proc.stdin.write(`${JSON.stringify(message)}\n`);
};
let threadId: string | null = null;
rl.on("line", (line) => {
const msg = JSON.parse(line);
if (msg.id === 1 && msg.result?.thread?.id && !threadId) {
threadId = msg.result.thread.id;
send({
method: "turn/start",
id: 2,
params: {
threadId,
input: [{ type: "text", text: "Summarize this repo." }],
},
});
}
});
send({
method: "initialize",
id: 0,
params: {
clientInfo: { name: "my_product", title: "My Product", version: "0.1.0" },
},
});
send({ method: "initialized", params: {} });
send({ method: "thread/start", id: 1, params: { model: "gpt-5.4" } });Наблюдаемый результат: пользователь видит, как ответ печатается по мере генерации; финал — уведомление turn/completed со статусом completed, а собранный текст берётся из item/completed.
Ограничение: один initialize на соединение; экспериментальные методы требуют capabilities.experimentalApi при инициализации.
Codex остаётся дома, вы работаете с ноутбука
Задача: проекты и настроенный Codex живут на стационарном компьютере, например на домашнем Mac mini, а вы уехали с ноутбуком и хотите продолжить работу в привычном терминальном интерфейсе.
Что делать: на домашней машине запустите codex app-server --listen ws://127.0.0.1:4500 и пробросьте порт по SSH. На ноутбуке подключитесь командой codex --remote ws://127.0.0.1:4500. Токен храните в файле и передавайте через переменную окружения, как показано в разделе про удалённый доступ.
Наблюдаемый результат: терминал на ноутбуке выглядит как обычный Codex, но команды выполняются на домашней машине; curl -sf http://127.0.0.1:4500/readyz отвечает 200 OK.
Ограничение: WebSocket-транспорт экспериментальный; без --ws-auth и TLS такой доступ наружу не выставляют.
Обновление Codex CLI без сюрпризов
Задача: вы обновили Codex CLI и хотите заранее узнать, не сломала ли новая версия вашу интеграцию.
Что делать: после каждого обновления выполните codex app-server generate-ts --out ./schemas (или generate-json-schema для других языков) и соберите клиент заново.
Наблюдаемый результат: все расхождения между клиентом и новой версией протокола всплывают сразу на этапе сборки, до выкладки.
Ограничение: схема соответствует только той версии CLI, из которой её сгенерировали, поэтому сгенерированные файлы логично хранить рядом с кодом клиента.
Проверка результата
Минимальный рабочий сценарий для проверки интеграции:
- Запустите
codex app-server --listen ws://127.0.0.1:4500. - Выполните
curl -sf http://127.0.0.1:4500/readyz: ответ 200 OK подтверждает, что листенер принимает соединения. - Отправьте
initialize, дождитесь ответа с user-agent сервера, отправьтеinitialized. - Выполните
thread/start, затемturn/startс простым текстовым запросом. - Признак успеха: поток
item/*уведомлений и финальныйturn/completedсо статусомcompleted. ОшибкаNot initializedозначает нарушенный порядок рукопожатия.
Ограничения и когда не подходит
- Команда app-server и WebSocket-транспорт официально экспериментальные и не поддерживаются для production-нагрузок.
- Для CI и прямой автоматизации документация рекомендует Codex SDK: протокол app-server шире и нужен именно для богатых клиентских интеграций.
- Методы
plugin/list,plugin/read,plugin/installиplugin/uninstallпомечены как находящиеся в разработке; из production-клиентов их вызывать не стоит. thread/rollbackи уведомлениеitem/fileChange/outputDeltaобъявлены устаревшими; для правок используйте элементыfileChangeиturn/diff/updated.- При перегрузке ждите
-32001и повторяйте запросы с экспоненциальной задержкой и джиттером.
Это руководство основано на официальной документации OpenAI и README app-server, а не на прогоне каждого метода локально. Поведение экспериментальных флагов сверяйте со своей версией CLI.
Официальные источники
- Документация Codex App Server
- README и исходники: openai/codex, каталог codex-rs/app-server
- Справочник команд Codex CLI
- Статья OpenAI об архитектуре App Server
Следующий шаг
Если ваша задача — не собственный клиент, а запуск задач Codex из терминала и скриптов, продолжите здесь:
codex exec — как выполнять конкретные задачи Codex из терминала и скриптов
Связанные материалы
- Статья: Codex становится платформой: агент должен жить там, где уже идёт работа
- Блог: OpenAI выложил Symphony — и теперь ваш трекер задач может стать оркестратором кодящих агентов
- База знаний: Codex App — единый справочник по среде от OpenAI
App-server открывает дорогу к собственным интерфейсам и рабочим контурам вокруг Codex. Если вы встраиваете агента в продукт или командный процесс, архитектуру интеграции полезно обсудить до того, как протокол зафиксируется в коде.
Если захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov
Если хотите разобрать свою задачу — напишите мне Если хотите разобрать свою задачу — напишите мне.
Можно прийти с идеей, черновым контекстом или уже живой задачей. Помогу быстро понять, где реальный следующий шаг, а где лишний шум.
Обычно хватает 2–3 сообщений, чтобы понять, могу ли я здесь реально помочь и в каком формате лучше двигаться дальше.
Дальше по теме
Как через Sites в Codex и ChatGPT Work собрать и задеплоить сайт: доступ и публичные ссылки, вход через ChatGPT, БД, домены, лимиты беты и чеклист.