TypeSafe Jev Tutorial: API, Code Examples & 12 Use Cases
A practical guide to TypeSafe Jev: atomic questions, batched requests, confidence-gated branching, code in curl, Python, TS, Workers, and 12 use cases.
Jev doesn't generate text. Send it state and a set of typed questions, and it returns a typed answer with a probability for each question in a single parallel pass. TypeSafe AI states end-to-end responses of 70-500ms and 40-200x faster than frontier LLMs (a self-reported ceiling from its own workflow benchmarks, with no third-party validation). This practical guide focuses on how to write it, what to use it for, and where it breaks: three ideas carry the whole thing — decompose questions atomically, batch them into one request, and let confidence drive branching in code.
The basics (the three question types, pricing, limits) were already covered in the intro article, What is TypeSafe Jev — read that first if you haven't. This article is based on the official docs at docs.typesafe.ai and the typesafe.ai blog as of 2026-09-19.
Anatomy of a request — state, questions, answers
A request has three parts. state holds whatever text or JSON you want evaluated. questions is a map of keys you choose, each pointing to a Choice ('which one?'), Score ('what stage?'), or Noul ('is this true?') question — you can mix all three in one request. Every question is evaluated against the same state in parallel and independently of the others, so adding a question never changes the answers to the others. The returned answers are typed per question: Noul carries noul (0-1); Choice carries choice, probabilities (the full distribution over options), and confidence; Score carries score (which can land between stages, e.g. 1.04), legend, probabilities, and confidence. From there it's on your code to compare confidence or noul against a threshold and branch into auto-execute, confirm, or hand off to a human.

| Type | Question | criteria | Returns | Good for |
|---|---|---|---|---|
| Choice | Which one? An exclusive pick from a set | Map of option key → description (description can be null; add other if the list might be incomplete) | choice, probabilities (distribution over all options), confidence | Routing, categorization |
| Score | What stage? An ordered stage | Array of stage descriptions (2+, first to last forming a spectrum) | score (can land between stages, e.g. 1.04), legend, probabilities, confidence | Severity, proficiency, continuous scales |
| Noul | Is this true? | Optional description of what true/false mean | noul (0-1; near 1 = strong yes, near 0.5 = uncertain) | Binary checks, guardrails |
The fastest path to running it — curl, Python, TypeScript, Cloudflare Workers
Early-access API keys are issued at https://console.typesafe.ai/keys. Here's the HTTP API hit directly with curl.
```bash
curl -X POST https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<'EOF'
{
"state": "Hi, I've been trying to connect my Stripe account for 3 days and it keeps failing. I'm losing sales. Please help ASAP.",
"model": "jev-latest",
"questions": {"urgency": {"type": "noul", "instructions": "Does this message express urgency?"}}
}
EOF
```The response carries answers per question plus a usage block with token counts. Here's the example response from the docs.
```json
{"model":"jev-latest","answers":{"is_urgent":{"type":"noul","noul":0.999}},"usage":{"input_tokens":312,"output_tokens":48}}
```SDKs exist too. Python: pip install typesafe-sdk (or uv add typesafe-sdk, reading TYPESAFE_API_KEY from the environment). JavaScript/TypeScript: npm install @typesafe-ai/sdk (v0.6.0, Node.js 20+, ESM/CommonJS with bundled types), where the answer type is inferred from the question you send. Python ships a synchronous TypeSafeClient, an async AsyncTypeSafeClient, and a RetryPolicy.
```python
from typesafe_sdk import Noul, TypeSafeClient
client = TypeSafeClient()
response = client.system_one(
state="Customer message here",
questions={"is_urgent": Noul(instructions="The message conveys urgency")}
)
print(response.answers["is_urgent"].noul)
``````ts
import { choice, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient();
const response = await client.systemOne({
state: { document: "I was charged twice. Please fix this ASAP." },
questions: {
category: choice("What is this ticket about?", { billing: null, technical: null, other: null }),
},
});
console.log(response.answers.category.choice);
```Cloudflare Workers AI also lists it in its model catalog as typesafe/jev (32,000 context, jev-1.13.0), callable directly with env.AI.run. Here's the official sample mixing Choice, Noul, and Score in one request.
```ts
const response = await env.AI.run('typesafe/jev', {
state: 'Help! My payouts have been failing for 3 days.',
questions: {
is_urgent: { type: 'noul', instructions: 'Does this convey urgency?',
criteria: { true: 'Explicitly time-sensitive', false: 'No urgency expressed' } },
department: { type: 'choice', instructions: 'Which team should handle this?',
criteria: { billing: 'Payments, invoicing, refunds', technical: 'Bugs, outages, integrations', sales: 'Pricing, upgrades, new accounts' } },
frustration: { type: 'score', instructions: 'How frustrated is the customer?',
criteria: ['Calm', 'Frustrated', 'Very angry'] },
},
})
```Errors come back as 401 (bad key), 422 (validation failure), 429 (rate limit), or 529 (overload). 429/529 should be retried with exponential backoff — the SDKs do this automatically. Rate limits sit at 250k tokens/sec and 1,200 requests/min, and move dynamically with demand. Only jev-1.13.0 is available in production; jev-latest (the SDK default) and jev-preview are both aliases currently pointing at that same version. Aliases move automatically on new releases, so if you need consistent behavior, pin a version ID instead of using jev-latest. The model field in the response tells you which version actually answered.
There's also a skill for coding agents. For Claude Code, install it like this.
```bash
claude plugin marketplace add typesafe-ai/skills
claude plugin install typesafe@typesafe-ai
# For other agents:
# npx skills add typesafe-ai/skills --skill typesafe-ai
```TypeSafe notes that agents aren't especially good at writing questions on their own, so it recommends having a human refine them together and keeping questions and thresholds in one place so they're easy to review.
Design principle — code is in charge, the model is a part
The core of the official "How to build with TypeSafe" guide is one idea: keep control flow, deterministic rules, and side effects in code, and never let the model choose actions the way an agent would. Take spam detection. Asking one big question — "is this spam?" — is bad design. Instead, break it into three atomic Noul questions: "does it request credentials?", "does the sender's claimed identity mismatch their email domain?", "does it announce an unexpected prize or reward?" — then combine them in code, e.g. spam_risk = 0.45*credentials + 0.30*identity + 0.25*reward. This decomposition is said to buy three things: explainability, composability, and accuracy.

| Belongs in | Examples |
|---|---|
| Code | Deterministic rules such as overdue checks, orchestration, combining outputs, side effects |
| Model | Interpreting unstructured text, commonsense judgment under ambiguity, classifying/scoring subjective qualities, detecting contradictions |
Put only relevant information in state — the docs are explicit that a state cluttered with irrelevant material hurts accuracy. Structuring it as JSON and referencing fields from questions with backtick-quoted paths (e.g. ticket.messages[0].text) is the recommended pattern, and up-to-date facts should be passed in state rather than relied on from the model's own knowledge. Write instructions as complete sentences even when the key is self-explanatory, and keep each question to one judgment call a knowledgeable person could make in a few seconds. For complex instructions, an object like {question, focus, compare} is suggested; for Choice options, a contrastive {what, not_for, examples} shape is said to improve accuracy.
- Delegating deterministic logic to the model
- Asking one compound, ambiguous question instead of several atomic ones
- Stuffing state with excessive, irrelevant context
- Ignoring uncertainty (confidence and the probability distribution)
- Firing off independent questions serially when they could run in one request
Using confidence — set thresholds by risk
Confidence is a 0-1 statistic computed from how "peaked" the Choice/Score probability distribution is, and since the distribution itself (probabilities) is also returned, you can build your own metrics on top of it. The official guideline: confidence >0.9 is where auto-executing a high-risk action is reasonable, and below 0.5 you should escalate to a human, ask for confirmation, or fall back to another approach. A different page shows a three-tier example: execute above 0.8, human review between 0.4 and 0.6, and route to a more expensive reasoning model below 0.4. The stated position is that "risk tolerance belongs in code" — thresholds are domain-dependent, and the advice is to start conservative and tune against your own data.
| confidence | Suggested action |
|---|---|
| > 0.9 | Safe to auto-execute even high-risk actions (official guideline) |
| > 0.8 | Auto-execute (three-tier example) |
| 0.6-0.8 | Execute or confirm, depending on the use case |
| 0.4-0.6 | Route to human review |
| < 0.4-0.5 | Escalate to a more expensive reasoning model or a human |
```python
# Sketch of the official "confidence-gated routing" cookbook pattern
if response.answers["intent"].confidence < 0.6:
route_to_human(ticket)
elif intent == "balance_inquiry":
execute_balance_inquiry() # low-risk op, fine to run around confidence 0.6
elif intent == "transfer_approval":
if response.answers["intent"].confidence > 0.85:
execute_transfer() # only auto-execute at high confidence
else:
ask_user_to_confirm() # otherwise ask the user to confirm
```The numbers here are just one cookbook example — thresholds shift with the task and dataset. It also helps to look past a single confidence number at the full probabilities distribution, and handle cases where the top two options are close together as a special case.
12 use case ideas
The mark in the # column shows where each idea comes from: ★ maps to an official cookbook, use-case map entry or demo, while ☆ is a proposal from this article, not something TypeSafe has measured. Each idea is spelled out as what goes into state, which questions (and types) to ask, and what the code does.
| # | Use case | state | Questions (type) | What code does |
|---|---|---|---|---|
| 1 ☆ | Triaging inbound inquiries / emails | Subject + body + customer segment | Choice department (sales / support / billing / recruit / other), Noul urgency / sales pitch, Score frustration (3 stages) | Notify immediately if urgency noul>0.8, auto-label if sales-pitch>0.9, route to human if confidence<0.6 |
| 2 ★ | LLM chatbot input / output guardrails | Input and output text | Noul (jailbreak / aiding illegal acts / medical advice / self-harm signs) + Score severity 0-3 | Decide pass / review / block / support by priority order |
| 3 ★ | Filtering RAG search results | Each retrieved passage + the query | 4 Noul questions (relevance / usable as evidence / contradiction / manipulation signs) | Exclude if injection>0.70, route to contradiction block if >0.70, exclude if relevance<0.45, keep if evidence>0.55 |
| 4 ☆ | Pre-execution gate for AI agents | The pending tool call / diff + project rules | Noul (writes to prod DB? / violates a rule? / leaks secrets externally?) | Hold for human approval if any exceeds 0.5 |
| 5 ★ | Model router | Task description | Score difficulty (3 stages) + Choice domain + Noul high-risk | Route easy tasks to a small model, hard ones to an expensive model, high-risk ones to a human |
| 6 ☆ | Checklist matching for contracts / quotes / invoices | Full document text | 10-20 Noul questions (payment terms stated? / delivery date stated? / subcontracting clause? / damages cap?) | Generate a list of missing items; amounts / dates are computed in code |
| 7 ☆ | Featurizing daily reports / inspection logs / near-miss reports | Text of each record | Multiple Noul / Score questions | Feed the resulting probabilities as numeric features into existing prediction models (failure prediction, attrition, demand) |
| 8 ★ | Normalizing e-commerce product listings | Product name and description | Choice hierarchical category (beam search) + Noul banned-item / counterfeit signs | Walk the probability tree with beam search, K=3 |
| 9 ★ | Composite scoring for hiring / sales leads | Resume or lead info | Multiple atomic Score questions (e.g. python_depth / team_leadership / system_design / generalist) | Combine with role-specific weights in code; humans make the final call |
| 10 ★ | Real-time control (game NPCs, smart home, digital signage) | Sensor values / situation description | Choice / Noul | Convert numeric sensor values into word buckets like "hot / comfortable / cold" in code before passing them in |
| 11 ★ | Semantic lint in CI | PR description, commit messages, docs | Noul (does it follow team conventions?) | Keep deterministic syntax checks in existing tools; use Jev only for meaning |
| 12 ☆ | Triaging monitoring alerts / logs | Alert body / log lines | Choice (noise / needs action / critical) + Noul (customer-impacting?) | Route only low-confidence cases to on-call; counting and timing stays in code |
Inquiry triage is the easiest place to start. Put the subject, body, and optionally the customer segment into state, and bundle a department Choice, urgency/sales-pitch Noul questions, and a frustration Score into one request. Below is a full request showing the questions block, with instructions in English and a Japanese inquiry text left as-is in state.
```json
{
"state": "お世話になっております。先週注文した商品がまだ届かず、非常に困っています。至急状況を確認して折り返しご連絡ください。",
"model": "jev-latest",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this inquiry?",
"criteria": {
"sales": "Pricing, new orders, upgrades",
"support": "Order status, delivery, product issues",
"billing": "Payments, invoicing, refunds",
"recruit": "Job applications, recruiting",
"other": "Anything that does not fit the above"
}
},
"is_urgent": {
"type": "noul",
"instructions": "Does this message express urgency requiring an immediate response?"
},
"is_sales_pitch": {
"type": "noul",
"instructions": "Is this an unsolicited sales or marketing pitch rather than a genuine customer inquiry?"
},
"frustration": {
"type": "score",
"instructions": "How frustrated does the customer sound?",
"criteria": ["Calm", "Frustrated", "Very angry"]
}
}
}
```Filtering RAG search results improves both quality and safety of internal knowledge search. Ask each retrieved passage four questions — relevance, whether it's usable as evidence, whether it contradicts the query's premise, whether it's attempting to manipulate the system — and process them in this order: exclude if injection>0.70, route to a contradiction block if >0.70, exclude if relevance<0.45, keep only if evidence>0.55. In an official validation across 72 passages, an injected passage that ranked #1 by similarity (0.584) was caught with injection score 0.99. Thresholds are corpus-dependent and need tuning on your own data.
A pre-execution gate for AI agents matters more the more write access the agent has. Put the pending tool call (a command or diff) and the project's rules into state, then ask Noul questions like "does this write to a production database?", "does it violate a rule?", "does it send secrets externally?". Holding for human approval whenever any answer exceeds 0.5 is a proposal made in this article, but npm packages that check a coding agent's writes against a rules document have already started appearing, so the same idea is emerging in the ecosystem independently.
Checklist matching for contracts, quotes, and invoices pairs well with the fact that batching questions is cheaper. Send 10-20 Noul questions about a single document in one request — payment terms stated, delivery date stated, subcontracting clause present, damages cap present, and so on — and have code list out whatever came back false. Never let Jev do the arithmetic on amounts or dates; extract values and compute/verify them in code.
Cost estimates — batching questions is cheaper
Pricing is $0.042 per million input tokens, with output free. You can estimate cost as token count x $0.042/1M.
| Case | Calculation | Estimated cost |
|---|---|---|
| 1,000 inquiries/month | 1,000 x 500 tokens = 500k tokens | ~$0.021/month |
| 100k log lines | 100,000 x 300 tokens = 30M tokens | ~$1.26 |
| 1 contract (20 questions batched) | 8,000 tokens | ~$0.0003 |
| 1 contract (20 questions sent separately) | ~20x the batched case | ~$0.006 |
| Real-time control (10 queries/sec) | Official Doom demo figure | ~$7/hour |
Batching questions has a measured effect on its own. In an official benchmark asking 13 questions about the GDPR Wikipedia article (~54,000 characters), sending them in one request cost $0.000497 and took 0.27s, versus $0.006090 and 2.71s when split into 13 separate requests — 12.2x cheaper and 10.0x faster in the batched case, with no change in answers and no increase in variance. The reason is that state only needs to be sent once, which also backs up the "speculative fan-out" pattern mentioned earlier: throw every question that might be relevant into one request and let code decide which answers to actually use.
What it's bad at — 10 weaknesses TypeSafe itself acknowledges
| Weakness | Mitigation |
|---|---|
| 1. Reads literally (misses negation, qualifiers, implicit conditions) | Spell out conditions precisely in instructions and add boundary examples to criteria |
| 2. Can't compute or count (error grows with the size of what's counted) | Do the arithmetic in code |
| 3. Can't judge closeness of numeric representations (RGB/hex, etc.) | Convert to named buckets in code before passing them in |
| 4. Unstable at comparing dates/times before/after | Extract with the model, compare in code |
| 5. Weak at double negatives and multi-hop indirect references | Write directly, name the exact state being referenced |
| 6. Accuracy drops when state has a lot of irrelevant info | Narrow it down in code first |
| 7. Answers shift under adversarial phrasing | State criteria explicitly and test before deploying |
| 8. Gets confused when instructions and criteria disagree | Keep the two consistent |
| 9. No structural invariants (a negated question's answer plus its positive doesn't sum to 1, Noul and Choice values aren't directly comparable) | Don't rely on arithmetic identities across questions or reuse thresholds across question types |
| 10. Can't generate text | Frame extraction tasks as picking from a finite set of options |
The Register makes the point that "doesn't hallucinate" only means the output isn't free-form natural language — a probability-scored judgment can still be wrong, just in a different way. It's also worth keeping in mind that the benchmarks are TypeSafe's own.
A practical approach for Japanese-language use
TypeSafe AI's own docs state that Jev's primary language is English — CJK input, including Japanese, is accepted but currently has lower accuracy. Since fine-tuning isn't an option either, the following adjustments are a realistic starting point for Japanese-language work (these are proposals made in this article, unverified, and assume you'll run your own evaluation).
- (a) Write instructions/criteria in English, and pass state in Japanese as-is
- (b) Measure accuracy against confidence on 100-200 of your own examples before setting thresholds
- (c) Escalate low-confidence cases to an LLM or a human
- (d) Also compare a variant where state is machine-translated before being sent
None of these have been validated — the accuracy/operational-cost tradeoff has to be measured on your own data.
Frequently asked questions
How is this different from an LLM's structured output (JSON mode, etc.)?
An LLM's structured output still formats the result of text generation into JSON, one token at a time. Jev doesn't generate text at all — it returns a typed answer and probability distribution per question in a single parallel pass, which TypeSafe says is why it can hit 70-500ms response times and claim 40-200x speed over frontier LLMs (its own benchmark).
How do I get an API key?
It's currently early access via waitlist; get an API key at https://console.typesafe.ai/keys.
Does it work in Japanese?
CJK input, including Japanese, is accepted, but the official docs state accuracy is currently lower for it. See the "practical approach for Japanese-language use" section above.
What if I have a lot of Choice options?
For hierarchical classification with many options, the official blog describes walking the probability tree with beam search (e.g. K=3) in parallel — used for examples like patent classification with roughly 27,000 nodes.
What confidence threshold should I use?
There's no fixed answer. The official guideline is >0.9 for auto-executing high-risk actions and escalating below 0.5, but another page shows a three-tier example: execute above 0.8, human review between 0.4 and 0.6, escalate below 0.4. The recommendation is to start conservative and tune against your own data.
Can I use it on Cloudflare?
Yes — it's listed in the Cloudflare Workers AI model catalog as typesafe/jev and can be called directly from Workers with env.AI.run('typesafe/jev', {...}). Its context is reported as 32,000 tokens on jev-1.13.0.
Summary
Using Jev in practice comes down to repeating the same three moves: decompose questions atomically, batch them into one request, and let code branch on confidence. As long as you hold to the design principle of keeping deterministic logic and side effects entirely in code — rather than letting the model generate text or choose actions — the same idea applies whether you're triaging inquiries, filtering RAG results, or gating an agent's next action.
Calling it from Cloudflare Workers AI fits naturally with the stack covered in Building a web app on the Cloudflare stack, and if you're wiring it into an internal knowledge-search RAG pipeline, a good starting point is adding it as a filter on top of the search results from Building internal knowledge search with OpenClaw. Since this is still an early-access model, validating confidence thresholds against your own data before production use is a step worth insisting on.
References (primary sources)
- https://docs.typesafe.ai/introduction
- https://docs.typesafe.ai/primitives
- https://docs.typesafe.ai/confidence
- https://docs.typesafe.ai/patterns
- https://docs.typesafe.ai/model-jaggedness/jev-1.13
- https://docs.typesafe.ai/models
- https://typesafe.ai/blog/introducing-system-one-models-and-jev
- https://developers.cloudflare.com/ai/models/typesafe/jev/
- The Register: https://www.theregister.com/ai-and-ml/2026/09/16/typesafe-ai-debuts-model-for-machines-that-plays-doom/5296711
Feel free to contact us
Contact Us