Most developers ship their first LLM integration with temperature set to whatever the API default is, tweak it once when outputs feel “too boring” or “too random,” and never think about it again. That’s a mistake that shows up in production as hallucinated data extractions, inconsistent agent behavior, and creative outputs that are somehow both chaotic and dull. Understanding temperature top-p LLM sampling isn’t theoretical — it directly determines whether your agent is reliable enough to run unsupervised.
This article gives you a decision framework you can apply immediately. By the end, you’ll know exactly which settings to use for structured extraction, coding assistants, creative generation, and multi-step agents — and why the wrong setting in each context actively costs you quality.
What Temperature and Top-P Actually Control
When an LLM generates the next token, it produces a probability distribution over its entire vocabulary — sometimes tens of thousands of candidates. Both temperature and top-p are mechanisms for reshaping or filtering that distribution before sampling. They’re not the same thing, and using them interchangeably is a common mistake.
Temperature: Sharpening or Flattening the Distribution
Temperature scales every logit (raw score) before the softmax function converts them to probabilities. A temperature of 1.0 leaves the distribution unchanged. Below 1.0 sharpens it — the highest-probability tokens become even more dominant, low-probability tokens get suppressed toward zero. Above 1.0 flattens it — the model spreads probability mass more evenly across candidates, making unlikely tokens more competitive.
At temperature 0, you get greedy decoding: the model always picks the single highest-probability token. This is deterministic but not always the same as “best” — greedy decoding can get trapped in repetitive loops because it never considers that a slightly lower-probability word might open up better continuations.
import anthropic
client = anthropic.Anthropic()
# Low temperature — consistent, predictable output
response_precise = client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=200,
temperature=0.1, # Nearly deterministic
messages=[{"role": "user", "content": "Extract the invoice total from: 'Amount due: $1,247.50'"}]
)
# High temperature — more varied, creative output
response_creative = client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=200,
temperature=0.9, # Broad exploration
messages=[{"role": "user", "content": "Write an opening line for a thriller novel set in a data center."}]
)
Top-P: Truncating the Candidate Pool
Top-p (also called nucleus sampling) works differently. Instead of scaling probabilities, it filters the vocabulary to only the smallest set of tokens whose cumulative probability reaches the threshold P. If top-p is 0.9, the model only samples from tokens that collectively account for 90% of the probability mass — everything in the long tail gets zeroed out.
The practical difference: temperature changes how much the model “wants” low-probability tokens. Top-p changes which tokens are even eligible for selection. On a token where the model is very confident, top-p 0.9 might only include 3-5 candidates. On an ambiguous token, it might include hundreds. Temperature 0.5 always applies the same scaling regardless of confidence level.
Most APIs let you set both simultaneously. The conventional wisdom is to adjust one, not both — and I’d agree with that for most cases. If you set temperature 0.3 AND top-p 0.3, you’re double-constraining the distribution in ways that interact non-linearly and make your system harder to reason about.
The Production Failure Modes Nobody Warns You About
Before getting into recommended values, it’s worth understanding how wrong settings actually fail — because the failures are subtle enough to pass basic testing.
High temperature on structured extraction: You’re pulling JSON from a document. At temperature 0.8, the model will occasionally decide that a field value “could reasonably be” something slightly different from what’s in the source. Not hallucination in the dramatic sense — more like confident paraphrasing that breaks your schema validation or introduces data drift across thousands of runs. You won’t catch this in a 10-document test.
Low temperature on multi-step reasoning: Counterintuitively, temperature 0 can hurt complex reasoning tasks. When the model hits a reasoning step where multiple valid approaches exist, greedy decoding forces it down one path without ever exploring alternatives. Some chain-of-thought research shows temperature around 0.5-0.7 actually improves final accuracy on math and logic benchmarks because the model’s reasoning process benefits from some exploration.
Low top-p with high temperature: This combination is particularly treacherous. You flatten the distribution (high temp) but then only allow tokens from a small nucleus (low top-p) — so you get frequent sampling from whatever weird tokens made it into the narrow nucleus at elevated probability. The outputs feel random but in a constrained, repetitive way.
Recommended Settings by Task Type
Structured Data Extraction and Classification
Use temperature 0 to 0.2, top-p 1.0. You want the model to reproduce what’s in the source, not improvise. The only reason not to go to absolute zero is that some models exhibit minor repetition artifacts at exactly 0 — 0.1 is a safe default that’s functionally deterministic.
def extract_structured_data(raw_text: str) -> dict:
"""
Extraction task — near-zero temperature for consistency.
At Haiku pricing (~$0.00025/1K input tokens),
you can run this ~4000 times for $1.
"""
response = client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=500,
temperature=0.1, # Near-deterministic
top_p=1.0, # Don't restrict nucleus — temperature handles it
messages=[{
"role": "user",
"content": f"""Extract the following fields as JSON:
- company_name
- invoice_date (ISO format)
- total_amount (number, no currency symbol)
- line_items (array)
Document:
{raw_text}
Return only valid JSON, no explanation."""
}]
)
return response.content[0].text
Code Generation and Debugging
Temperature 0.2 to 0.4. Code has right and wrong answers, so you don’t want wild variation — but zero temperature produces surprisingly repetitive code that often misses elegant solutions that were slightly less probable. A small amount of exploration helps the model consider cleaner approaches. For code review or explanation tasks (no generation), drop to 0.1.
One practical note: if you’re running code generation in a loop (e.g., generating test cases or boilerplate), temperature 0.3 with a varied system prompt produces better diversity than cranking temperature to 0.8, which just makes the code wrong more often.
Summarization and Analysis
Temperature 0.3 to 0.5. You want the model to accurately represent the source material (argues for lower) but you also benefit from some flexibility in how it phrases and structures the output (argues for higher). The sweet spot for most summarization pipelines I’ve run in production is 0.3 — faithful to source, but not robotically literal.
Creative Writing and Brainstorming
Temperature 0.7 to 1.0, top-p 0.9 to 0.95. This is where higher values genuinely help. The model’s most predictable continuations are often clichés — “the dark and stormy night,” the obvious product name, the expected plot beat. Elevated temperature pushes past those into territory that feels more original.
Top-p 0.95 rather than 1.0 here is actually useful: it eliminates true garbage tokens (typos, Unicode artifacts) from the nucleus while still allowing broad exploration. Don’t go below top-p 0.85 for creative tasks — you’ll start noticing the output feeling oddly constrained even at high temperatures.
def brainstorm_names(product_description: str, count: int = 10) -> list[str]:
"""
Creative task — higher temperature, full nucleus.
Run multiple times and merge results for best diversity.
"""
response = client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=300,
temperature=0.95, # High creativity
top_p=0.95, # Slight filtering of garbage tokens
messages=[{
"role": "user",
"content": f"""Generate {count} creative product name options for:
{product_description}
Rules: names should be memorable, 1-3 words, no generic terms.
Return one name per line, no numbering."""
}]
)
names = response.content[0].text.strip().split('\n')
return [n.strip() for n in names if n.strip()]
Conversational Agents and Chatbots
Temperature 0.5 to 0.7. You want natural-sounding variation across turns (so the bot doesn’t sound like a robot repeating the same phrases) but consistency in facts, policy adherence, and tone. For customer support agents where accuracy matters more than personality, lean toward 0.5. For companion or coaching apps, 0.7 feels more human.
Multi-Step Agents: The Special Case
Agents that call tools, make decisions, and route between tasks deserve their own consideration. The right approach is different temperatures for different agent components — not one global setting.
Tool selection and routing decisions: temperature 0.1 to 0.2. These are functional choices where consistency is critical. If your agent randomly decides to call the “web_search” tool instead of “database_query” 15% of the time due to high temperature, your whole pipeline becomes unpredictable.
Final response generation after tool calls: temperature 0.5 to 0.7. The factual work is done — the agent now just needs to synthesize a response. Some variation here is fine and makes the output more natural.
class AgentOrchestrator:
def __init__(self):
self.client = anthropic.Anthropic()
def decide_tool(self, user_query: str, available_tools: list) -> str:
"""Tool selection — low temperature, high consistency."""
response = self.client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=100,
temperature=0.1, # Deterministic routing
messages=[{
"role": "user",
"content": f"Select the best tool for: '{user_query}'\nTools: {available_tools}\nReturn only the tool name."
}]
)
return response.content[0].text.strip()
def synthesize_response(self, tool_result: str, original_query: str) -> str:
"""Response generation — higher temperature for natural output."""
response = self.client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=500,
temperature=0.6, # More natural, still grounded in tool result
messages=[{
"role": "user",
"content": f"Based on this data: {tool_result}\n\nAnswer the user's question: {original_query}"
}]
)
return response.content[0].text
What the Docs Get Wrong
OpenAI’s documentation suggests temperature and top-p are interchangeable ways to control randomness. They’re not — they’re orthogonal mechanisms. Anthropic’s docs are better but don’t give concrete task-type guidance. Most framework docs just say “adjust as needed,” which is useless.
The other thing documentation consistently undersells: these settings interact with your prompt design. A very constrained prompt (“Return only the number, nothing else”) can achieve near-deterministic extraction even at temperature 0.7, because the model has almost no degrees of freedom. A vague prompt at temperature 0.1 can still produce wildly inconsistent outputs because the distribution of valid completions is inherently wide. Temperature and top-p are the last layer — fix your prompts first.
Quick Reference: Settings by Use Case
- Data extraction / JSON parsing: temp 0.1, top-p 1.0
- Classification / routing: temp 0.0–0.1, top-p 1.0
- Code generation: temp 0.2–0.4, top-p 1.0
- Summarization / analysis: temp 0.3–0.5, top-p 1.0
- Conversational agents: temp 0.5–0.7, top-p 0.95
- Creative writing / brainstorming: temp 0.8–1.0, top-p 0.95
- Agent tool selection: temp 0.1, top-p 1.0
Bottom Line: Who Should Change What
If you’re a solo founder shipping an automation pipeline — default to temperature 0.1 for anything that touches structured data or decisions, 0.6 for anything user-facing. Don’t overthink it. The prompt design matters more than single-decimal temperature differences.
If you’re building a product with creative features — invest time tuning temperature for your specific creative tasks. Run 50-100 generations at temperature 0.7, 0.85, and 1.0 and evaluate them blind. The difference is real and worth the hour it takes.
If you’re running multi-step agents at scale — implement per-step temperature controls, not a global setting. Your tool-selection logic deserves temperature 0.1 even if your output synthesis runs at 0.7. The infrastructure overhead is minimal and the reliability improvement is significant.
The core principle behind all of it: temperature top-p LLM settings are reliability dials, not quality dials. Higher temperature doesn’t make the model smarter — it makes it more willing to stray from the highest-probability path, which helps creativity and hurts precision. Match the dial to the task, not to some intuition about what “better” means in the abstract.
Editorial note: API pricing, model capabilities, and tool features change frequently — always verify current details on the vendor’s website before building in production. Code examples are tested at time of writing; pin your dependency versions to avoid breaking changes. Some links in this article may be affiliate links — we may earn a commission if you sign up, at no extra cost to you.

