Choosing the right reasoning level
On this page
Lesson rewritten on November 2, 2026. It previously contrasted Mistral Small’s “adjustable” reasoning with Magistral’s “native” reasoning, but Magistral was retired on July 31, 2026. The choice now lies between generalist models and
reasoning_effortlevels. Sources: Reasoning · Small 4 and Large 4 model cards.
Two dials instead of a model lineup
Choosing a reasoning model at Mistral used to mean picking between two distinct lineups. Today, it means adjusting two dials: the model (Small 4 for most tasks, Large 4 for the hardest cases) and the reasoning level (none or high on Small 4; low, medium, or high on Large 4). A single application can, and often should, use multiple combinations.
The decision matrix
| Situation | Starting setting | Why |
|---|---|---|
| Factual question, rephrasing, extraction | Small 4, none | Nothing to deliberate: reasoning would only add latency and tokens |
| Multi-step calculation, routine debugging, simple comparison | Small 4, high | Reasoning corrects chaining errors for a modest cost |
| Summarization or rephrasing on Large 4 | Large 4, low | Large 4 does not accept none; low is its most economical level |
| Multi-criteria analysis, migration plan, subtle bug | Large 4, medium then high | Test the intermediate level first; step up if quality demands it |
| Critical decision (legal, financial, medical) | Large 4, high + verification | Reasoning reduces errors but doesn’t eliminate them: a second pass or human review remains necessary |
This matrix provides starting points, not absolute truths: your own evaluations decide. Also remember that Large 4 is in Public Preview as of November 2, 2026.
Calculate before you scale
The listed rates (per million tokens, recorded on November 2, 2026) let you estimate the cost of a setting from the usage field in responses:
RATES = { # USD per million tokens: (input, output)
"mistral-small-2603": (0.15, 0.60),
"mistral-large-4-0": (0.70, 2.10),
"mistral-medium-3-5": (1.50, 7.50), # deprecated, retirement on April 30, 2027
}
def cost(response, model):
"""Cost of a response, including reasoning (excluding cache discounts)."""
input_rate, output_rate = RATES[model]
u = response.usage
return (u.prompt_tokens * input_rate + u.completion_tokens * output_rate) / 1_000_000
Sum this cost per request type over a few days of real traffic: that figure tells you whether a generalized high setting is sustainable.
A routing architecture
In a real application, most requests are simple. Paying for reasoning on these adds no value. The following router first asks Small 4, without reasoning, to estimate the question’s complexity, then routes the query to the appropriate setting:
import os
from mistralai.client import Mistral
class ReasoningRouter:
"""Routes each question to a model and a reasoning level."""
def __init__(self):
self.client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
def complexity(self, question):
r = self.client.chat.complete(
model="mistral-small-2603",
messages=[{"role": "user", "content":
f"Rate the complexity of this question from 0 to 10. Reply with only the number: {question}"}],
reasoning_effort="none",
)
try:
return min(max(int(str(r.choices[0].message.content).strip()), 0), 10)
except ValueError:
return 5 # conservative value if the response isn't a number
def respond(self, question, system_prompt=None):
score = self.complexity(question)
if score <= 3:
model, level = "mistral-small-2603", "none"
elif score <= 7:
model, level = "mistral-small-2603", "high"
else:
model, level = "mistral-large-4-0", "high"
messages = [{"role": "system", "content": system_prompt}] if system_prompt else []
messages.append({"role": "user", "content": question})
return self.client.chat.complete(model=model, messages=messages, reasoning_effort=level)
The classification call costs little: a few dozen tokens on the cheapest model, without reasoning. Adjust the thresholds after observation, comparing the quality and cost of each branch.
Production best practices
Log usage by branch. For every response, store the model, the level, usage.prompt_tokens, usage.completion_tokens, and the calculated cost above. Without these numbers, you cannot tell if reasoning pays off.
Pin dated identifiers. In production, use mistral-small-2603 rather than mistral-small-latest: an alias can switch to a new version without your code changing. Centralize these identifiers in a single configuration.
MODELS = {
"fast": ("mistral-small-2603", "none"),
"reasoning": ("mistral-small-2603", "high"),
"deep": ("mistral-large-4-0", "high"),
}
Plan a fallback. Since Large 4 is in Public Preview, a fallback to Small 4 in high mode protects your service if the call fails. All SDK HTTP errors inherit from MistralError:
from mistralai.client import errors
def query_with_fallback(client, messages):
try:
return client.chat.complete(model="mistral-large-4-0", messages=messages, reasoning_effort="high")
except errors.MistralError:
return client.chat.complete(model="mistral-small-2603", messages=messages, reasoning_effort="high")
Watch for deprecations. The Mistral models page lists deprecation and retirement dates. Medium 3.5 will be retired on April 30, 2027: if you use it, the deadline is already set.
Course summary
Reasoning gives the model a space to think before answering; at Mistral, you configure this per request with reasoning_effort, whose values depend on the model. The response then arrives as fragments—thinking then answer—which you must know how to read, including in streaming mode, and replay in full for multi-turn conversations. Agents and the Conversations API carry the same setting in completion_args. Magistral is retired: Small 4 and Large 4 take over, with Medium 3.5 serving only as a transitional step. Finally, reasoning is justified where there are paths to explore and errors to catch (math, code, decisions), and it must always be measured: quality, tokens, latency.
Key takeaways
- Two dials: the model (Small 4, Large 4) and the
reasoning_effortlevel - Small 4 in
nonefor simple tasks, inhighfor multi-step; Large 4 for the hardest cases - Calculate each setting from
usageand official rates before scaling it - A router reserves reasoning for queries that benefit from it
- In production: dated identifiers, usage logging, fallback from Large 4 to Small 4
Test your knowledge
Five questions to validate the course essentials.
1. Which reasoning_effort values does Mistral Large 4 accept, and which one does it reject?
Answer: low, medium, and high (documentation recommends high as a starting point). It rejects none: the level formerly called that in its preview is now named low.
2. Where is the thinking text located in a response with reasoning?
Answer: In a ThinkChunk (type thinking) within the message.content list. Its thinking field is itself a list of TextChunk objects, from which you read the text field. The final answer is in a top-level TextChunk.
3. What must you put back into the history of a multi-turn conversation in Chat Completions?
Answer: The assistant’s complete message, including thinking fragments. Removing the thinking saves tokens but significantly degrades the quality of subsequent turns.
4. Your code still calls magistral-medium-latest: what should you do?
Answer: Migrate immediately, as Magistral was retired on July 31, 2026. Target Small 4 if quality suffices, otherwise Large 4 with reasoning_effort="high"; Medium 3.5, the designated replacement, is itself deprecated until April 30, 2027. Remove prompt_mode and the thinking template from system prompts.
5. How do you set reasoning_effort in a Mistral agent?
Answer: In the agent’s completion_args field, for example completion_args={"reasoning_effort": "high"}. With the Conversations API, use the same field at each start or append.