Contents · 14 sections↓
- 01Jev vs Clef vs OpenAI Decisions API: which should you use?
- 02What do Jev, Clef and the Decisions API have in common?
- 03Side by side: prices, limits and inputs
- 04How do the request formats differ?
- 05Jev (TypeSafe): strengths and watch-outs
- 06Clef and Clef-flash (Cloudflare): strengths and watch-outs
- 07OpenAI Decisions API: strengths and watch-outs
- 08Other decision models worth a look
- 09Jev vs Clef vs OpenAI vs Promptise: where does Promptise fit?
- 10How to choose: test on your own data
- 11Common problems and fixes
- 12Limitations of this comparison
- 13FAQ
- 14Next steps
Jev vs Clef vs OpenAI Decisions API is the comparison developers now face when they want cheap, fast classification instead of a full LLM call. All three are decision models: you send an input and typed questions, and you get probabilities back instead of text. This guide compares them from each vendor's own documentation (prices, limits, inputs, request formats, self-hosting), shows how to switch between them with a small adapter, and explains how to test them on your own data before you choose.
Jev vs Clef vs OpenAI Decisions API: which should you use?
Pick by your main constraint. Clef-flash and Jev have the lowest published input prices for text. Clef is the only one of the three with open weights, so it is the choice for self-hosting or fine-tuning. OpenAI's Decisions API takes images in its standard request and runs inside an OpenAI account you may already have. None of the vendors' benchmark claims has been reproduced independently, so test two candidates on your own labeled examples before you commit.
Jev (TypeSafe) | Clef / Clef-flash (Cloudflare) | OpenAI Decisions API | |
|---|---|---|---|
Released | September 15, 2026 (early access) | October 1, 2026 | October 6, 2026 (public beta) |
Input price per 1M tokens | $0.042 | $0.24 / $0.038 | $0.10 |
Output tokens | free | free | free |
Context per request | 64k (32k per question) | 65,536 / 24,576 (hosted) | not stated in the guide |
Images | preview, behind a header | yes, up to 4 | yes |
Weights | closed | Apache 2.0 on Hugging Face | closed |
Question types | noul, choice, score (box in 1.14) | noul, choice, score | predicate, choice, score |
Request format | Jev format | Jev format ("fully Jev-API compatible") | its own format |
Use from Promptise Foundry | your function in AutoApprovalClassifier or a router | same | same |
Prices and limits are from each vendor's docs, checked on October 22, 2026.
Key takeaways:
Same job, same three question types. A yes/no probability, a choice among your options, or a score on your scale.
Two request shapes. Jev, Clef and Microsoft-Decision-1 share one; OpenAI uses another. A 30-line adapter covers both.
Price per call depends on input size only. None of the three bills output tokens.
Open weights change the decision. Clef can run on your own hardware; Jev and OpenAI can't.
Benchmarks are vendor-run. Use them to shortlist, then measure on your own labeled data.
[02]
What do Jev, Clef and the Decisions API have in common?
All three are decision models: models trained or post-trained to answer bounded, typed questions with probabilities instead of generating text. You send a state (text, JSON or images) and one or more questions. Each question is one of three kinds:
Yes/no (noul in Jev and Clef, predicate in OpenAI): returns one probability.
Choice: picks one of the options you list, with a probability per option.
Score: rates the input on ordered levels you define and returns a probability-weighted position on that scale.
You use them for routing, gating and classification inside apps and agents, where a typed answer and a number to threshold beat parsing free text. The decision models for AI agents guide explains the pattern and builds a router and an approval gate.
[03]
Side by side: prices, limits and inputs
Jev 1.13 / 1.14 | Clef | Clef-flash | OpenAI Decisions API | |
|---|---|---|---|---|
Model ID | jev-1.13.0, jev-1.14.0 (jev-latest, jev-preview aliases) | @cf/cloudflare/clef | @cf/cloudflare/clef-flash | gpt-6-luna (the only model) |
Endpoint | POST api.typesafe.ai/v1/systemone | Workers AI | Workers AI | POST /v1/decisions |
Input price per 1M | $0.042 | $0.24 | $0.038 | $0.10, plus regional and long-context multipliers |
Context | 64k per request, 32k per question; opt-in long context up to 262k | 65,536 | 24,576 hosted (256k in the weights) | not stated |
Questions per request | not stated | 1 to 64 | 1 to 64 | 1 to 200 (SDK reference) |
Images | PNG/JPEG behind TypeSafe-Danger-Zone-Images: true; "not yet production" | PNG, JPEG, WebP, up to 4 | same as Clef | base64 or public URLs |
Parameters | not published | 27B (Qwen3.8-27B base) | 9B (Qwen3.5-9B base) | not published |
Status | early access | live on Workers AI | live; price cut from $0.09 on October 9 | public beta, GA "in the coming weeks" |
A few rows need context. Jev's long-context opt-in raises both limits to 262k tokens, but TypeSafe's docs say it is slower and less accurate. Cloudflare cut Clef-flash's price on October 9, which also cut its hosted context window from 64k to 24k tokens, and released Clef-omni ($0.15 per million input tokens) for audio and video. OpenAI's Decisions API is the only one that can return a refusal instead of an answer for a question, so your code must handle that case.
What a million decisions cost
Because none of them bills output, cost is input tokens times price. For one million decisions:
State size | Clef-flash | Jev | OpenAI | Clef |
|---|---|---|---|---|
500 tokens | $19 | $21 | $50 | $120 |
2,000 tokens | $76 | $84 | $200 | $480 |
These figures use list prices only. OpenAI adds regional processing premiums and long-context multipliers, images count as input tokens on every service, and asking several questions in one request shares the cost of the state. For comparison, a generative call to the same gpt-6-luna model on OpenAI's standard API bills $0.50 per million output tokens on top of input, according to OpenAI's changelog.
[04]
How do the request formats differ?
Jev and Clef use the same request: a state and a questions object keyed by your own names, with options or levels in criteria. Microsoft-Decision-1 in Foundry follows the same shape. OpenAI's Decisions API uses input, a questions array where each question carries its name, the type predicate instead of noul, and choices or levels instead of criteria. Answers come back as an object keyed by name on the Jev side and as an array on OpenAI.
If you write your questions once in the Jev format, a small adapter sends them to OpenAI and turns every answer into one shape:
"""Send a Jev-style request (Jev, Clef, Microsoft-Decision-1) to OpenAI's Decisions API.
Jev-style: {"state": ..., "questions": {name: {"type": "noul"|"choice"|"score",
"instructions": ..., "criteria": {option: description} or [levels]}}}
OpenAI: input=..., questions=[{"name": ..., "type": "predicate"|"choice"|"score",
"instructions": ..., "choices": [...] or "levels": [...]}]
"""
from openai import AsyncOpenAI
client = AsyncOpenAI()
def to_openai(questions: dict) -> list[dict]:
out = []
for name, q in questions.items():
item = {"name": name, "instructions": q["instructions"]}
if q["type"] == "noul":
item["type"] = "predicate"
elif q["type"] == "choice":
item["type"] = "choice"
item["choices"] = [{"value": k, "description": v} for k, v in q["criteria"].items()]
else: # score: an ordered list of level descriptions, lowest first
item["type"] = "score"
item["levels"] = [{"label": level} for level in q["criteria"]]
out.append(item)
return out
def normalize(answer) -> dict:
"""One shape for every vendor: the decision plus a probability per option."""
if answer.type == "predicate":
return {"value": answer.probability}
if answer.type == "choice":
return {"value": answer.choice, "p": {p.value: p.probability for p in answer.probabilities}}
if answer.type == "score":
return {"value": answer.score, "p": {p.label: p.probability for p in answer.probabilities}}
return {"value": None, "refused": True}
async def decide_openai(state, questions: dict) -> dict:
result = await client.decisions.create(
model="gpt-6-luna", input=state if isinstance(state, str) else str(state),
questions=to_openai(questions))
return {a.name: normalize(a) for a in result.answers}Here is the request from Cloudflare's Clef documentation, sent to OpenAI through the adapter:
import asyncio
import json
from adapter import decide_openai, to_openai
# The request from Cloudflare's Clef docs, in the Jev-style format Jev and Clef share.
QUESTIONS = {
"urgent": {"type": "noul", "instructions": "Is this support request urgent?"},
"team": {"type": "choice", "instructions": "Which team should handle this request?",
"criteria": {"billing": "Payments, invoices, and refunds",
"technical": "Outages, errors, and configuration",
"sales": "Plans and upgrades"}},
"severity": {"type": "score", "instructions": "How severe is the customer impact?",
"criteria": ["No impact", "Minor", "Major", "Critical"]},
}
STATE = "Checkout has been failing for every customer for the last hour."
async def main():
for jev, oai in zip(QUESTIONS.values(), to_openai(QUESTIONS)):
extra = {k: v for k, v in oai.items() if k in ("choices", "levels")}
print(f"{jev['type']:6} -> {oai['type']:9} {json.dumps(extra)[:70]}")
print()
answers = await decide_openai(STATE, QUESTIONS)
for name, answer in answers.items():
print(f"{name:9} {answer}")
asyncio.run(main())noul -> predicate {}
choice -> choice {"choices": [{"value": "billing", "description": "Payments, invoices,
score -> score {"levels": [{"label": "No impact"}, {"label": "Minor"}, {"label": "Maj
urgent {'value': 0.99}
team {'value': 'technical', 'p': {'billing': 0.0, 'technical': 1.0, 'sales': 0.0}}
severity {'value': 2.98, 'p': {'No impact': 0.0, 'Minor': 0.0, 'Major': 0.02, 'Critical': 0.98}}The same three questions run unchanged against Jev or Clef, because they accept this format natively. The HTTP call for those is short; this version is written from each vendor's documentation and was not run for this guide:
"""The same questions sent to Jev, Clef or Microsoft-Decision-1 over HTTP.
Written from each vendor's documentation (TypeSafe quickstart, Cloudflare Workers AI
model page, Microsoft Learn); not run for this guide.
"""
import os
import httpx
ENDPOINTS = {
"jev": ("https://api.typesafe.ai/v1/systemone", "TYPESAFE_API_KEY", "jev-1.13.0"),
"clef": (f"https://api.cloudflare.com/client/v4/accounts/{os.getenv('CLOUDFLARE_ACCOUNT_ID')}"
"/ai/run/@cf/cloudflare/clef", "CLOUDFLARE_AUTH_TOKEN", "clef"),
"microsoft": (f"{os.getenv('AZURE_ENDPOINT', '')}/providers/microsoft/v1/systemone",
"AZURE_ENTRA_TOKEN", os.getenv("DEPLOYMENT_NAME", "")),
}
async def decide_systemone(vendor: str, state, questions: dict) -> dict:
url, key_var, model = ENDPOINTS[vendor]
async with httpx.AsyncClient(timeout=30) as http:
r = await http.post(url, headers={"Authorization": f"Bearer {os.environ[key_var]}"},
json={"model": model, "state": state, "questions": questions})
r.raise_for_status()
body = r.json()
return body.get("result", body)["answers"] # Workers AI wraps the output in "result"Check each vendor's response reference before you parse answers. Jev's yes/no answer carries its probability in a noul field, and Workers AI's REST API wraps model output in a result object.
[05]
Jev (TypeSafe): strengths and watch-outs
TypeSafe calls Jev a "System One" model. Its docs show it used for intent routing, classification, guardrails, re-ranking and citation checks. Its strengths:
The lowest-priced closed option: $42 per billion input tokens, output free.
Typed SDKs for Python (typesafe-sdk) and JavaScript, with retries for 429 and 529 built in.
A detailed confidence model. Choice and score answers include a confidence computed from the probability distribution, and the docs explain how to gate actions on it by risk.
Many worked patterns: fan-out questions, confidence-gated routing, composite scoring, intent routing, and cookbooks such as guardrails and citation checks.
From the TypeSafe Python SDK docs (not run here, no TypeSafe key):
from typesafe_sdk import AsyncTypeSafeClient, Noul
async with AsyncTypeSafeClient() as client: # reads TYPESAFE_API_KEY
response = await client.system_one(
state={"email": "Sorry about that, we'll refund the full $89 today."},
questions={"money": Noul(instructions="Does this email promise money?")},
)
print(response.nouls["money"].noul)Watch-outs: it is in early access, images and the image-location "box" question are marked as not yet production-ready, jev-latest points to 1.13 while jev-preview points to 1.14, and rate limits are set per organization in the console. TypeSafe's headline speed and cost multiples come from its own workflow evaluations, which its launch post says are likely on the high end of real-world gains.
[06]
Clef and Clef-flash (Cloudflare): strengths and watch-outs
Cloudflare trained Clef (27B) and Clef-flash (9B) from Qwen backbones and released the weights under Apache 2.0. Its strengths:
Open weights. Download from Hugging Face and serve with vLLM, SGLang or Transformers; the model card says the API is fully compatible with Jev's.
Hosted on Workers AI at $0.24 (Clef) and $0.038 (Clef-flash) per million input tokens, with images supported.
Fine-tuning. Cloudflare offers reinforcement-learning fine-tuning as a hands-on service through its engineering team, with self-serve planned later.
Multimodal sibling. Clef-omni adds audio and video input.
Watch-outs: the hosted Clef-flash context window is now 24,576 tokens, smaller than Jev's; the 27B model needs a large GPU to self-host (the model card was tested on a single H200); and Cloudflare's benchmark tables, including its latency comparison with Jev, are Cloudflare's own runs.
[07]
OpenAI Decisions API: strengths and watch-outs
OpenAI's Decisions API runs on gpt-6-luna through POST /v1/decisions. Its strengths:
One account, one SDK. If you already use OpenAI, client.decisions.create(...) works with the same key and the official SDK.
Images in the standard request, as base64 data URLs or public URLs.
Up to 200 questions per request, per the SDK's parameter reference.
Enterprise options. OpenAI lists Zero Data Retention, data residency in the US and Europe, and other enterprise data controls for eligible customers. Ask your security and legal teams which of these you need.
Watch-outs: it is a beta with one model; the guide doesn't state a context window; a question can come back as a refusal; its format differs from the Jev-style APIs; and OpenAI's "10x faster than the Responses API" figure is measured against its own Responses API, not against Jev or Clef. The request shape is strict: a choice question without choices returns 400 Missing required parameter: 'questions[1].choices'.
[08]
Other decision models worth a look
Microsoft-Decision-1 in Microsoft Foundry takes text or JSON state with noul, choice and score questions at /providers/microsoft/v1/systemone, authenticated with Entra ID or an API key. Its documentation is unusually frank about limits: scores change with question wording and option order, and calibration is strongest on familiar task types.
Strands Decider from Strands Labs, the experimental arm of the Strands Agents project, is an Apache 2.0 model of about 1.9B parameters that runs on CPU, Apple silicon or CUDA and serves a /v1/systemone endpoint. It is the smallest option here if you need a decision model on your own machine.
[09]
Jev vs Clef vs OpenAI vs Promptise: where does Promptise fit?
Promptise Foundry is not a decision model, so it doesn't compete with these three. It is the agent framework that calls one. The natural place is the approval gate: AutoApprovalClassifier runs deny, ask and allow rules and a read-only check first, then calls your classifier function for the cases rules can't settle, then a person. That function can call any of the three:
"""Use whichever decision model you picked as one layer of a Promptise approval gate."""
import asyncio
import os
from promptise import (ApprovalDecision, ApprovalRequest, AutoApprovalClassifier,
CallbackApprovalHandler)
from adapter import decide_openai
BACKEND = os.getenv("DECISION_BACKEND", "openai") # or jev, clef, microsoft
QUESTIONS = {"money": {"type": "noul",
"instructions": "Does this email promise money, a refund or a credit?"}}
async def promises_money(body: str) -> float:
if BACKEND == "openai":
return (await decide_openai(body, QUESTIONS))["money"]["value"]
from systemone import decide_systemone
return (await decide_systemone(BACKEND, body, QUESTIONS))["money"]["noul"]
async def check(request: ApprovalRequest):
p = await promises_money(request.arguments["body"])
return ("allow" if p <= 0.10 else "escalate"), f"{BACKEND}: money p={p:.2f}"
async def person(request):
print(f" -> a person reviews: {request.arguments['body']}")
return ApprovalDecision(approved=False, reviewer_id="sam")
gate = AutoApprovalClassifier(llm_classifier=check, fallback=CallbackApprovalHandler(person))
async def main():
calls = [
("get_customer", {"id": "C-7"}),
("send_email", {"body": "Your order ships Thursday. Tracking link inside."}),
("send_email", {"body": "Sorry about that, we'll refund the full $89 today."}),
]
for i, (tool, args) in enumerate(calls):
decision = await gate.request_approval(ApprovalRequest(f"r{i}", tool, args))
print(f"{tool:12} approved={decision.approved!s:5} layer={decision.trace.layer:28} "
f"{decision.trace.rule_reason}")
asyncio.run(main())get_customer approved=True layer=read_only
send_email approved=True layer=llm_allow openai: money p=0.00
-> a person reviews: Sorry about that, we'll refund the full $89 today.
send_email approved=False layer=llm_escalate_then_fallback openai: money p=1.00The read-only lookup never reached the decision model. The status email scored 0.00 on "promises money" and was approved automatically; the refund email scored 1.00 and went to a person. Switching vendors means setting DECISION_BACKEND, not changing the gate.
Where Promptise is not the better tool: it has no built-in client for any decision-model API, so you write the call yourself as above. Its FallbackChain (model failover) and the reasoning engine's RouterNode work with chat models, not decision APIs. If all you need is classification in a batch job or a web backend with no agent, call the vendor SDK directly; you don't need an agent framework.
[10]
How to choose: test on your own data
Vendor benchmarks don't transfer to your task. A comparison that does:
Label 200 or more real examples for the decision you want to automate, with a written definition.
Write the questions once in the Jev format and send them to each candidate through an adapter, so only the vendor changes.
Measure accuracy, Brier score and calibration on the same examples. The guide on calibrating LLM classifiers with a labeled set has the code.
Compare coverage at a fixed precision: how many items each model handles automatically while staying above, say, 97% correct. That number turns into hours saved.
Measure latency from where you run, median and 95th percentile, over at least a few hundred calls. Region and connection setup dominate small calls.
Price your real traffic with your state size and questions per call.
Re-run on every model version change. Pin versions (jev-1.13.0, not jev-latest) so results stay valid.
[11]
Common problems and fixes
Symptom | Cause | Fix |
|---|---|---|
| Jev-style criteria sent to OpenAI | Convert with an adapter: choices for choice, levels for score |
Crash reading an OpenAI answer | One answer is a refusal | Check answer.type and treat a refusal as "unsure" |
Workers AI answers not where expected | REST responses wrap output in result | Read body["result"]["answers"] |
Clef-flash requests fail on long inputs | Hosted context is 24,576 tokens | Shorten the state, or use Clef (65,536) or self-host |
Jev image request rejected | Images are off by default | Send TypeSafe-Danger-Zone-Images: true; treat as preview |
Scores shift after an update | Alias moved to a new version | Pin model versions and re-run your labeled set |
Different answers when options are reordered | Option order sensitivity | Keep option order fixed, test reordering, add a "cannot tell" option |
[12]
Limitations of this comparison
No head-to-head accuracy numbers. Only OpenAI's API was run for this guide. Accuracy depends on your task, and every published benchmark here is vendor-run.
Prices and limits change fast. Clef-flash's price and context changed eight days after launch. Check the vendor pages on the day you decide.
Some fields aren't published. OpenAI's context window for /v1/decisions, Jev's parameter count and Microsoft-Decision-1's price aren't on the pages cited.
Data handling differs. Read each vendor's data terms with your security team; this guide doesn't assess them.
[13]
FAQ
What is the difference between Jev, Clef and the OpenAI Decisions API?
All three answer typed yes/no, choice and score questions with probabilities. Jev is TypeSafe's closed model with the lowest closed-model input price. Clef and Clef-flash are Cloudflare's open-weight models, hosted on Workers AI and compatible with Jev's request format. The OpenAI Decisions API runs gpt-6-luna with its own request format, images and enterprise data options.
Is Clef compatible with Jev?
Yes, according to Cloudflare. Its launch post and Hugging Face model card say Clef is fully compatible with Jev's API, so the same state and questions body works for both. OpenAI's Decisions API uses a different format and needs an adapter.
Which decision model is cheapest?
On list price per million input tokens, Clef-flash ($0.038) and Jev ($0.042) are the cheapest hosted options, followed by OpenAI ($0.10) and Clef ($0.24). None bills output tokens. Self-hosting Clef or Strands Decider has no API fee but needs your own GPU or CPU capacity.
Can I self-host a decision model?
Yes. Clef and Clef-flash publish Apache 2.0 weights on Hugging Face and can be served with vLLM or SGLang. Strands Decider is a smaller Apache 2.0 model that runs on CPU, Apple silicon or CUDA. Jev and OpenAI's model are available only as hosted APIs.
Does Promptise support Jev, Clef or the OpenAI Decisions API?
Promptise Foundry has no built-in client for them, but any of them plugs into its AutoApprovalClassifier as the classifier function, or into your own router, in a few lines. The example above gates an agent's tool calls with the OpenAI Decisions API and switches vendors with one environment variable.
Are decision model benchmarks reliable?
Treat them as vendor claims. TypeSafe, Cloudflare and Microsoft publish results from their own runs, and no independent leaderboard has reproduced them yet. Test the shortlist on your own labeled examples.
[14]
Next steps
Learn the pattern: decision models for AI agents: route, gate and classify.
Measure candidates properly: how to calibrate LLM classifiers with a labeled set.
Pick generative models too: the best LLM for AI agents and the best local LLM for AI agents.
Route between models: LLM routing: when to use a small vs large model.
Build the approval side: AI agent approval fatigue.
Explain it to your managers: decision models explained for leaders.