Back to posts
AINews

temperature=0 returns a 400 now, and the dial that replaced it is not a budget

Three flagship models shipped between September 1 and 3, and all three migration lists remove the sampling parameters. On Claude, any temperature other than 1.0 is a 400 error on nine named models. Gemini 3.8 Flash tells you to strip temperature, top_p and top_k, and drops candidate_count entirely. GPT-6 Astra tells you to remove temperature, top_p and logprobs. What replaced them is a five-value effort enum that Anthropic describes as a behavioral signal rather than a token budget, and that invalidates your prompt cache when you change it. Here is what breaks in a normal codebase, and what reproducibility looks like without a sampler.

This request now fails on every current Claude model:

{ "model": "claude-fable-5-1", "max_tokens": 4096, "temperature": 0,
  "messages": [{"role": "user", "content": "Extract the invoice total as JSON."}] }

The Messages API reference marks temperature deprecated and says a value of 1.0 is accepted for backwards compatibility, and "all other values will be rejected with a 400 error". The thinking documentation names the models: on Claude Fable 5.1, Mythos 5.1, Fable 5, Mythos 5, Mythos Preview, Opus 5, Opus 4.8, Opus 4.7 and Sonnet 5, "non-default temperature, top_p, or top_k values return a 400 error on every request, regardless of whether thinking is used."

Three flagship models shipped in three days — Claude Fable 5.1 on September 1, Gemini 3.8 Flash on September 2, GPT-6 Astra on September 3 — and each one published a migration list the same day. The lists differ in almost everything except this.

What each vendor removed

ModelParameters removedEnforcement
Claude Fable 5.1 (Sep 1)non-default temperature, top_p, top_k400 on every request, across nine models
Gemini 3.8 Flash (Sep 2)temperature, top_p, top_k deprecated; candidate_count unsupportedmigration list says to strip them from generation configs
GPT-6 Astra (Sep 3)temperature, top_p, top_logprobs, plus logprobs on Chat Completionsmigration list says to remove them

Google's migration checklist puts them under the heading "Remove deprecated sampling parameters", and the candidate_count line is the one to read twice: it is "unsupported in Gemini 3 and later", not just in 3.8 Flash. OpenAI's Astra guide instructs the same removal and adds that the model does not support the none reasoning effort.

The Anthropic restriction is the oldest of the three. It applies to every model released after Claude Opus 4.6, which is why this reads as a confirmed direction rather than a coincidence in one week. Two vendors caught up to a third inside seventy-two hours.

The replacement is a different kind of control

All three now expose one coarse enum instead. Anthropic uses output_config.effort with low, medium, high, xhigh and max, defaulting to high. OpenAI uses reasoning.effort with the same five names on Astra. Google uses thinking_level with low, medium and high, defaulting to medium, and minimal is not supported on 3.8 Flash.

It is tempting to treat that as a rename. It is not, and Anthropic's effort page says so directly:

Effort is a behavioral signal, not a strict token budget. At lower effort levels, Claude still thinks on sufficiently difficult problems, but thinks less than it would at higher effort levels for the same problem.

The numeric thinking budget went out on the same schedule as the numeric sampler. Setting thinking: {"type": "enabled", "budget_tokens": N} returns a 400 on Opus 4.7 and later, including Fable 5.1, and the documented mapping is to remove the budget and set an effort level instead. The page is explicit that this is a behavioural change and not a syntax change: "With a fixed budget, Claude thinks on every request. With adaptive thinking, Claude decides whether and how much to think on each request, and at lower effort settings it may skip thinking entirely on easy inputs."

Google made the identical substitution, an integer thinking_budget for a string thinking_level. So two controls disappeared together, and both of them were numbers that specified computation: one shaped the decode distribution, one capped the reasoning spend. What is left in their place expresses a preference and lets the provider allocate against it.

That is the part worth carrying past these three releases. You are no longer configuring the sampler. You are stating a priority to a scheduler you do not control, and the amount of computation you get for the same string is now the provider's decision, revisited per request.

The new dial is also a cache key

temperature had no billing consequence. Effort does, and this is the trap for anyone who ports the old habit of varying a parameter per call.

Changing the top-level effort value between requests invalidates prompt caching on the Claude API, because the value is rendered into the prompt. Anthropic's guidance is to pick a level at the start of a cached conversation and hold it. Fable 5.1, Mythos 5.1 and Opus 5 support a per-message form that preserves the cache, behind the beta header mid-conversation-output-config-2026-07-01:

{"role": "system", "content": [], "output_config": {"effort": "low"}}

Models without per-message support return a 400 reading output_config.effort requires a model that supports per-turn effort; this model does not. OpenAI documents the same shape for Astra, where mid-conversation effort changes go through configuration_update items specifically so the cached prefix survives.

So a per-request effort tweak that looks free is a cache miss on every turn it touches. On a long agent loop re-reading a large prefix, that is the largest line in the run, not a rounding error.

What this finds in a normal codebase

grep -rn --include='*.py' --include='*.ts' --include='*.js' --include='*.go' \
  -E 'temperature|top_p|topP|top_k|topK|candidate_count|candidateCount|logprobs|thinking_budget|thinkingBudget|budget_tokens' .

Most codebases return a small number of hits and they cluster in one file, because almost everyone sets these once in a shared client wrapper and never again. Four patterns are worth separating out of the results:

temperature: 0 for repeatable extraction. This is the common case and it has no parameter replacement. See below.

candidate_count above 1, or any generate-several-and-pick-one loop. Unsupported on Gemini 3 and later. The pattern still works, but it becomes N separate requests, which means N times the input cost unless the shared prefix is cached, and N times the latency unless you fan out. That is a budget change, not an edit.

logprobs read for a confidence threshold. If a router or a classifier decides between "answer" and "escalate to a human" by reading token probability, that signal does not exist on Astra. The branch needs a different input before the model ID changes, not after.

tool_choice set to any or a named tool to force schema-valid JSON. A 400 on Fable 5.1 and Mythos 5.1. The replacements are auto with strict tool use, or structured outputs; the Fable 5.1 post covers the mechanics.

Reproducibility without a sampler

Worth being honest about what is actually being lost, because the same API reference that deprecates temperature also says: "Note that even with temperature of 0.0, the results will not be fully deterministic."

So the line that a great deal of production code depends on was never delivering determinism. It was reducing variance and providing the feeling of a controlled experiment. If a test suite asserts string equality against a model response and passes today, it is passing on a sampler setting these APIs no longer accept, and it was already going to break on a silent serving change.

Four things do still reduce variance, and none of them are request parameters:

  1. Pin the dated snapshot, not the alias. An alias is a pointer the vendor moves. This is the same failure the model ID drift post covers, and it matters more now that the remaining knob is coarse.
  2. Pick one effort level per workload and freeze it. You need this for the cache anyway, so the correctness reason and the cost reason point the same way.
  3. Constrain the output shape rather than the decode. With structured outputs or strict tool use, the variation lands in prose you discard instead of in the field you parse. That is where the guarantee moved.
  4. Make evals read a distribution. Run the same input five times, report the agreement rate, and alert on the rate rather than on a diff. A single-sample golden-file eval is now measuring noise and calling it a regression.

The first three take an afternoon. The fourth is the one people skip, and it is the one that tells you whether an effort step-down from high to medium actually cost you anything on your own data — which is the only way to answer that question, since the effort levels are described in prose and calibrated differently by each vendor.

Reading the next one

Three vendors removed overlapping parameter sets in the same week, and none of the three announcements led with it. The removals were in the migration lists, under the benchmark tables, below the pricing.

The through-line is a boundary that moved. Parameters that describe what you want back — a schema, a tool contract, a max token count, a cache TTL — are still yours. Parameters that reached into how the model computes are becoming vendor-managed, exposed as a preference with a name instead of a number. temperature, top_p, top_k, candidate_count, logprobs and budget_tokens are all on the far side of that line.

When the next flagship ships, the migration list is the part that costs you time, and the removals are the part of the migration list that costs the most. Read it before the benchmark table.

For the vocabulary, /glossary covers temperature, top-p and reasoning model. For the models themselves, see Claude, Gemini and ChatGPT, or the three-way comparison.

Get the next post when it ships

One email on Sunday with the new post and a short list of what shipped that week — new guides, tool updates, and a couple of links worth reading.