Set Temperature

Su Suriya Ravichandran Updated 10 Nov 2026
10 min read ·Lesson 19 of 200

Important: current status (November 2026)

The temperature parameter, along with top_p and top_k, has been removed in Claude API version 2026-10-21, which is the version used by Anthropic Python SDK 2.0.0 and later. Requests that send these parameters are rejected, even at their default values. This lesson explains what temperature is, why you will still see it in older code and tutorials, what happens if you use it today, and how to achieve the same goals with current techniques.


What Temperature Is

When a language model writes a response, it produces text one token at a time. At each step it calculates a probability for every possible next token, and then samples one of them.

Temperature is a setting that changes how that sampling behaves:

TemperatureEffect on samplingTypical result
Low (for example, 0.0–0.3)Strongly favors the most likely tokensFocused, conservative, more repeatable wording
Default (1.0)Samples according to the model's probabilitiesNatural, varied responses
HigherGives less likely tokens more chanceMore varied, sometimes less coherent

In the Claude API, temperature accepted values from 0.0 to 1.0, with a default of 1.0.

Two related parameters controlled sampling in other ways:

ParameterWhat it did
top_p (nucleus sampling)Sampled only from the smallest set of tokens whose combined probability reached p
top_kSampled only from the k most likely tokens

All three were sampling parameters: they adjusted randomness in token selection, not the model's knowledge or reasoning.

A Common Misconception

Even when it was supported, temperature=0 did not guarantee identical output on every run. It made responses much more consistent, but not perfectly deterministic. Code that relied on exact repeatability was always fragile.


Current Status

Starting with API version 2026-10-21:

  • A Messages API request (or Message Batch request) that includes temperature, top_p, or top_k returns a 400 error, even if the value equals the default.
  • The SDK's 2.x releases no longer have these parameters in messages.create().
  • Requests are sampled with the defaults, including a temperature of 1.0. That is the same behavior as an older request that simply left the parameters out.
Model generationEffect of the change
Claude 4.7 and later, including all current modelsNo behavior change. These models already accepted only the default values.
Older models that accepted other values (for example, Claude Sonnet 4.6)Requests that lowered temperature for more consistent output lose that effect. No other setting replaces it.

If a workload truly depends on non-default sampling on an older model, the documented option is to keep that request on the previous API version (2023-06-01) by staying on SDK 1.x for it, as described in Lesson 5. For all current models, the parameters have no role.


What Happens If You Use It Today

With SDK 2.x

from anthropic import Anthropic

client = Anthropic()

message = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    temperature=0.2,   # This parameter no longer exists in SDK 2.x
    messages=[{"role": "user", "content": "Summarize the benefits of unit testing."}],
)

The method has no temperature parameter, so the call fails before any request is sent. Python raises a TypeError about an unexpected keyword argument, and type checkers flag the line in your editor.

Forcing It Through extra_body

The SDK lets you add raw fields to a request with extra_body:

message = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Summarize the benefits of unit testing."}],
    extra_body={"temperature": 0.2},
)

The request reaches the API, which rejects it with a 400 error (anthropic.BadRequestError). The parameter is removed in the API itself, not just hidden by the SDK.

Recognizing Legacy Code

You will still find code like this in older articles, repositories, and Stack Overflow answers:

# Legacy pattern: SDK 1.x / API version 2023-06-01
message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    temperature=0.0,
    messages=[...],
)

When you see temperature, top_p, or top_k in Claude code, recognize it as written for the older API version. Remove these parameters when moving the code to SDK 2.x and current models.


Achieving the Same Goals Today

Developers used temperature for two opposite goals: more consistency and more variety. Both can be achieved with current techniques, which are often more reliable than temperature ever was.

Goal 1: Consistent, Predictable Output

TechniqueHow it helpsLessons
Precise instructionsLeaves less room for variation in content, length, and wording31, 38
A fixed output formatConstrains what the answer can look like36, 37
Examples in the promptShows exactly the style and structure you expect35
Structured outputsMakes responses follow a defined schema101–110
Validation with retryAccepts only answers that meet your rulesThis lesson
Caching resultsReturns the stored answer for identical inputs, which gives truly identical outputThis lesson

The last technique deserves attention. If your application needs the same answer every time for the same input, for example a classification shown to users, store the first result and reuse it. That provides exact repeatability, which no sampling setting could guarantee.

Goal 2: Variety and Creativity

TechniqueHow it helps
Ask for several distinct options in one request"Give 5 different titles, each with a different tone." Claude deliberately varies them, which is more controlled than random sampling.
Explicit style direction"Playful", "formal", "use a metaphor from cooking"… Directed variety is more useful than random variety.
Varying the promptChange the angle, audience, or constraint between requests to explore different directions.

Default sampling already produces natural variation between runs. For brainstorming, explicitly asking for diverse options usually gives better results than relying on randomness alone.

What effort Does and Does Not Do

The effort setting (Lessons 13 and 151–153) controls how much the model thinks before answering. It affects depth, latency, and cost. It is not a randomness control and does not replace temperature.


Practical Example: Consistency Without Temperature

A classic use of temperature=0 was classification, where the same input should always get the same label. This example achieves consistency with current techniques: a precise instruction, validation of the answer, and caching of results.

"""consistent_classifier.py: stable classification without sampling parameters."""

from functools import lru_cache

from anthropic import Anthropic
from anthropic.types import Message

client = Anthropic()

LABELS = ("bug", "feature_request", "question", "billing")

SYSTEM_PROMPT = f"""You classify customer support tickets.
Reply with exactly one label from this list and nothing else: {", ".join(LABELS)}.
Rules:
- bug: something is broken or behaves incorrectly.
- feature_request: asks for new functionality.
- question: asks how to do something that already exists.
- billing: payments, invoices, refunds, or plans."""


def get_text(message: Message) -> str:
    return "".join(block.text for block in message.content if block.type == "text")


def request_label(ticket: str) -> str:
    message = client.messages.create(
        model="claude-opus-5-5",
        max_tokens=1024,
        output_config={"effort": "low"},
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": f"<ticket>\n{ticket}\n</ticket>"}],
    )
    return get_text(message).strip().lower()


@lru_cache(maxsize=10_000)
def classify(ticket: str, attempts: int = 2) -> str:
    """Return a validated label; identical tickets always get the same answer."""
    for _ in range(attempts):
        label = request_label(ticket)
        if label in LABELS:
            return label
    return "needs_review"


if __name__ == "__main__":
    tickets = [
        "The export button crashes the app on Android.",
        "Could you add dark mode?",
        "How do I change my profile picture?",
        "I was charged twice this month.",
        "The export button crashes the app on Android.",   # Repeated input
    ]
    for ticket in tickets:
        print(f"{classify(ticket):<16} {ticket}")
    print(classify.cache_info())

Example output:

bug              The export button crashes the app on Android.
feature_request  Could you add dark mode?
question         How do I change my profile picture?
billing          I was charged twice this month.
bug              The export button crashes the app on Android.
CacheInfo(hits=1, misses=4, maxsize=10000, currsize=4)

How It Works

  1. The system prompt defines a closed set of labels with a rule for each. Clear definitions are what make the classification consistent: Claude is not choosing words, it is applying rules.
  2. <ticket> tags separate the ticket text from instructions (Lesson 18).
  3. output_config={"effort": "low"} reduces thinking for this simple task, saving latency and tokens. It does not affect randomness.
  4. Validation: if label in LABELS accepts only exact, known labels. An unexpected answer, such as extra words, triggers one retry. If that also fails, the ticket is routed to "needs_review" instead of storing an invalid label.
  5. @lru_cache stores results by ticket text. The repeated ticket is answered from the cache, with no second API call. It is guaranteed to receive the same label, and costs nothing. cache_info() confirms one hit.

Note: lru_cache lives in memory and is cleared when the program stops. In production, store results in a database or a cache such as Redis, keyed by a hash of the input. For even stricter output shapes, use structured outputs (Lessons 101–110).


Practical Example: Variety Without Temperature

For creative tasks, ask for distinct options directly:

prompt = """Suggest 5 titles for a beginner tutorial about Python virtual environments.
Make each title use a different style:
1. straightforward, 2. question, 3. playful, 4. benefit-focused, 5. step-count ("in N steps").
Return only the numbered list."""

message = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=2048,
    messages=[{"role": "user", "content": prompt}],
)

titles = [
    line.split(".", 1)[1].strip()
    for line in get_text(message).splitlines()
    if line.strip()[:1].isdigit() and "." in line
]
print(titles)

Example output:

['Python Virtual Environments Explained', 'Why Does Every Python Project Need Its Own Environment?', 'Stop Fighting Your Dependencies: A Friendly Guide to venv', 'Keep Projects Clean and Conflict-Free with Virtual Environments', 'Set Up a Python Virtual Environment in 4 Steps']

How the parsing works: splitlines() splits the answer into lines. Lines that start with a digit and contain a period are list items. line.split(".", 1)[1] keeps everything after the first period, which removes the 1., 2., and so on. One request produces five deliberately different results, with more control over the kind of variety than random sampling could offer.


Common Mistakes

Copying temperature from Older Code

What happens: TypeError with SDK 2.x, or a 400 BadRequestError when sent through extra_body or raw HTTP with API version 2026-10-21.

Fix: remove temperature, top_p, and top_k. The scanning script in Lesson 5 finds them across a project.

Expecting Any Setting to Make Output Fully Deterministic

What happens: tests that compare exact output strings fail randomly.

Fix: test properties instead of exact text: the label is valid, the JSON parses, required fields exist, the length is within limits. For truly identical answers, cache the results.

Using effort as a Replacement for Temperature

What happens: expecting low effort to make answers less random.

Fix: effort controls thinking depth, cost, and latency. Use instructions, examples, structured outputs, and validation for consistency.

Relying on Randomness for Variety

What happens: repeated requests return similar ideas.

Fix: ask for multiple distinct options with explicit style directions in one request.


Best Practices

  • Do not use sampling parameters with SDK 2.x or current models. Treat them as legacy.
  • Get consistency from clear instructions, examples, fixed formats, and structured outputs.
  • Validate model output and retry or escalate when it does not meet your rules.
  • Cache results when the same input must always produce the same answer.
  • Get variety by asking for it explicitly and specifying how the options should differ.
  • Write tests that check properties, not exact wording.
  • Check the migration guide when you find legacy parameters in code you maintain (Lesson 5).

Exercise

  1. Try calling messages.create() with temperature=0.5 using SDK 2.x. What error do you get, and at what point does it occur?
  2. Run consistent_classifier.py and add three new tickets of your own, including one that is ambiguous. How is the ambiguous one labeled?
  3. Change classify() so that, when both attempts return an invalid label, it logs the invalid answers before returning "needs_review".
  4. Write a prompt that produces 3 different product descriptions for a reusable water bottle: one for athletes, one for students, and one for office workers.
Show answers for steps 1 and 3

Step 1: Python raises a TypeError for the unexpected keyword argument temperature when the method is called, before any network request is made. SDK 2.x has no such parameter.

Step 3:

import logging

logger = logging.getLogger(__name__)


@lru_cache(maxsize=10_000)
def classify(ticket: str, attempts: int = 2) -> str:
    invalid_answers = []
    for _ in range(attempts):
        label = request_label(ticket)
        if label in LABELS:
            return label
        invalid_answers.append(label)

    logger.warning("Unclassifiable ticket %r; model answers: %r", ticket[:80], invalid_answers)
    return "needs_review"

ticket[:80] limits how much of the ticket is written to the log, which keeps logs readable and avoids storing long, possibly sensitive text. %r shows the exact answers, including stray whitespace or punctuation, which helps you improve the prompt.

0 Comments

Reviewed before they appear

No comments yet.

Anthropic SDK Using Python
Anthropic SDK Intro Claude API Intro SDK Requirements Install Anthropic SDK Upgrade the SDK Create an API Key Set API Keys Use Environment Variables Import Anthropic Create a Client Send Your First Message Choose a Claude Model Set Max Tokens Read a Response Print Response Text Understand Message Blocks Use System Prompts Send User Messages Set Temperature Handle Stop Reasons Messages API Intro Create Messages Use Message Roles Send Conversation History Continue a Conversation Build a Chat Loop Reset Chat History Use Multiple Turns Inspect Message IDs Read Usage Data Write Clear Prompts Set a System Prompt Add Context to Prompts Use Prompt Templates Add Examples to Prompts Request JSON Output Use XML Tags Control Response Length Improve Prompt Quality Avoid Prompt Injection Read Text Blocks Read Content Blocks Check Stop Reasons Count Input Tokens Count Output Tokens Count Tokens Before Sending Limit Output Tokens Use Stop Sequences Read Request IDs Parse API Responses Streaming Intro Stream Text Output Use Stream Events Use Stream Helpers Get Final Messages Stream Async Responses Handle Stream Errors Build a Live Chat Stream Long Responses Close Streams Safely Build a Chatbot Keep Chat History Manage Chat Sessions Add Chat Memory Build a CLI Chatbot Build a Web Chatbot Use Flask with Claude Use FastAPI with Claude Return JSON from an API Add Chat Error Messages Async SDK Intro Create an Async Client Send Async Messages Use asyncio Run Parallel Requests Stream Async Text Handle Async Errors Set Async Timeouts Close Async Clients Choose Sync or Async Tool Use Intro Define a Tool Create Tool Schemas Send Tools to Claude Read Tool Calls Run Python Tools Return Tool Results Continue After Tool Use Control Tool Choice Handle Tool Errors Use the beta_tool Decorator Create a Tool Runner Add Tool Docstrings Validate Tool Inputs Use Multiple Tools Limit Tool Calls Log Tool Activity Build a Weather Tool Build a Search Tool Build a Calculator Tool Structured Output Intro Request JSON Data Validate JSON Output Use Pydantic Models Handle Invalid JSON Extract Fields from Text Generate Typed Data Use Image URLs Send Base64 Images Read PDFs with Claude Use Output Schemas Build Data Extraction Test Structured Responses Send Image Inputs Upload Files Use File IDs Process Text Files Summarize Documents Extract Table Data Handle File Errors Read Cache Usage Reduce Repeated Input Costs Debug Cache Misses Prompt Caching Intro Enable Prompt Caching Cache System Prompts Cache Long Context Test Cache Performance Use Cache Breakpoints Cache Best Practices Message Batches Intro Create a Message Batch Set Batch IDs Check Batch Status List Message Batches Get Batch Results Process Batch Outputs Handle Failed Batch Items Use Batches for Bulk Tasks Compare Batches and Requests Handle API Errors Handle Rate Limits Retry Failed Requests Set Request Timeouts Handle Network Errors Use Exponential Backoff Build Reliable API Calls Use Extended Thinking Log API Errors Track Request IDs Paginate API Results Set Thinking Budgets Read Thinking Blocks Use Tool Search Use Web Search Tools Use Computer Tools Use Citations Use Token Counting Read Raw Responses Set Custom Headers Use Claude on AWS Bedrock Use Claude on Vertex AI Use Claude on Microsoft Foundry Configure Cloud Credentials Choose a Cloud Provider Compare API Integrations Configure Provider Clients Handle Cloud Errors Use Cloud SDK Extras Deploy Cloud Apps Protect API Keys Use a .env File Ignore Secrets in Git Validate User Input Reduce Prompt Injection Limit Tool Permissions Avoid Unsafe Tool Calls Sanitize Tool Results Set Usage Limits Review Security Logs Test SDK Functions Mock API Responses Test Error Handling Test Streaming Code Measure Token Usage Track API Costs Configure Logging Deploy with Docker Deploy a FastAPI App Monitor Production Apps Build a Claude Chatbot Build a Text Summarizer Build a Code Explainer Build a JSON Extractor Build a PDF Assistant Build a Streaming Chat App Build a Tool-Calling Agent Build a Batch Processor Build a Research Assistant Build a Claude API Dashboard
Ask about this post
AI Ask about this post

Ask questions about Set Temperature and get answers drawn from it.

Signed-in readers only.