How to set DeepSeek V4.1 Flash's reasoning effort on any OpenAI-compatible API
By Nicho
DeepSeek V4.1 Flash reasons before it answers. Unless you say otherwise, it reasons at high effort. You can change that with one request field, reasoning_effort. It's an ordinary field in the request body, so you can set it per request through any endpoint that passes it along, including ours. You don't need a different model ID.
This post covers the four levels, what each one cost in a test we ran on October 16, 2026, how to set the field from code and from common tools, and how to check that a third-party endpoint actually passes it through.
The short version
Add reasoning_effort next to model:
curl https://api.cheapaimodel.ai/v1/chat/completions \
-H "Authorization: Bearer $CHEAPAIMODEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-1-flash",
"reasoning_effort": "low",
"messages": [{"role": "user", "content": "Summarize this changelog in three bullets: ..."}]
}'
| Value | What it does |
|---|---|
none |
Turns reasoning off. The model answers right away. |
low |
Short reasoning. DeepSeek suggests it for simple tasks. |
high |
The default. DeepSeek suggests it for everyday agent work. |
max |
The longest reasoning, for harder problems. |
Leaving the field out is the same as sending high.
What each level cost
We sent one math question with a single correct answer to https://api.cheapaimodel.ai/v1: how many ordered pairs (a, b) of positive integers, both at most 100, make a² + b² divisible by 13? (The answer is 1,491.) Each level ran 8 times, except none, which ran 3 times. All requests were non-streaming.
| Effort | Avg. reasoning tokens | Range | Avg. time | Correct |
|---|---|---|---|---|
none |
0 | 0 | 14.0 s | 0 of 3 |
low |
2,348 | 925–3,719 | 17.2 s | 7 of 8 |
high |
3,081 | 2,232–3,629 | 20.4 s | 8 of 8 |
max |
3,530 | 2,700–5,803 | 23.2 s | 7 of 8 |
Reasoning tokens are billed as output tokens. At our V4.1 Flash price when we ran the test, $0.84 per million output tokens, an average request cost about $0.002 at low and $0.003 at max.
What stood out:
- With reasoning off, the model was wrong every time. Twice it ignored "reply with just the number" and worked through the problem in its visible answer, which took about as long as reasoning would have.
highandmaxwere close on this question.maxspent clearly more only once, when it chose to think much longer (the 5,803-token run).lowused about a quarter fewer tokens thanhighand missed once.
One question isn't a benchmark. Before you pick a default, run a sample of your own prompts at two levels and compare usage.completion_tokens_details.reasoning_tokens and the answers.
Setting it from code
OpenAI Python SDK
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheapaimodel.ai/v1",
api_key=os.environ["CHEAPAIMODEL_API_KEY"],
)
completion = client.chat.completions.create(
model="deepseek-v4-1-flash",
reasoning_effort="low",
messages=[{"role": "user", "content": "Explain recursion in one sentence."}],
)
print(completion.choices[0].message.content)
print(completion.usage.completion_tokens_details.reasoning_tokens)
reasoning_effort is an ordinary argument. Its type hints include none from openai 2.8.0 and max from 2.45.0, so older versions still send those values but your type checker will complain. The reasoning text itself is in completion.choices[0].message.reasoning_content. It isn't part of the SDK's types, but the SDK keeps extra fields, so the attribute works.
OpenAI TypeScript SDK
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.cheapaimodel.ai/v1",
apiKey: process.env.CHEAPAIMODEL_API_KEY,
});
const completion = await client.chat.completions.create({
model: "deepseek-v4-1-flash",
reasoning_effort: "max",
messages: [{ role: "user", content: "Explain recursion in one sentence." }],
});
'none' and 'max' type-check from openai 6.46.0. reasoning_content isn't in the SDK's types either, so to read it, cast the message to the SDK's ChatCompletionMessage type intersected with { reasoning_content?: string }.
Responses API
The Responses API takes the same four values inside a reasoning object:
response = client.responses.create(
model="deepseek-v4-1-flash",
reasoning={"effort": "low"},
input="Explain recursion in one sentence.",
)
print(response.output_text)
print(response.usage.output_tokens_details.reasoning_tokens)
With "effort": "none", the response has no reasoning item and reasoning_tokens is 0.
Turning reasoning off
There are two switches. reasoning_effort: "none" is the portable one. DeepSeek also has its own thinking object, which the OpenAI Python SDK sends through extra_body:
completion = client.chat.completions.create(
model="deepseek-v4-1-flash",
messages=[{"role": "user", "content": "..."}],
extra_body={"thinking": {"type": "disabled"}},
)
In the TypeScript SDK, thinking isn't in the types. Add it with a // @ts-expect-error comment, which is what the SDK's README suggests for undocumented parameters. Don't use the per-request body option for this: it replaces the whole request body instead of adding a field.
Use one switch or the other. When we sent both, thinking won both ways: disabled with high didn't reason, and enabled with none did.
In frameworks
We pointed each library at a local server that records requests and checked the body it actually sent. Each one can send the field, but several have a default that doesn't.
LangChain (Python)
import os
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="deepseek-v4-1-flash",
base_url="https://api.cheapaimodel.ai/v1",
api_key=os.environ["CHEAPAIMODEL_API_KEY"],
reasoning_effort="low",
)
llm.invoke("Explain recursion in one sentence.", reasoning_effort="max") # per call
- Send
thinkingwithextra_body={"thinking": {...}}. Putting it inmodel_kwargsraises aTypeError. - Passing
reasoning={"effort": ...}instead ofreasoning_effortquietly switchesChatOpenAIto the Responses API. ChatOpenAIdiscardsreasoning_content. The token count survives inusage_metadata["output_token_details"]["reasoning"]. If you need the text,ChatDeepSeekfromlangchain-deepseekreturns it inadditional_kwargs["reasoning_content"].
LlamaIndex
import os
from llama_index.llms.openai_like import OpenAILike
llm = OpenAILike(
model="deepseek-v4-1-flash",
api_base="https://api.cheapaimodel.ai/v1",
api_key=os.environ["CHEAPAIMODEL_API_KEY"],
is_chat_model=True,
additional_kwargs={"reasoning_effort": "low"},
)
- Use
additional_kwargs. The constructor also has areasoning_effort=argument, but it's only sent for OpenAI's own reasoning models, so with V4.1 Flash it silently does nothing. It also rejects"max". thinkinggoes one level down:additional_kwargs={"extra_body": {"thinking": {...}}}.
Vercel AI SDK
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { generateText } from "ai";
const cheapaimodel = createOpenAICompatible({
name: "cheapaimodel",
baseURL: "https://api.cheapaimodel.ai/v1",
apiKey: process.env.CHEAPAIMODEL_API_KEY,
});
const { text, reasoningText } = await generateText({
model: cheapaimodel("deepseek-v4-1-flash"),
prompt: "Explain recursion in one sentence.",
providerOptions: { cheapaimodel: { reasoningEffort: "low" } },
});
- The key under
providerOptionsis thenameyou gave the provider. WritereasoningEffortin camelCase:reasoning_effortthere is silently dropped. - AI SDK 7 also has a top-level
reasoning: "low"option that sends the same field. thinkingworks under the same key:providerOptions: { cheapaimodel: { thinking: { type: "disabled" } } }.
LiteLLM
import os
import litellm
response = litellm.completion(
model="openai/deepseek-v4-1-flash",
api_base="https://api.cheapaimodel.ai/v1",
api_key=os.environ["CHEAPAIMODEL_API_KEY"],
reasoning_effort="low",
messages=[{"role": "user", "content": "Explain recursion in one sentence."}],
)
- Keep the
openai/prefix. Withdeepseek/, LiteLLM turns the effort into DeepSeek's on/off switch and drops the level, solowandmaxboth become plain "thinking on". - On LiteLLM Proxy, set
reasoning_effortunder the model'slitellm_params. A value the client sends overrides it.
In coding tools and apps
Most tools only send the field if you tell them to. If a tool sends nothing, DeepSeek runs at high.
| Tool | Where to set it | Levels you can reach |
|---|---|---|
| Codex CLI | model_reasoning_effort in config.toml |
all four |
| Continue | requestOptions.extraBodyProperties on the model |
all four |
| Aider | --reasoning-effort, after declaring the setting (below) |
all four |
| Open WebUI | Model → Advanced Params → Reasoning Effort, set to Custom | all four |
| Zed | reasoning_effort on the model in available_models |
all four |
| OpenClaw | the model's compat settings (below) |
all four |
| n8n | OpenAI Chat Model → Options → Extra Body | all four |
| Cline | Reasoning Effort in the OpenAI Compatible settings, or --thinking |
none, low, high |
| Dify | Reasoning effort, after setting Thinking Mode Support (below) | none, low, high |
| Cursor | not available with a custom base URL | default only |
Tested with Codex CLI 0.163.0, Continue CLI 1.5.47, Aider 0.86.2, Cline CLI 3.0.71, and OpenClaw 2026.10.4; read from source for Open WebUI 0.12.2, Zed 1.24.2, the Dify OpenAI-API-compatible plugin 0.0.68, and n8n 2.43.6.
Codex CLI only talks to custom providers through the Responses API, so it sends reasoning.effort. Also set model_reasoning_summary = "none". Otherwise Codex adds reasoning.summary, which V4.1 Flash on cheapaimodel rejects with a 400.
model_reasoning_effort = "low"
model_reasoning_summary = "none"
If you leave model_reasoning_effort unset, Codex's banner says "reasoning effort: none", but it sends no effort at all, so the model runs at high.
Continue has no effort option for OpenAI-compatible models, but it adds any body field you list:
models:
- name: DeepSeek V4.1 Flash
provider: openai
model: deepseek-v4-1-flash
apiBase: https://api.cheapaimodel.ai/v1
apiKey: YOUR_API_KEY
requestOptions:
extraBodyProperties:
reasoning_effort: low
Aider ignores --reasoning-effort for models it doesn't know and prints a warning. Declare the setting in .aider.model.settings.yml:
- name: openai/deepseek-v4-1-flash
accepts_settings: ["reasoning_effort"]
Then run aider --model openai/deepseek-v4-1-flash --reasoning-effort low, or type /reasoning-effort low in the chat. Don't put the field in extra_params directly: Aider drops it there.
OpenClaw treats any custom base URL as a proxy and doesn't send an effort unless the model entry says it can. Add these fields to the entry from our OpenClaw guide:
{
id: "deepseek-v4-1-flash",
// ...the rest of the entry
reasoning: true,
compat: {
supportsUsageInStreaming: true,
supportsReasoningEffort: true,
supportedReasoningEfforts: ["none", "low", "high", "max"],
},
}
Then set a default in agents.defaults.models["cheapaimodel/deepseek-v4-1-flash"].params.thinking, for example "high". Without it, new sessions start at low, and OpenClaw rounds levels it doesn't list down, so medium becomes low.
n8n only shows its built-in Reasoning Effort option for OpenAI model names. Use Extra Body instead, and match the field to the API the node uses. With Use Responses API on, the default, write {"reasoning": {"effort": "low"}}. With it off, write {"reasoning_effort": "low"}.
Dify is the one to watch. With the default Thinking Mode Support, "Only Non-Thinking Mode", Dify sends no effort and only hides the reasoning from the reply. The model still reasons at high, and you still pay for those tokens. To actually turn reasoning off, choose a mode that includes thinking and set Reasoning effort to none.
Cursor doesn't send an effort for models behind a custom base URL, so they run at high.
On other OpenAI-compatible endpoints
Everything above applies to any provider that serves V4.1 Flash behind an OpenAI-compatible base URL. What varies is what the endpoint does with the field. Before you rely on it:
- Check that it arrives. Send the same prompt with
noneand withmax. Withnone,reasoning_tokensshould be 0 and the message should have noreasoning_content. If both requests come back looking the same, the endpoint is dropping the field and you're getting its default. - Check the model list. Some gateways expose each level as its own model ID, for example with a
-maxor-nonesuffix. If yours does, use those IDs. cheapaimodel has one ID,deepseek-v4-1-flash, and the field decides. - Check what a typo does. On cheapaimodel,
"reasoning_effort": "turbo"returns400with"code": "InvalidParameter", so a mistake fails loudly. An endpoint that drops values it doesn't recognize will quietly run at the default instead. - Stick to
none,low,high, andmax. DeepSeek's own API also accepts OpenAI'sminimal,medium, andxhighand maps them to the nearest level, but endpoints don't all map them the same way. In our tests,minimalbehaved more likehighthanlow. - Don't assume the rules carry over. Providers that serve the same model differ in the details. DeepSeek's documentation says its API returns
400fortool_choice: "required"in thinking mode and for tool conversations that dropreasoning_content. On cheapaimodel, both requests went through in our tests. Write your code to work under the stricter rules.
Three things that trip people up
max_tokens includes the reasoning
With reasoning_effort: "high" and max_tokens: 100, we got finish_reason: "length" and an empty content. All 100 tokens went to reasoning. If you cap output, leave room for it. When you don't set max_tokens, DeepSeek's API defaults to 64K in thinking mode and 128K at max.
Keep reasoning_content in tool conversations
When the model calls a tool, its message carries reasoning_content alongside tool_calls. DeepSeek's API requires you to send it back, unchanged, in every later request of that conversation. In the OpenAI Python SDK, appending the returned message object does that:
messages.append(completion.choices[0].message)
Libraries differ here. The OpenAI SDKs, LiteLLM with the openai/ prefix, and the Vercel AI SDK keep reasoning_content when you send the returned message back. LangChain's ChatOpenAI and ChatDeepSeek and LlamaIndex's OpenAILike leave it out of the next request. On cheapaimodel, leaving it out didn't cause an error in our test, but on an endpoint that enforces DeepSeek's rule, the request fails with a 400.
In conversations without tools, you don't need to send it back. DeepSeek ignores it.
Temperature doesn't steer reasoning
In thinking mode, temperature has no effect, and a top_p below 0.95 is treated as 0.95. To make answers faster or more careful, change the effort level instead.
Checking it on cheapaimodel
Open Logs in the console and click a request. If you sent reasoning_effort, the details show it under Reasoning effort. If the row isn't there, the request ran at the default, high.
Prices and context limits are on the DeepSeek V4.1 Flash model page. To get a key and make your first call, see the Quickstart. DeepSeek's own reference is its thinking mode guide.