> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apiyi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Выбор эндпоинта: миграция GPT-5.4+ на Responses

> В GPT-5.4 и более поздних версиях отправка tools вместе с reasoning_effort через /v1/chat/completions может быть отклонена с ошибкой 400. На этой странице описано, как подтвердить, что вы столкнулись с этой проблемой, как выбрать один из двух способов её решения, какие именно изменения внести в код (с полным примером вызова tools до и после), а также как проверить миграцию.

<Note>
  **Кратко**: в моделях GPT-5.4 и более поздних моделях отправка **`tools` вместе с явным `reasoning_effort`** (любым значением, кроме `none`) в `/v1/chat/completions` может быть отклонена на upstream с ошибкой 400: `Function tools with reasoning_effort are not supported ...`.

  Есть два решения: **перенести запросы с инструментами в `/v1/responses`** (сохраняет и рассуждение, и инструменты — рекомендуется) или **явно задать `reasoning_effort="none"`** (сохраняет эндпоинт, но отключает рассуждение). Запросы без `tools` не затрагиваются.
</Note>

## Сначала убедитесь, что столкнулись именно с этой проблемой

Она проявляется тремя способами. Второй проще всего неправильно интерпретировать.

### Симптом 1: явная ошибка 400

```text theme={null}
Function tools with reasoning_effort are not supported for gpt-5.6-sol in
/v1/chat/completions. To use function tools, use /v1/responses or set
reasoning_effort to 'none'.
```

В ответе содержится `param: reasoning_effort`. Это **официальное ограничение OpenAI**, а не проблема шлюза APIYI — тот же запрос, отправленный напрямую в OpenAI, ведёт себя идентично.

### Симптом 2: иногда работает, а иногда завершается ошибкой

Одна модель может обслуживаться несколькими маршрутами вышестоящих систем, и **это ограничение применяется не на каждом маршруте**. Наши собственные измерения от 2026-09-02, группа по умолчанию, тот же ключ, тот же временной интервал, по шесть вызовов для каждой комбинации:

| Модель          | `tools` + `reasoning_effort="medium"`            |
| --------------- | ------------------------------------------------ |
| `gpt-5.6-luna`  | 6/6 вернули 400                                  |
| `gpt-5.6-sol`   | 6/6 вернули 200, инструмент был вызван корректно |
| `gpt-5.6-terra` | 6/6 вернули 200, инструмент был вызван корректно |
| `gpt-5.4`       | 6/6 вернули 200, инструмент был вызван корректно |

Ранее в тот же день клиент действительно получил ошибку 400 для `gpt-5.6-sol`.

<Warning>
  **«Только что у меня это сработало» не доказывает, что вы в безопасности.** Та же модель и тот же код могут начать возвращать 400 в другое время или в другой группе. Перейдите на Responses API или явно задайте `reasoning_effort="none"` — оба варианта стабильны на каждом маршруте.
</Warning>

### Симптом 3: ошибки нет, но инструмент никогда не вызывается

Если модель должна была вызвать инструмент, но вместо этого отвечает праздной беседой (`finish_reason` — `stop`, `tool_calls` пуст), не начинайте переписывать промпт. Повторно отправьте запрос один раз, явно задав `reasoning_effort` равным `none`: если после этого инструмент будет вызван корректно, проблема заключается в комбинации параметров, а не в вашем промпте.

## Что охватывает ограничение

|                                                                                    | Затронуто                                                   |
| ---------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| семейства `gpt-5.6-sol` / `gpt-5.6-terra` / `gpt-5.6-luna` / `gpt-5.5` / `gpt-5.4` | Да — зависит от маршрута, см. выше                          |
| `gpt-5.2` / `gpt-5.1` / `gpt-5` и более ранние версии                              | Не охватывается официальным объявлением                     |
| Claude, Gemini, Grok и другие модели, не относящиеся к OpenAI                      | Не связано, не затронуто                                    |
| Запросы без `tools`                                                                | Не затронуты, отправляйте любое значение `reasoning_effort` |
| Запросы к `/v1/responses`                                                          | Не затронуты, рассуждение и tools работают совместно        |

Ограничение срабатывает **только при явной отправке уровня усилий, отличного от `none`**. В наших тестах все четыре значения — `low`, `medium`, `high` и `xhigh` — вызывают его.

<Note>
  **Пропуск `reasoning_effort` не вызывает ограничение.** На маршруте `gpt-5.6-luna`, где ошибка 400 воспроизводится детерминированно, все четыре уровня усилий возвращали 400, а при пропуске параметра значение `tool_calls` корректно возвращалось в 6 случаях из 6. Поэтому минимальное экстренное исправление имеет две формы: явно задать `none` или полностью удалить параметр.
</Note>

## Какой вариант выбрать

|                       | Перейти на `/v1/responses`                                   | Установить `reasoning_effort="none"`                                                        |
| --------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| Сохраняет рассуждение | Да, полностью, при любом уровне усилий                       | Нет — рассуждение отключается, и модель теряет этап планирования                            |
| Масштаб изменений     | Изменяются и структура запроса, и структура ответа; см. ниже | Один дополнительный параметр, одна строка                                                   |
| Стабильность          | Одинаковая для всех маршрутов                                | Одинаковая для всех маршрутов                                                               |
| Для кого подходит     | Агенты, многошаговая оркестрация tools, долгосрочное решение | Устранение проблем в рабочей среде, простая логика tools, код, который пока нельзя изменить |

Для сложных задач с использованием tools отключение рассуждения заметно ухудшает работу модели — она теряет этап, на котором определяет, какой tool вызвать и в каком порядке. Рассматривайте `none` как временное решение, а не как конечный вариант.

## Дело не только в обходе ошибки

Даже если вы никогда не столкнётесь с ограничением, Responses — это эндпоинт, который OpenAI рекомендует для новых проектов. Согласно официальным данным, одна и та же модель рассуждения показывает более высокие результаты в SWE-bench при использовании Responses, использование кэша значительно эффективнее, чем в Chat Completions, а встроенные инструменты, такие как веб-поиск и интерпретатор кода, доступны только здесь. Числовые показатели и подробности приведены в разделе [Нативные вызовы](/ru/api-capabilities/openai/native).

Именно кэширование отражается в вашем счёте: **многошаговые агенты больше всего выигрывают от попаданий в кэш**, а многошаговые агенты — это как раз тот тип нагрузки, который с наибольшей вероятностью сталкивается с указанным выше ограничением. О том, как тарифицируется кэширование и как интерпретировать показатели попаданий: [Кэширование промптов](/ru/api-capabilities/openai/prompt-caching).

## В какой вы группе

| Как вы интегрируете                                    | Что делать                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Вы пишете код** (OpenAI SDK или необработанный HTTP) | Измените эндпоинт — см. следующий раздел                                                                                                                                                                                                                                                                                                                                   |
| **Вы используете фреймворк** (LangChain и аналоги)     | Проверьте, есть ли в вашем фреймворке переключатель Responses. В LangChain есть `ChatOpenAI(..., use_responses_api=True)`. Если в фреймворке такого переключателя нет, вам остаётся `reasoning_effort="none"` или другая модель                                                                                                                                            |
| **Вы используете клиент или плагин для IDE**           | На стороне клиента вы ничего изменить не можете; вам нужен клиент с поддержкой Responses. Полная матрица поддержки находится в разделе «Текущая поддержка клиентов» на странице [Нативные вызовы](/ru/api-capabilities/openai/native); сведения о конкретных инструментах см. в разделах [Trae](/ru/scenarios/programming/trae) и [Cline](/ru/scenarios/programming/cline) |

## Что изменяется в вашем коде

Полное сопоставление полей приведено в разделе [Нативные вызовы](/ru/api-capabilities/openai/native). Ниже перечислены только четыре различия, имеющие значение для вызова инструментов, поскольку именно этому посвящена данная страница:

|                                    | Chat Completions                                     | Responses                                                       |
| ---------------------------------- | ---------------------------------------------------- | --------------------------------------------------------------- |
| Уровень рассуждения                | На верхнем уровне: `reasoning_effort="medium"`       | Вложенный: `reasoning={"effort": "medium"}`                     |
| Определение инструмента            | Вложенное: `{"type": "function", "function": {...}}` | Плоское: `{"type": "function", "name": ..., "parameters": ...}` |
| Возвращаемый вызов                 | `message.tool_calls[]`, определяется по `id`         | Элемент `function_call` в `output`, определяется по `call_id`   |
| Результат отправляется обратно как | `{"role": "tool", "tool_call_id": ...}`              | `{"type": "function_call_output", "call_id": ...}`              |

<Warning>
  Два формата инструментов **нельзя смешивать**. Отправка вложенного определения `function: {...}` в стиле Chat Completions в `/v1/responses` (или наоборот) — наиболее распространённая причина ошибки «недопустимый параметр» от SDK. Подробнее см. в разделе [Вызов функций](/ru/api-capabilities/openai/function-calling).
</Warning>

Один и тот же цикл работы инструмента погоды до и после изменений:

<CodeGroup>
  ```python До: Chat Completions theme={null}
  from openai import OpenAI

  client = OpenAI(api_key="YOUR_APIYI_KEY", base_url="https://api.apiyi.com/v1")

  tools = [{
      "type": "function",
      "function": {
          "name": "get_weather",
          "description": "Look up the weather for a city",
          "parameters": {
              "type": "object",
              "properties": {"city": {"type": "string"}},
              "required": ["city"],
          },
      },
  }]

  messages = [{"role": "user", "content": "What is the weather in Beijing today?"}]

  resp = client.chat.completions.create(
      model="gpt-5.6-luna", messages=messages, tools=tools,
      reasoning_effort="medium",              # sent alongside tools; may be rejected
  )

  call = resp.choices[0].message.tool_calls[0]
  messages.append(resp.choices[0].message)    # the assistant turn, verbatim
  messages.append({
      "role": "tool",
      "tool_call_id": call.id,
      "content": '{"temp": 26, "sky": "clear"}',
  })

  final = client.chat.completions.create(
      model="gpt-5.6-luna", messages=messages, tools=tools,
      reasoning_effort="medium",
  )
  print(final.choices[0].message.content)
  ```

  ```python После: Responses theme={null}
  from openai import OpenAI

  client = OpenAI(api_key="YOUR_APIYI_KEY", base_url="https://api.apiyi.com/v1")

  tools = [{                                  # flat, with no "function" wrapper
      "type": "function",
      "name": "get_weather",
      "description": "Look up the weather for a city",
      "parameters": {
          "type": "object",
          "properties": {"city": {"type": "string"}},
          "required": ["city"],
          "additionalProperties": False,
      },
  }]

  history = [{"role": "user", "content": "What is the weather in Beijing today?"}]

  resp = client.responses.create(
      model="gpt-5.6-luna", input=history, tools=tools,
      reasoning={"effort": "medium"},         # nested, and unrestricted here
  )

  call = next(i for i in resp.output if i.type == "function_call")
  history += resp.output                      # append the whole output verbatim
  history.append({
      "type": "function_call_output",
      "call_id": call.call_id,                # note: call_id, not id
      "output": '{"temp": 26, "sky": "clear"}',
  })

  final = client.responses.create(
      model="gpt-5.6-luna", input=history, tools=tools,
      reasoning={"effort": "medium"},
  )
  print(final.output_text)
  ```
</CodeGroup>

Оба фрагмента выполнялись с группой APIYI по умолчанию: первый стабильно воспроизводит ошибку 400, а второй полностью выполняет цикл вызова, возврата результата и формирования финального ответа.

<Tip>
  Не пропускайте `history += resp.output`. Помимо `function_call`, вывод может содержать элемент `reasoning` — его дословная передача обратно позволяет модели продолжить предыдущую цепочку рассуждений и является именно той причиной, по которой Responses лучше справляется с многоэтапными задачами с использованием инструментов.
</Tip>

## Ловушки, с которыми сталкиваются при миграции

<AccordionGroup>
  <Accordion title="output — это не choices, не обращайтесь к нему по индексу">
    `output` — это **массив элементов**, который может одновременно содержать записи `reasoning`, `message` и `function_call`, причём их порядок и количество не гарантируются. Используйте `resp.output_text` для текста и выполняйте итерацию с фильтрацией по `type == "function_call"` для вызовов инструментов. Никогда не задавайте индекс жёстко.
  </Accordion>

  <Accordion title="Переименованные параметры: max_tokens, response_format, temperature">
    `max_tokens` (или `max_completion_tokens`) становится `max_output_tokens`; `response_format` становится `text.format`; системный prompt можно переместить из `messages` в корневой уровень `instructions`. Отдельно следует отметить, что модели рассуждения gpt-5 **не поддерживают `temperature` или `top_p`** ни на одном из эндпоинтов — удалите их и управляйте моделью с помощью `reasoning.effort`.
  </Accordion>

  <Accordion title="Все поля usage переименованы">
    `usage.prompt_tokens` становится `usage.input_tokens`, `completion_tokens` становится `output_tokens`, а попадания в кэш находятся в `usage.input_tokens_details.cached_tokens`. Одновременно обновите учёт usage, иначе в нём незаметно будут записываться нулевые значения.
  </Accordion>

  <Accordion title="Многоходовый режим: самостоятельное управление историей работает всегда; цепочка запросов зависит от вашей группы">
    Самый надёжный подход — **самостоятельно поддерживать массив `input`**, дословно добавляя в него `output` каждого хода. Это работает в любой группе и с любой моделью, именно так поступает приведённый выше пример.

    Цепочка запросов с `previous_response_id` работала в группе по умолчанию 2026-09-02 — `gpt-5.6-sol`, `terra`, `luna` и `gpt-5.4` восстанавливали предыдущий ход, `store` по умолчанию имеет значение `true`, а отправка `store: false` с последующим созданием цепочки корректно сообщает, что предыдущий ответ не найден. Получение истории с помощью `GET /v1/responses/{id}` по-прежнему недоступно. **Проверьте это в собственной группе, прежде чем полагаться на такую возможность.** Дополнительная информация: [Многоходовые диалоги](/ru/api-capabilities/multi-turn-conversation).
  </Accordion>

  <Accordion title="Потоковая передача — это поток семантических событий, а не объединение delta">
    Chat Completions передаёт последовательность приращений `delta`; Responses передаёт типизированные события, такие как `response.output_text.delta` и `response.function_call_arguments.delta`. Парсер потоковой передачи необходимо переписать, а не повторно использовать. См. раздел [Нативные вызовы](/ru/api-capabilities/openai/native).
  </Accordion>
</AccordionGroup>

## Проверка миграции

Не ограничивайтесь кодом HTTP 200. Выполните эти четыре проверки:

<Steps>
  <Step title="Убедитесь, что результат действительно содержит function_call">
    Выведите `[i.type for i in resp.output]` — вы должны увидеть `function_call`, которому на более высоких уровнях усилий предшествует `reasoning`. Только `message` означает, что инструмент так и не был вызван.
  </Step>

  <Step title="Убедитесь, что поля использования по-прежнему содержат значения">
    Проверьте, что `usage.input_tokens` и `output_tokens` не равны нулю, а `output_tokens_details.reasoning_tokens` изменяется вместе с уровнем усилий.
  </Step>

  <Step title="Убедитесь, что начинают появляться попадания в кэш">
    Выполните несколько запросов и следите, чтобы `usage.input_tokens_details.cached_tokens` превысил ноль. Это самое непосредственное преимущество тарификации Responses перед режимом совместимости.
  </Step>

  <Step title="Повторно отправьте запрос, который раньше возвращал ошибку 400">
    Та же комбинация `tools` и `reasoning_effort` теперь должна стабильно выполняться. Сохраните её как регрессионный тест, чтобы будущая замена модели сразу выявила проблему.
  </Step>
</Steps>

## Когда не следует переходить

Это не решение по принципу «всё или ничего». Оставаться в режиме совместимости вполне разумно, если:

* **Вы не используете вызов инструментов** — ограничение не применяется, и вы можете отправлять любые `reasoning_effort`
* **Вы вызываете несколько поставщиков через один путь кода** — здесь Claude и Gemini предлагают только `/v1/chat/completions`, и разветвление кода только ради OpenAI может не окупиться
* **Ваш фреймворк или клиент фиксирует эндпоинт** — оставайтесь на `reasoning_effort="none"`, пока он не будет обновлён
* **Вы используете `gpt-5.2` или более раннюю версию** — она находится за пределами затронутого диапазона

Полный перечень ограничений возможностей режима совместимости приведён в разделе [Режим совместимости](/ru/api-capabilities/openai/compatible).

## Часто задаваемые вопросы

<AccordionGroup>
  <Accordion title="Что именно я теряю при reasoning_effort=none?">
    Модель перестаёт явно выполнять рассуждение и отвечает напрямую. В одноступенчатых задачах с очевидным выбором инструмента изменения минимальны; многошаговая оркестрация, требующая от модели определить порядок вызовов, заметно ухудшается. Это промежуточный этап, а не конечное решение.
  </Accordion>

  <Accordion title="Можно ли переключать эндпоинты только для запросов, содержащих tools?">
    Да, это распространённый поэтапный подход: оставить обычный чат на `/v1/chat/completions`, а на `/v1/responses` перевести только путь с инструментами. Оба эндпоинта используют один и тот же ключ и один и тот же базовый URL, а тарификация идентична.
  </Accordion>

  <Accordion title="Изменяется ли цена после переключения эндпоинтов?">
    Нет. Тарифы на входные и выходные данные для конкретной модели одинаковы на обоих эндпоинтах, как и модель тарификации. См. [Модели и тарификация](/ru/api-capabilities/model-info). Единственное различие заключается в частоте попаданий в кэш, которая обычно выше в Responses, поэтому итоговый счёт, как правило, уменьшается.
  </Accordion>

  <Accordion title="Затрагивает ли это Claude и Gemini?">
    Нет. Это ограничение OpenAI для собственных моделей GPT-5.4 и новее. Claude через `/v1/messages` или режим совместимости, а также Gemini через нативный режим или режим совместимости могут одновременно использовать вызов инструментов и рассуждение.
  </Accordion>

  <Accordion title="Почему для моделей Pro доступен только Responses?">
    На практике `gpt-5.4-pro` и `gpt-5.5-pro` можно использовать только через `/v1/responses`, и для них требуется группа SVIP. Они выполняются долго и рассчитаны на работу в фоновом режиме, который режим совместимости не поддерживает. См. [Нативные вызовы](/ru/api-capabilities/openai/native).
  </Accordion>

  <Accordion title="Прекратит ли работу Chat Completions?">
    Нет. Эндпоинт, закрытие которого запланировала OpenAI, — это **Assistants API**, а не Chat Completions. Оба эндпоинта будут поддерживаться в долгосрочной перспективе; новые функции просто сначала появляются в Responses.
  </Accordion>
</AccordionGroup>

## Связанные страницы

<CardGroup cols={3}>
  <Card title="Нативные вызовы" icon="zap" href="/ru/api-capabilities/openai/native">
    Полное описание эндпоинта Responses: параметры, структура ответа, встроенные tools и матрица поддержки клиентов
  </Card>

  <Card title="Режим совместимости" icon="plug" href="/ru/api-capabilities/openai/compatible">
    Принцип работы Chat Completions, границы его возможностей и настройка SDK для каждого языка
  </Card>

  <Card title="Вызов функций" icon="wrench" href="/ru/api-capabilities/openai/function-calling">
    Полные примеры вызова tools и сборка потоковой передачи для обоих эндпоинтов
  </Card>
</CardGroup>
