Stop Asking a Chat Model to Decide: Clef, Decider and the Typed-Probability Turn
💡 Tool Tip:API Tester, JSON Formatter, Regex Tester
Decision models went from a curiosity to a category in about two weeks. On October 1, 2026, Cloudflare released Clef and Clef-flash, hosted on Workers AI and fully open-sourced on Hugging Face under Apache 2.0. The same day, Perplexity published pplx-decider-v1-27b on Hugging Face under Apache 2.0 and opened a hosted Decisions API. Both do the same thing: they do not write prose, they return a verdict.
A decision model swaps a paragraph for a number
1. What a decision model is
Cloudflare's own definition is the clearest one going. Classifiers have existed for a while, but a decision model is a model that helps an agent decide how to act: you pass in inputs, such as a customer support message, and ask whether it is urgent and which team should handle it. It returns typed answers with probabilities, and your code uses those numbers to route the ticket, trigger an escalation, or defer to a human. Unlike an LLM it is not endlessly open-ended, and it does not need retraining every time you add a category. As Cloudflare puts it, a human no longer necessarily needs to be in the loop: agents can gather context, decide, act, and defer only when needed. The practical question each of them answers is the same one: given this input, what should happen next, and how confident is the system that it is right?
# A decision model answers questions about state. It does not chat.
# Ask for a yes/no probability (noul) and threshold the number yourself.
import json, urllib.request
state = open("ticket.txt").read() # the content to judge
questions = {
"is_urgent": "noul", # probability of yes
"team": {"choice": ["billing", "platform", "abuse", "other"]},
"severity": {"score": ["p1", "p2", "p3", "p4"]},
} # up to 128 questions in one request
body = json.dumps({"model": "pplx-decider-v1-27b",
"state": state, "questions": questions}).encode()
req = urllib.request.Request(
"https://openrouter.ai/api/v1/decisions", data=body,
headers={"Authorization": "Bearer $KEY", "Content-Type": "application/json"})
resp = json.loads(urllib.request.urlopen(req, timeout=60).read())
# -> typed, probabilistic, no prose to parse2. The Clef specifics
Clef comes in two sizes: Clef is a 27-billion-parameter model for the most accurate answers, and Clef-flash is a 9-billion-parameter model built for answers in a few tens of milliseconds. Both run on Workers AI, and the weights are on Hugging Face under Apache 2.0 so you can run them yourself. Cloudflare highlights three differences from its closest rival: a vision encoder, so it can classify images where Jev only did text; a 64k context window against Jev's 32k, so you can squeeze more input state in; and full Jev API compatibility, so most code written for Jev works unchanged. There is also a new reinforcement-learning product for fine-tuning Clef.
# The application, not the model, owns the threshold.
# Write it down, version it, and log every near-miss.
ROUTING = {
"urgent_threshold": 0.80, # above this, page a human
"auto_route_threshold": 0.65, # above this, route automatically
"escalate_band": (0.45, 0.65), # ambiguous: hand to a human queue
}
def route(decision):
p = decision["is_urgent"]["yes"]
team = max(decision["team"]["probs"], key=decision["team"]["probs"].get)
conf = decision["team"]["probs"][team]
if p >= ROUTING["urgent_threshold"]:
return {"action": "page", "team": team, "p_urgent": p}
if conf >= ROUTING["auto_route_threshold"]:
return {"action": "auto_route", "team": team, "confidence": conf}
return {"action": "human_queue", "reason": "ambiguous_band",
"p_urgent": p, "confidence": conf} # log this, tune laterYour code thresholds a probability instead of parsing a chat reply
3. Read the benchmark table carefully
Cloudflare states that Clef is currently the leader on the Jev Decision Index, and publishes a table to support it. Some of those numbers are worth remembering: BFCL case exact 98.47 against Jev's 98.76 and DiffusionGemma Jev's 95.75; ToolRet nDCG@10 69.19 against Jev's 66.43; API-Bank accuracy 91.93 against Jev's 93.11; home appliances case exact 82.95 against Jev's 97.73; and When2Call accuracy 72.37 against Jev's 80.97. These are vendor-reported, and Clef does not win every row - it loses the last two clearly. The more convincing evidence is Cloudflare's own threat-intelligence workflow: classifying a domain took Clef 2.2 seconds, while the fastest general LLM, gpt-oss-120b, took 4.7 seconds in the same workflow and returned only two classifications.
# A bounded decision is only safe to automate when it is reversible.
# Same model call, three different action classes.
DECISION_CLASSES = {
"auto": {"reversible": True, "logged": True, "human": False},
"notify": {"reversible": True, "logged": True, "human": "post_hoc"},
"human_gate": {"reversible": False, "logged": True, "human": "pre_approval"},
}
def act(decision, cls_name):
cls = DECISION_CLASSES[cls_name]
if cls["human"] == "pre_approval":
return queue_for_approval(decision)
if cls["human"] == "post_hoc":
notify_owner(decision)
return execute(decision, rollback=cls["reversible"])
# Probability tells you how sure the model is.
# Reversibility tells you whether you are allowed to care.4. How Perplexity's Decider is shaped
According to the OpenRouter model page, Decider V1 27B was released on October 1, 2026. It reads content passed as state and returns typed, probabilistic answers to one or more named questions in a single request: the probability of yes for a yes/no question (noul), a probability for every option plus the most likely one (choice), or a probability for every level of an ordered rubric plus the expected score (score). It is built for classification, routing, moderation and rubric grading, where application code thresholds the returned numbers rather than parsing a chat reply. A request can carry up to 128 questions about the same content, the context window is 262,144 tokens, and pricing is $0.04 per million input tokens with free output.
# Rubric grading: get a probability per level plus an expected score.
# Useful for content scoring where you need a number, not a paragraph.
rubric = {
"technical_accuracy": {"score": ["0", "1", "2", "3"]},
"citations_present": "noul",
"tone_suitable": "noul",
"length_ok": "noul",
}
def accept(graded, min_expected=2.2, min_cite_prob=0.85):
return (graded["technical_accuracy"]["expected"] >= min_expected
and graded["citations_present"]["yes"] >= min_cite_prob
and graded["tone_suitable"]["yes"] >= 0.80)
# Two numbers and a boolean replace a paragraph you would have had to parse,
# regex, and argue about in code review.A 9B model sits on the hot path; the big model does open-ended reasoning
5. Where it belongs in an agent
Split the decisions. Bounded ones - classification, routing, escalation, scoring - go on the hot path and should use a decision model. Open-ended ones, where you need an explanation, a novel plan, or code, stay with a large model. The real win from a decision model is not price, it is that there is nothing to parse: your code receives a number and compares it to a threshold you wrote down. No parse failures, no format drift, no retry loop built only to make a chat model emit JSON. Two things stay your responsibility, though - application code must own the thresholds, and the actions taken must be reversible and logged.
# Benchmark the decision against the LLM it would replace,
# on the same task, before you migrate anything.
def bench(task_inputs, decision_model, chat_model, runs=50):
t0 = time.perf_counter()
for x in task_inputs[:runs]:
decision_model.decide(x) # bounded output
decision_ms = (time.perf_counter() - t0) / runs * 1000
t1 = time.perf_counter()
for x in task_inputs[:runs]:
parse(chat_model.complete(x)) # prose you must parse
llm_ms = (time.perf_counter() - t1) / runs * 1000
return {"decision_ms": round(decision_ms, 1),
"llm_ms": round(llm_ms, 1),
"parse_failures": chat_failures(), # the hidden cost
"cost_per_task_usd": cost_per_task()}6. When not to use one
Keep the LLM when you need a rationale: compliance explanations, user-facing justifications. Keep it when the categories are still evolving and their definitions are unsettled. Keep it when reaching a judgement requires multi-step reasoning. And keep it whenever a single wrong number could cause irreversible harm - unless there is a human approval gate in front. A decision model turns uncertainty into an observable number, which is a real advance, but it does not tell you what that number should mean. That judgement stays in your code and your process. Treat the number as evidence, not as authority. A calibrated probability plus a threshold you own is a much better arrangement than a well-written paragraph you have to interpret.
📌 Frequently Asked Questions
What is a decision model?
Per Cloudflare's definition, classifiers have existed for some time, but a decision model helps an agent decide how to act: you pass in inputs such as a customer support message and ask whether it is urgent and which team should handle it. The model returns typed answers with probabilities, and your code routes, escalates or defers to a human. It does not need retraining to add categories, and unlike an LLM it is not open-ended.
What are the key specs of Cloudflare's Clef?
Clef and Clef-flash were released on October 1, 2026 and hosted on Workers AI. Clef is a 27B-parameter model and Clef-flash is a 9B model; weights are on Hugging Face under Apache 2.0 for local use; it has a vision encoder, so it can classify images; its context window is 64k against Jev's 32k; and it is fully Jev-API compatible. Cloudflare also launched an RL fine-tuning product.
Should you trust the published benchmarks?
Cloudflare says Clef currently leads the Jev Decision Index, but the numbers are vendor-reported and Clef does not win every row: in the published table, home appliances case exact is 82.95 against Jev's 97.73, and When2Call accuracy is 72.37 against Jev's 80.97. Stronger evidence is Cloudflare's own threat-intelligence example, where classifying a domain took 2.2s versus 4.7s for gpt-oss-120b, which also returned only two classifications.
How does Perplexity's Decider V1 27B work?
Per OpenRouter, it was released October 1, 2026. It reads content passed as state and returns typed, probabilistic answers: probability of yes (noul), a probability per option plus the most likely one (choice), or a probability per rubric level plus the expected score (score). It accepts up to 128 questions per request, has a 262,144-token context window, and costs $0.04 per million input tokens with free output. Note it uses a Decisions API, not an OpenAI-compatible chat endpoint.
When should you not use a decision model?
When you need a rationale or explanation, such as compliance notes or user-facing justifications. When categories are still evolving and their definitions unsettled. When the judgement requires multi-step reasoning. And whenever a single wrong number could cause irreversible harm, unless a human approval gate sits in front of the action.