Skip to main content
The short version: on GPT-5.4 and later models, sending tools together with an explicit reasoning_effort (anything other than none) to /v1/chat/completions can be rejected upstream with a 400: Function tools with reasoning_effort are not supported ....Two ways out: move tool-carrying requests to /v1/responses (keeps both reasoning and tools — recommended), or set reasoning_effort="none" explicitly (keeps the endpoint, gives up reasoning). Requests without tools are unaffected.

First, confirm that this is what you hit

There are three ways it shows up. The second one is the easiest to misread.

Symptom 1: an explicit 400

The response carries param: reasoning_effort. This is an official OpenAI restriction, not an APIYI gateway problem — the same request sent straight to OpenAI behaves identically.

Symptom 2: it works sometimes and fails other times

A single model may sit behind several upstream routes, and not every route enforces this. Our own measurements on 2026-09-02, default group, same key, same time window, six calls per combination: Earlier the same day, a customer did receive this 400 on gpt-5.6-sol.
“It worked for me just now” is not evidence that you are safe. The same model and the same code can start returning 400 at a different time or in a different group. Either move to Responses or set reasoning_effort="none" explicitly — both are stable across every route.

Symptom 3: no error, but the tool is never called

If the model should have called a tool and instead replied with small talk (finish_reason is stop, tool_calls empty), do not start rewriting your prompt. Resend once with reasoning_effort set explicitly to none: if the tool is then called correctly, the problem is the parameter combination, not your prompt.

What the restriction covers

The trigger is explicitly sending a non-none effort level. All four of low, medium, high and xhigh trigger it in our tests.
Omitting reasoning_effort does not trigger it. On the gpt-5.6-luna route that reproduces the 400 deterministically, all four effort levels returned 400, while omitting the parameter returned tool_calls correctly 6 times out of 6. So the minimal emergency fix has two forms: set none explicitly, or drop the parameter entirely.

Which way out to pick

For complex tool-driven tasks, turning reasoning off degrades the model noticeably — it loses the step where it works out which tool to call and in what order. Treat none as a stopgap rather than a destination.

It is not only about dodging the error

Even if you never hit the restriction, Responses is the endpoint OpenAI recommends for new projects. Officially: the same reasoning model scores higher on SWE-bench through Responses, cache utilization is substantially better than Chat Completions, and built-in tools such as web search and the code interpreter exist only here. The numbers and details are on Native Calls. The cache point is the one that shows up on your bill: multi-turn agents benefit most from cache hits, and multi-turn agents are exactly the workload most likely to hit the restriction above. How caching is billed and how to read hit rates: Prompt Caching.

Which group are you in

What changes in your code

The complete field mapping lives on Native Calls. Here are only the four differences that matter for tool calling, since that is what this page is about:
The two tool formats cannot be mixed. Sending a Chat Completions style nested function: {...} definition to /v1/responses (or the reverse) is the most common cause of an “invalid parameter” error from the SDK. More detail on Function Calling.
The same weather-tool loop, before and after:
Both snippets were run against the APIYI default group: the first reproduces the 400 reliably, the second completes the full call, return, final-answer loop.
Do not skip history += resp.output. Besides function_call, the output may contain a reasoning item — carrying it back verbatim is what lets the model continue its earlier train of thought, and it is precisely why Responses performs better on multi-step tool tasks.

The traps people hit while migrating

output is an array of items that can hold reasoning, message and function_call entries at once, in no guaranteed order or count. Use resp.output_text for text, and iterate filtering on type == "function_call" for tool calls. Never hard-code an index.
max_tokens (or max_completion_tokens) becomes max_output_tokens; response_format becomes text.format; the system prompt can move out of messages into the top-level instructions. Separately, gpt-5 reasoning models do not support temperature or top_p on either endpoint — remove them and control the model through reasoning.effort instead.
usage.prompt_tokens becomes usage.input_tokens, completion_tokens becomes output_tokens, and cache hits live in usage.input_tokens_details.cached_tokens. Update your usage accounting at the same time, or it will silently record zeros.
The safest approach is to maintain the input array yourself, appending each turn’s output verbatim. That holds in every group and for every model, and it is what the example above does.Chaining with previous_response_id did work in the default group on 2026-09-02 — gpt-5.6-sol, terra, luna and gpt-5.4 all recalled the previous turn, store defaults to true, and sending store: false then chaining correctly reports that the previous response cannot be found. Retrieving history with GET /v1/responses/{id} is still unavailable. Verify it in your own group before you depend on it. Background: Multi-Turn Conversations.
Chat Completions streams a series of delta increments; Responses streams typed events such as response.output_text.delta and response.function_call_arguments.delta. Your streaming parser has to be rewritten rather than reused. See Native Calls.

Verifying the migration

Do not stop at HTTP 200. Walk these four checks:
1

Confirm output really contains function_call

Print [i.type for i in resp.output] — you should see function_call, preceded by reasoning at higher effort levels. Only a message means the tool was never called.
2

Confirm your usage fields still read values

Check that usage.input_tokens and output_tokens are non-zero, and that output_tokens_details.reasoning_tokens moves with the effort level.
3

Confirm cache hits start appearing

Run several turns and watch usage.input_tokens_details.cached_tokens rise above zero. This is the most direct billing benefit Responses has over compatibility mode.
4

Replay the request that used to 400

The same tools plus reasoning_effort combination should now pass consistently. Keep it as a regression case so a future model swap surfaces the problem immediately.

When not to migrate

This is not all-or-nothing. Staying on compatibility mode is perfectly reasonable when:
  • You do not use tool calling — the restriction does not apply and you can send any reasoning_effort
  • You call several vendors with one code path — Claude and Gemini only offer /v1/chat/completions here, and forking just for OpenAI may not pay off
  • Your framework or client locks the endpoint — hold the line with reasoning_effort="none" until it catches up
  • You are on gpt-5.2 or earlier — outside the affected range
The full capability boundary of compatibility mode is on Compatibility Mode.

FAQ

The model stops reasoning explicitly and answers directly. Single-step tasks with an obvious tool choice barely change; multi-step orchestration that needs the model to work out a call order degrades noticeably. It is a bridge, not a destination.
Yes, and it is a common incremental approach: keep plain chat on /v1/chat/completions and move only the tool-carrying path to /v1/responses. Both endpoints use the same key and the same base URL, and pricing is identical.
No. Input and output rates for a given model are the same on both endpoints, and so is the billing model. See Models and Pricing. The only difference is the cache hit rate, which is usually higher on Responses — so the bill tends to go down.
No. This is an OpenAI restriction on its own GPT-5.4+ models. Claude through /v1/messages or compatibility mode, and Gemini through native or compatibility mode, can both use tool calling and thinking at the same time.
In practice gpt-5.4-pro and gpt-5.5-pro are only usable through /v1/responses, and require the SVIP group. They run for a long time and are designed to pair with background mode, which compatibility mode cannot carry. See Native Calls.
No. The endpoint OpenAI has scheduled for shutdown is the Assistants API, not Chat Completions. Both endpoints stay supported long-term; new features simply land on Responses first.

Native Calls

The full Responses endpoint: parameters, response shape, built-in tools, client support matrix

Compatibility Mode

How Chat Completions works, its capability boundary, and SDK setup per language

Function Calling

Complete tool-calling examples and streaming assembly for both endpoints