Ускорение рабочих процессов агентов с помощью WebSockets в Responses API

Авторы: Брайан Ю (Brian Yu) и Ашвин Натан (Ashwin Nathan), члены технического персонала

Когда вы просите Codex исправить баг, он сканирует кодовую базу в поисках релевантных файлов, читает их для формирования контекста, вносит правки и запускает тесты, чтобы убедиться, что исправление сработало. Под капотом это означает десятки взаимных запросов к Responses API: определение следующего действия модели, запуск инструмента на вашем компьютере, отправка результата работы инструмента обратно в API и повторение этого процесса.

Все эти запросы в сумме могут выливаться в минуты ожидания, пока Codex выполняет сложные задачи. С точки зрения задержек (латентности), цикл агента Codex проводит больше всего времени на трех основных этапах: работа в службах API (для валидации и обработки запросов), инференс модели и клиентское время (запуск инструментов и построение контекста модели). Инференс — это этап, на котором модель работает на графических процессорах (GPU) для генерации новых токенов. Раньше выполнение инференса LLM на GPU было самой медленной частью цикла агента, поэтому накладные расходы службы API было легко скрыть. По мере того как инференс ускоряется, совокупные накладные расходы API от работы агента становятся гораздо более заметными.

В этой статье мы расскажем, как нам удалось ускорить циклы работы агентов через API на 40% от начала до конца, позволив пользователям ощутить скачок скорости инференса с 65 до почти 1000 токенов в секунду. Мы подошли к решению этой задачи через кэширование, устранение лишних сетевых переходов, улучшение стека безопасности для быстрой фильтрации проблем и — что наиболее важно — создание способа поддержания постоянного (персистентного) соединения с Responses API вместо выполнения серии синхронных вызовов API.

Diagram titled

Когда API стал узким местом

В Responses API предыдущие флагманские модели, такие как GPT‑5 и GPT‑5.2, работали со скоростью примерно 65 токенов в секунду (TPS). Для запуска GPT‑5.3‑Codex‑Spark, быстрой модели для написания кода, нашей целью был порядок величины выше: более 1000 TPS, что стало возможным благодаря специализированному оборудованию Cerebras, оптимизированному для инференса LLM. Чтобы пользователи могли прочувствовать истинную скорость этой новой модели, нам нужно было уменьшить накладные расходы API.

Примерно в ноябре 2025 года мы запустили спринт по производительности Responses API, реализовав множество оптимизаций латентности на критическом пути для отдельного запроса:

  • Кэширование отрендеренных токенов и конфигурации модели в памяти для пропуска дорогостоящей токенизации и сетевых вызовов для многошаговых ответов
  • Сокращение задержки сетевых переходов за счет исключения вызовов промежуточных сервисов (например, разрешения обработки изображений) и прямого вызова самой службы инференса
  • Улучшение нашего стека безопасности, чтобы мы могли запускать определенные классификаторы для более быстрой фильтрации диалогов

Благодаря этим улучшениям мы добились почти 45-процентного улучшения времени до первого токена (TTFT), которое отражает то, насколько отзывчивым кажется API, но эти улучшения все еще были недостаточны для GPT‑5.3‑Codex‑Spark. Даже с учетом этих улучшений накладные расходы Responses API были слишком велики по сравнению со скоростью модели — то есть пользователям приходилось ждать ЦП, на которых работал наш API, прежде чем они могли задействовать ГП, обслуживающие модель.

Более глубокая проблема носила структурный характер: мы рассматривали каждый запрос Codex как независимый, обрабатывая состояние диалога и другой повторно используемый контекст в каждом последующем запросе. Даже когда большая часть диалога не менялась, мы все равно платили за работу, привязанную ко всей истории. По мере удлинения диалогов эта повторяющаяся обработка становилась все более затратной.

Создание постоянного соединения

Чтобы оптимизировать архитектуру, мы переосмыслили транспортный протокол: могли ли мы поддерживать постоянное соединение и кэшировать состояние вместо установки нового соединения по HTTP и отправки полной истории диалога для каждого последующего запроса? Идея заключалась в том, чтобы отправлять только новую информацию, требующую валидации и обработки, и кэшировать повторно используемое состояние в памяти в течение всего времени жизни соединения. Это позволило бы снизить накладные расходы от избыточной работы.

Мы рассмотрели несколько различных подходов, включая WebSockets и двунаправленный стриминг gRPC. Мы остановились на WebSockets, так как в качестве простого протокола передачи сообщений он избавляет пользователей от необходимости менять формат входных и выходных данных Responses API. Он оказался удобным для разработчиков и органично вписался в нашу существующую архитектуру без серьезных потрясений.

Первый прототип WebSocket изменил наше представление о возможностях латентности Responses API. Инженер из команды Codex, обладающий глубокой экспертизой во всем стеке API, собрал прототип, запустив агента Codex на всю ночь.

В этом прототипе развертывание агентов моделировалось как единый долгоиграющий ответ (Response). Используя функции asyncio, Responses API асинхронно блокировался в цикле выборки после того, как вызывался инструмент, и Responses API отправлял событие response.done обратно клиенту. После выполнения вызова инструмента клиенты отправляли обратно событие response.append с результатом работы инструмента, что снимало блокировку с цикла выборки и позволяло модели продолжить работу.

Аналогией здесь является отношение к локальному вызову инструмента как к хостинговому вызову инструмента. Когда модель вызывает поиск в интернете, цикл инференса блокируется, вызывает службу веб-поиска и помещает ответ службы в контекст модели. В нашей архитектуре мы сделали то же самое;, но вместо вызова удаленного сервиса мы отправляли вызов инструмента моделью обратно клиенту по WebSocket. Когда клиент отвечал, мы помещали ответ клиента на вызов инструмента в контекст и продолжали выборку.

Этот дизайн оказался чрезвычайно эффективным, поскольку он устранил повторяющуюся работу API в ходе работы агента. Мы могли выполнить работу до инференса один раз, сделать паузу для выполнения инструментов и выполнить работу после инференса один раз в самом конце.

К сожалению, это потребовало платы в виде менее привычного и более сложного формата API. Мы хотели, чтобы разработчики могли легко внедрить поддержку WebSocket без необходимости переписывать свою интеграцию API под новый режим взаимодействия.

Сохранение привычного API при переходе на инкрементальный стек

Для версии, которую мы запустили, мы вернулись к привычному формату: продолжаем использовать response.create с тем же телом запроса и используем previous_response_id для продолжения контекста диалога из состояния предыдущего ответа.

При соединении по WebSocket сервер сохраняет в памяти кэш предыдущего состояния ответа, привязанный к сеансу соединения. Когда последующий запрос response.create включает previous_response_id, мы извлекаем это состояние из кэша вместо того, чтобы пересобирать весь диалог с нуля.

Это закэшированное состояние включает в себя:

  • Предыдущий объект response
  • Предыдущие элементы ввода и вывода
  • Определения инструментов и пространства имен
  • Повторно используемые артефакты выборки, такие как ранее отрендеренные токены
Diagram titled

Повторно используя состояние предыдущего ответа в памяти, мы смогли реализовать несколько крупных оптимизаций:

  • Настройка некоторых наших классификаторов безопасности и валидаторов запросов на обработку только новых входных данных, а не всей истории каждый раз
  • Поддержание кэша отрендеренных токенов в памяти, к которому мы осуществляем дозапись, что позволяет пропускать ненужную токенизацию
  • Повторное использование нашей успешной логики разрешения/маршрутизации моделей между запросами
  • Совмещение по времени неблокирующих задач, выполняемых после инференса (например, биллинга), с последующими запросами

Целью было максимально приблизиться к прототипу с минимальными накладными расходами, но при этом сохранить формат API, который разработчики уже понимали и под который выстраивали свою работу.

Новая планка скорости

После двухмесячного спринта по созданию режима WebSocket мы запустили альфа-версию совместно с ключевыми стартапами в области кодинг-агентов, чтобы они могли интегрировать ее в свою инфраструктуру и безопасно наращивать трафик. Альфа-пользователи были в восторге, сообщив о повышении производительности до 40% в своих агентских рабочих процессах. Учитывая положительные отзывы об альфа-версии, мы были готовы к запуску.

Результаты запуска не заставили себя ждать. Codex быстро перевел бо́льшую часть своего трафика Responses API на работу в режиме WebSocket, зафиксировав значительное улучшение латентности. Для GPT‑5.3‑Codex‑Spark мы достигли целевого показателя в 1000 TPS, а пиковые значения доходили до 4000 TPS, что доказало способность Responses API справляться с гораздо более быстрым инференсом в условиях реального продакшн-трафика. Эффект быстро проявился и в сообществе разработчиков:

  • Codex оперативно перевел бо́льшую часть своего трафика на WebSockets. Пользователи Codex, запускающие новейшие модели, такие как GPT‑5.3‑Codex, GPT‑5.4 и более поздние, получают выгоду от ускорения благодаря режиму WebSocket.
  • Vercel интегрировала режим WebSocket в AI SDK и зафиксировала снижение латентности до 40%.
  • Многофайловые рабочие процессы Cline стали выполняться на 39% быстрее.
  • Модели OpenAI в Cursor стали работать до 30% быстрее.

Режим WebSocket — это одна из самых значимых новых возможностей в Responses API с момента его запуска в марте 2025 года. Мы прошли путь от идеи до запуска в продакшн всего за несколько недель благодаря тесному сотрудничеству между командами API и Codex в OpenAI. Это не только кардинально улучшает задержку при развертывании агентов, но и отвечает растущей потребности разработчиков: по мере того как инференс моделей ускоряется, сервисы и системы, окружающие инференс, также должны ускоряться, чтобы передать эти преимущества пользователям.

Авторы

Brian Yu, Ashwin Nathan

Благодарности

Особая благодарность командам Responses API и Codex, которые работали над созданием режима WebSocket.

Полный текст статьи читайте на OpenAI