Если проект начинается сегодня, в большинстве случаев стоит брать Responses API. Если сервис на Chat Completions стабильно решает простую задачу генерации текста, срочной переписи нет. Текущее руководство OpenAI по миграции одновременно говорит две важные вещи: Responses рекомендован для новых проектов, а Chat Completions продолжает поддерживаться.
Это не два имени одного JSON-протокола. Chat Completions строится вокруг массива сообщений и массива вариантов ответа. Responses использует типизированные Items: сообщение, reasoning, вызов функции и результат функции — разные элементы. Поэтому смена URL затрагивает парсер, состояние диалога, инструменты, streaming и наблюдаемость.
Сначала найдите контракт, от которого зависит код
Минимальные вызовы выглядят похоже:
pythoncompletion = client.chat.completions.create( model="gpt-5.6", messages=[{"role": "user", "content": "Классифицируй обращение"}], ) text = completion.choices[0].message.content response = client.responses.create( model="gpt-5.6", input="Классифицируй обращение", ) text = response.output_text
Но output_text — удобный помощник SDK только для итогового текста. Если нужны вызовы инструментов, статусы или другие типы результата, приложение должно разбирать response.output.
| Контракт | Chat Completions | Responses API |
|---|---|---|
| Endpoint | /v1/chat/completions | /v1/responses |
| Вход | messages | input и при необходимости instructions |
| Выход | choices[].message | типизированные output[] Items |
| Несколько кандидатов | параметр n | одна генерация в response |
| Продолжение диалога | повторная отправка истории | previous_response_id, Conversations или ручной replay |
| Structured Outputs | response_format | text.format |
| Поток | chunks и choices[].delta | типизированные события |
Простой массив role/content можно передать в Responses как input. Это облегчает первый тест, но не делает протоколы взаимозаменяемыми.
Состояние диалога не отменяет ответственность приложения
В Chat Completions приложение обычно хранит нужную историю и снова отправляет её в messages. Responses позволяет связать следующий ход через previous_response_id:
pythonfirst = client.responses.create( model="gpt-5.6", instructions="Отвечай как дежурный инженер.", input="Сгруппируй эти алерты по причине.", ) next_turn = client.responses.create( model="gpt-5.6", previous_response_id=first.id, instructions="Отвечай как дежурный инженер.", input="Оставь только критическую группу.", )
Повтор instructions здесь обязателен по смыслу. API reference Responses предупреждает: инструкции предыдущего response не переносятся автоматически только из-за previous_response_id.
Удобное продолжение и хранение данных — разные решения. В документе OpenAI о данных отдельно описаны store, Zero Data Retention, background mode, кэш, hosted tools и внешние сервисы. Сейчас для сохранённого Responses application state указан период не менее 30 дней, но организационные настройки и исключения меняют результат. Для требований к данным проверяйте реальную конфигурацию, а не один флаг.
Function calling меняет весь цикл

В Chat Completions вызовы функций находятся внутри assistant message. Результат возвращается сообщением role: "tool", связанным через tool_call_id. В Responses вызов — отдельный Item function_call, а результат — function_call_output, связанный через call_id.
pythonoutputs = [] for item in response.output: if item.type == "function_call": outputs.append({ "type": "function_call_output", "call_id": item.call_id, "output": run_tool(item.name, item.arguments), })
Нельзя обрабатывать только первый элемент: модель может вернуть параллельные вызовы. Приёмочные тесты должны покрывать ноль, один и несколько вызовов, неверные аргументы, timeout, ошибку инструмента и повторный вызов после результата. Актуальные конверты приведены в официальном руководстве по function calling.
Hosted tools — web search, file search, code interpreter и remote MCP — делают Responses особенно полезным для агентных сценариев. Но поддержка конкретного инструмента зависит от модели.
Streaming требует диспетчера событий
Chat Completions отдаёт chunks, и интерфейс часто просто добавляет choices[0].delta.content. Responses отдаёт семантические события разных типов: текстовые delta, аргументы функции, завершение Item и финальный статус всего response. В руководстве по streaming эти формы показаны отдельно.
Интерфейс должен различать completed, failed, incomplete, отмену пользователем и разрыв сети. HTTP 200 и первый текстовый fragment ещё не означают успешного завершения. Для диагностики полезно сохранять response ID, финальный статус, типы Items, usage и причину ошибки или незавершённости.
Structured Outputs тоже меняет форму запроса: response_format становится text.format. Проверяйте не только JSON Schema, но и поддержку модели, refusal и ветку ошибки. Официальное руководство отдельно объясняет, когда нужна структурированная реплика пользователю, а когда function calling для действия в системе.
Когда остаться, а когда перейти

Responses лучше подходит новому проекту с инструментами, reasoning context, мультимодальным входом, длинной задачей или будущим агентным циклом. Chat Completions можно оставить для зрелого однопроходного текста, если миграция пока не даёт измеримой пользы.
Для сторонних сервисов важна переносимость. Надпись «OpenAI-compatible» часто означает совместимость именно с Chat Completions. Она не доказывает поддержку Responses. По документации провайдера отдельно проверяйте endpoint, Items, события потока, tool envelopes, продолжение состояния и ошибки.
Практичная миграция идёт за адаптером: сначала уберите из бизнес-кода прямой доступ к choices[0], затем запустите shadow-трафик, выберите стратегию состояния, перенесите полный цикл инструментов, перепишите streaming и только после этого постепенно переключайте production. Готовность наступает не тогда, когда пример выдал текст, а когда диалог восстанавливается, все вызовы связаны, schema разбирается, поток корректно закрывается, а сбой можно объяснить.



