AI Decision Models Explained: Clef-Flash vs Jev
A lot of the LLM calls in my automation work aren't really asking for text. They're asking a question with three or four possible answers. Is this message a complaint or a question? Which team should get this ticket? Is this PDF an invoice, a receipt or someone's holiday photos? (It happens.)
For that kind of question, an LLM is overkill. It writes a small JSON essay, you parse it, and you pay for every token of the essay.
AI decision models skip the essay. You hand them the input and a set of typed questions, and they return a probability for every answer you allowed. No generated text, no broken JSON, and no output tokens on the bill. For easy decisions they're cheaper, faster and more reliable than an LLM, and after a couple of weeks with Cloudflare's Clef-Flash I want one in most of my pipelines.
I built a small demo so you can try one yourself: Triage Desk. Below I'll cover what these models are, how I'm using Clef-Flash, where they fall over, and how they compare with Jev, the model that started all this.
What is an AI decision model?
An AI decision model is a model that answers questions you define, using answer options you define, and returns a probability for each option instead of generating text. You send it the input (called the state) plus a set of typed questions, and it scores every option in one pass.
That's the whole trick. It reads, it scores, it stops. The new part is that you set the answer options per request, so there's no training step and no labelled dataset to collect before you start.
Decision model vs LLM
Here's how it compares with the tools you'd otherwise reach for.
| LLM with JSON mode | AI decision model | Trained classifier | Rules engine | |
|---|---|---|---|---|
| Output | Generated text you parse | A probability per answer you defined | A probability per fixed label | One exact outcome |
| Answer options set | Loosely, by prompt or schema | Per request | At training time | When you write the rules |
| Can return an invalid answer | Rarely with strict schemas, more often without | No | No | No |
| You pay for | Input and output tokens | Input tokens only | Your own compute | Nothing |
| Typical latency | Hundreds of ms to seconds | Tens to hundreds of ms | A few ms | Microseconds |
| Handles reasoning | Yes | Barely | No | No |
| Reads messy text | Yes | Yes | Yes, for its labels | No |
The row I care about most is the invalid-answer one. JSON mode and structured outputs constrain what an LLM is allowed to generate, but it's still generating, token by token, and you still pay for every token. They're great when you actually need text. A decision model never generates anything, so there's nothing to parse and nothing to repair.
The three question types
Every question has one of three types:
noulis a yes/no question. You get back the probability of yes. (The name comes from Jev's API. I didn't pick it.)choicepicks one of 2 to 255 named options and returns a probability for each, plus a confidence value.scorerates something on an ordered scale of 2 to 10 levels, lowest first. You get a probability per level and a weighted score that can land between levels.
A request looks like this:
{
"model": "clef-flash",
"state": { "message": "Checkout has been failing for every customer for the last hour." },
"questions": {
"urgent": {
"type": "noul",
"instructions": "Does `message` describe a problem blocking customers right now?"
},
"team": {
"type": "choice",
"instructions": "Which team should handle `message`?",
"criteria": {
"billing": "Payments, invoices, refunds",
"technical": "Outages, errors, bugs",
"other": "Anything that fits neither team"
}
},
"severity": {
"type": "score",
"instructions": "How severe is the customer impact?",
"criteria": ["No impact", "Minor", "Major", "Critical"]
}
}
}Clef accepts up to 64 questions in one request, all asked about the same state. That's where the economics get a bit silly. TypeSafe's cookbook measured 13 questions in a single request as 12.2x cheaper and 10x faster than asking them one at a time.
Not the DMN kind
Quick detour if you landed here from a search. "Decision model" also means DMN, the OMG standard for decision tables and diagrams, plus a pile of management frameworks like Vroom-Yetton. Different thing entirely. This article is about the machine learning kind. If you came for decision tables, stick around anyway. You might end up replacing a few of them.
Try it: Triage Desk
Triage Desk is a support inbox with nobody working in it. Paste a customer message, or pick one of the presets, and Clef-Flash answers five questions about it in a single call:
- Is it urgent?
- Which team should get it (billing, technical, sales or other)?
- How severe is the impact?
- Does it contain personal data?
- How annoyed is the customer?
Each answer comes back as probability bars with a confidence value. The footer shows the latency, the input token count, the output token count (always zero, which still makes me smile) and what the call cost.
The part I like best is the threshold slider. Set it to 0.8 and the app only auto-routes a ticket when the model is at least 80% confident about the team. Anything below that goes to a human. That's the whole production pattern for these models, and it lands much faster when you drag a slider than when you read a paragraph about it. (Yes, I see the irony.)
How I built it
It's a single Cloudflare Worker that serves a React 19.3 front end (Vite 8, TypeScript 7) and one API route, which calls Clef-Flash through the Workers AI binding. The questions are fixed on the server, so nobody can stuff 64 questions into my bill. Turnstile, the Workers rate-limiting binding and a daily cap in KV stop it from turning into someone's free classification API.
The cost maths is almost funny. A request is roughly 400 input tokens, which works out at about $0.000015 per call at $0.038 per million tokens. Workers AI includes 10,000 free Neurons a day, and if my maths is right, that covers around 7,000 of these calls before I pay anything.
Break it
Then open the Break it tab. I added it because a demo that only shows the good side is an ad, and I wanted you to see where the model falls over:
- Turn off the "other" option and send a pizza order. The model has to pick billing, technical or sales anyway, because those are the only answers it's allowed to give.
- Ask whether an invoice was paid late, given two dates. The page shows the model's answer next to the answer computed in code. Code wins.
- Compare a vague question ("has repro steps?") with a precise one, and watch the confidence move.
- Ask the same question in two phrasings and compare the probabilities.
Each of these is a real limitation, and I'll get to all of them below.
Using Clef-Flash on Cloudflare Workers AI
Why Clef is my pick right now
Honest answer: because I'm already on Cloudflare. My site, my Workers and most of my side projects live there, so adding a decision is one binding and one function call. No new vendor, no new API key, no new invoice to reconcile at tax time.
The numbers help too. Clef-Flash costs $0.038 per million input tokens and output is free. Cloudflare cut the price from $0.09 on 9 October, which makes it slightly cheaper than Jev at $0.042. Cloudflare quotes a 38.8 ms median latency on its own infrastructure, and Flavio Copes measured around 200 ms over the REST API from Italy, round trip included. Either way, it's fast enough that I stopped thinking about it.
Under the hood it's a 9B model: a frozen Qwen3.5-9B with a custom scoring head on top. The weights are on Hugging Face under Apache-2.0, so if I ever need to run the same model somewhere else, I can.
If you live on AWS or OpenAI's platform, your answer is probably different, and that's fine. Pick the one closest to where your code already runs.
TypeScript (Workers binding)
interface Env {
AI: Ai;
}
type Answer =
| { type: "noul"; noul: number }
| { type: "choice"; choice: string; probabilities: Record<string, number>; confidence: number }
| { type: "score"; score: number; probabilities: Record<string, number>; confidence: number };
interface ClefResponse {
model: string;
answers: Record<string, Answer>;
usage: { input_tokens: number; output_tokens: number };
}
export default {
async fetch(request, env): Promise<Response> {
const { message } = (await request.json()) as { message: string };
const res = (await env.AI.run("@cf/cloudflare/clef-flash", {
model: "clef-flash",
state: { message },
questions: {
team: {
type: "choice",
instructions: "Which team should handle `message`?",
criteria: {
billing: "Payments, invoices, refunds",
technical: "Outages, errors, bugs",
sales: "Plans, pricing, upgrades",
other: "Anything that fits none of the teams above",
},
},
},
})) as ClefResponse;
const team = res.answers.team;
if (team.type === "choice" && team.confidence >= 0.8 && team.choice !== "other") {
return Response.json({ route: team.choice });
}
return Response.json({ route: "human" });
},
} satisfies ExportedHandler<Env>;The binding hands you the answers directly, with no envelope around them.
Go (REST API)
Most of my backends are Go, so here's the same call over the REST API:
package clef
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
)
type Question struct {
Type string `json:"type"`
Instructions string `json:"instructions"`
Criteria any `json:"criteria,omitempty"` // map[string]string for choice, []string for score
}
type Answer struct {
Type string `json:"type"`
Noul *float64 `json:"noul,omitempty"`
Choice string `json:"choice,omitempty"`
Score *float64 `json:"score,omitempty"`
Probabilities map[string]float64 `json:"probabilities,omitempty"`
Confidence *float64 `json:"confidence,omitempty"`
}
type envelope struct {
Success bool `json:"success"`
Result struct {
Answers map[string]Answer `json:"answers"`
} `json:"result"`
Errors []json.RawMessage `json:"errors"`
}
func Decide(ctx context.Context, accountID, token string, state any, qs map[string]Question) (map[string]Answer, error) {
body, err := json.Marshal(map[string]any{"model": "clef-flash", "state": state, "questions": qs})
if err != nil {
return nil, err
}
url := "https://api.cloudflare.com/client/v4/accounts/" + accountID + "/ai/run/@cf/cloudflare/clef-flash"
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var env envelope
if err := json.NewDecoder(resp.Body).Decode(&env); err != nil {
return nil, err
}
if !env.Success {
return nil, fmt.Errorf("workers ai: %s", env.Errors)
}
return env.Result.Answers, nil
}Over REST, the answers sit inside Cloudflare's usual result envelope. Your API token also needs Workers AI permissions, or you'll be debugging an auth error instead of building something.
Gotchas worth knowing
- The
modelfield in the body is required, even though the model is already in the URL. It has to becleforclef-flash, so pastingjev-latestfrom old code fails. - The hosted context window is 24,576 tokens. It was 64K at launch and dropped on 9 October. If your text state is too long, it gets truncated quietly. "Quietly" is the word that should worry you, so check your input sizes.
- At launch,
wrangler typesdidn't know about the Clef models, so the answers came back typed asunknown. Hence the hand-written types above. - It takes images (up to four per request), but Flavio saw 13 to 30 seconds per image call on launch day. I'd keep images out of anything latency-sensitive for now.
- Coming from Jev? The request shape is the same System One API. Change the endpoint, the key and the model name, and unwrap
resultif you're on REST.
Where decision models shine (and where they don't)
My rule: use a decision model when the decision needs reading, not thinking.
Good fits
- Triage of incoming messages: urgency, team, sentiment, language
- Order and document intake: is this an order or a change request, is a PO number present, is this an invoice or a receipt
- Intent classification for chatbots, forms and shared inboxes
- Routing: which queue, agent or model should handle this request
- Guardrails and tool-call checks, like the AWS Strands demo that checks whether an agent's chosen city actually appears in the conversation before it calls a weather tool
- A first pass on content moderation (Cisco found Jev held up well using only the policy text, though a classifier trained on that policy still fit it better)
Every item on that list has the same shape. A person could make the call in about two seconds from the text in front of them, and nobody would need a calculator or a meeting. A lot of the automation work I do for small businesses looks exactly like this: messages, orders and documents arriving all day, each needing a quick label before anything useful can happen.
Bad fits
The first one is when the right answer isn't on your list. A choice question has to pick one of your options, full stop. Cloudflare's own benchmark shows how much this hurts: on CLINC150, which includes out-of-scope queries, Clef-Flash scored 66.77 macro-F1, against 97.43 for the bigger Clef and 89.27 for Jev. Always add an "other" option and treat it as an escalation.
Maths, counting and dates are the second. TypeSafe's own docs list them as weak spots for Jev. Do the calculation in code and put the result in the state.
Third, anything that needs real reasoning. On GPQA Diamond, Clef-Flash scored 51.0 to Jev's 78.3 (Cloudflare's numbers again). That's a benchmark of hard science questions, and nobody should be asking a scoring head about quantum chemistry anyway.
Fourth, decisions you have to explain. You get numbers, not reasons. If an auditor or a customer is going to ask "why?", use an LLM or a rules engine you can show them.
And finally, vague questions. A result hovering around 0.5 usually means your question is ambiguous, not that the model is confused. Flavio got 0.04 from Clef and 0.54 from Clef-Flash for the same "has repro steps?" question on the same ticket. Rewrite the question before you blame the model.
The rule of thumb
If a competent person could make the call in two seconds from the text alone, use a decision model. If they'd need to think it through, calculate something or look something up, don't.
And if you can compute it, compute it. The cheapest decision model is still an if statement.
Decision models and LLMs: better together
This is where it gets good. Decision models don't replace LLMs. They make LLMs cheaper to run, because most requests never need to reach one.
The pattern I use is a cascade:
- The decision model answers its questions on every incoming item. It's cheap and fast enough to run on everything.
- When an answer is confident and isn't "other", plain code acts on it.
- When confidence is below your threshold, or the answer is "other", the item goes to an LLM or a person.
- The LLM only does the work that needs actual language: drafting a reply, extracting fields, summarising.
If you've been reading about LLM routers, this is one. Ask the decision model "does this need a frontier model, a small model or no model at all?" and route on the answer. You end up with a router whose output is a probability you can threshold, which beats parsing a model's opinion about which model should answer.
A real pipeline
Here's the shape of an order-intake flow. An email arrives. The decision model answers four questions about it: is this an order, is it new or a change, is it urgent, and does it include everything we need (customer, items, delivery date)?
A complete new order with high confidence goes to an LLM, which extracts the line items into JSON, and from there straight into the system. If something's missing, an LLM drafts a short reply asking for it. If the decision model isn't sure what the email even is, a person looks at it.
The decision model handles the "what is this?" part on every single email for a fraction of a cent. The LLM only runs when there's writing or extracting to do. I described a similar setup for support tickets in my AI ticket triage article, and a decision model slots straight into its classification step. Same goes for agents: if you're building with the Claude Agent SDK, a decision model makes a cheap sanity check before an expensive tool call.
Pick your threshold with data
Don't choose 0.8 because it sounds sensible. Confidence isn't the same thing as accuracy. On the independent Decision Index, Jev's average confidence was 0.81 while its accuracy was 0.74, so it was about seven points overconfident (an expected calibration error of 0.074). Perplexity's open pplx-decider came in at 0.018, which is much better calibrated.
The fix is boring, and it works. Label 100 to 200 real examples from your own data, run them through the model, and check how often it's right at each confidence level. Then set the threshold where the error rate is one you can live with. Do it again for every model you try, because a 0.8 from Clef-Flash doesn't mean the same thing as a 0.8 from Jev.
Clef-Flash vs Jev vs the rest
Prices are as of 14 October 2026. This space moves weekly, so check before you commit to anything.
| Model | Maker | Runs on | Input price per M tokens | Licence | Good for |
|---|---|---|---|---|---|
| Clef-Flash | Cloudflare | Workers AI, open weights | $0.038 | Apache-2.0 | Cheap, fast decisions where the answer is on your list |
| Clef | Cloudflare | Workers AI, open weights | $0.24 | Apache-2.0 | When Flash gets your test set wrong |
| Jev 1.13 | TypeSafe AI | Hosted only | $0.042 | Closed | Decisions that need a bit more reasoning |
| OpenAI Decisions API | OpenAI | Hosted, public beta | $0.10 | Closed | Teams already on OpenAI, very long inputs, up to 200 questions |
| pplx-decider | Perplexity | Open weights | Free to self-host | Apache-2.0 | The best-calibrated open model, if you have a big GPU |
| Strands Decider 2B | AWS Strands Labs | Local | Free | Apache-2.0 | Laptops and modest hardware |
Hosted context is 24K tokens for Clef-Flash and 64K for Clef and Jev. OpenAI's is far bigger, if you need to throw whole documents at it.
One caveat about all the benchmark numbers in this article: Clef-Flash's come from Cloudflare itself, and TypeSafe doesn't publish benchmarks for Jev at all. The Decision Index is the closest thing to an independent leaderboard, and as of 12 October it hadn't scored Clef-Flash. Treat every number here as a starting point for your own test set, not a verdict.
Running decision models locally
I've only played with local decision models a little, but so far I'm impressed. They're fast, and for simple questions the answers look as good as the hosted ones.
A few practical notes before you try:
- Ollama added the System One API in v0.35.0 and Clef plus Clef-Flash in v0.35.1.
ollama pull clef-flashis an 11 GB download. - On Apple Silicon, the 4-bit MLX build of Clef-Flash is a 6.2 GB download and peaks at around 7 to 8.6 GB of memory, so you want a 16 GB Mac at minimum.
- GGUF files, llama.cpp and LM Studio don't work for decisions yet. The GGUF conversions lack the scoring head, so you just get ordinary text generation. As of early October, llama.cpp support was still an open pull request.
- On an 8 GB machine, look at Strands Decider 2B instead. AWS quotes about 153 ms per call on an M3 MacBook.
Local makes sense when documents can't leave the building, or when your volume is high enough that even $0.038 per million tokens starts to show up on the bill.
The Jev story
I feel a bit bad for TypeSafe. They launched Jev on 15 September and pretty much created this category. Two weeks later, AWS had shipped its own take (TechCrunch called it a Jev clone), Ollama had added the same API, and Cloudflare had released Clef with the same request shape, open weights and a lower price. OpenAI's Decisions API went into public beta on 6 October.
That said, they are doing well. Jev 1.13 had handled about 1.05 billion requests on OpenRouter by 11 October, ahead of the OpenAI, Perplexity and Cloudflare models, according to Forbes. TypeSafe also reportedly raised an $870M Series A at a $7.5B valuation. They'll be fine.
What did happen is that their API became a commodity almost overnight. A clean JSON API is easy to copy, so it turns into a standard rather than a moat. That's rough for TypeSafe and great for the rest of us, because I can move between Jev, Clef and a local Ollama model by changing an endpoint and a model name. Somewhere there's an engineer at TypeSafe who designed that API really well, and every competitor said thank you.
FAQ
Can decision models hallucinate?
Not in the usual sense. They can't make up an answer that isn't on your list. They can still pick the wrong option with high confidence, especially when the right answer isn't one of the options, which is why an "other" option and a threshold matter.
Is a decision model just JSON mode?
No. JSON mode constrains the text an LLM generates, and you pay for every generated token. A decision model generates no text at all. It scores your options directly, returns probabilities and bills input tokens only.
Is Clef-Flash compatible with Jev?
Mostly. Both use the System One request format with a state and typed questions. To switch, change the endpoint, the API key and the model name to clef-flash, and unwrap Cloudflare's result envelope if you call it over REST.
How much does Clef-Flash cost?
$0.038 per million input tokens, with no charge for output, as of 14 October 2026. A typical 400-token request costs about $0.000015, and Workers AI includes 10,000 free Neurons a day.
Can I run a decision model locally?
Yes. Ollama (v0.35.1 and later) and MLX both run Clef-Flash, and you'll want at least a 16 GB Mac for it. GGUF builds and LM Studio don't support decision models yet. On smaller machines, try Strands Decider 2B.
So, should you use one?
Yes, for the boring decisions. If your pipeline asks an LLM to pick a label, you're paying for text you throw away. Swap that step for a decision model, keep the LLM for the parts that need words, and put a threshold between them.
Start with Triage Desk and try to break it. Then pick one classification step in your own stack and run it through Clef-Flash for a week. And if you'd rather have someone build that for you, that's what I do.
Related Articles
NVIDIA DGX Spark Review: Why Small Businesses Should Consider Local AI
Is NVIDIA DGX Spark worth $8,900 for your business? Analysis of on-premise AI infrastructure, privacy benefits, and cost comparison vs cloud solutions for Sydney SMBs.
8 min read
AI for BusinessAI Business Context Validation: How to Know If Your AI Is Actually Working
Why do 80% of AI projects fail? Context — not capability. Learn the 5-step AI business context validation framework SMBs use to close the gap.
11 min read
AI for BusinessBest LLM for Office Work 2025: ChatGPT vs Claude vs Gemini
ChatGPT, Claude, or Gemini for office work? Compare real costs ($30-100/user), task performance, and integration. Data-driven guide with benchmarks.
11 min read