Lesson 01 · TypeSafe Jev — System One models
The docs confuse people because they lead with philosophy. Let's do the opposite: one clear picture of what Jev is, what it hands back, and — most important for you — a simple test for spotting the problems it's actually built for. No code yet; just the shape.
When you use a normal LLM to make a decision inside code, you're bending a text-generation tool into a decision tool. TypeSafe calls this the core mismatch: "you are coercing a text-generation system into outputting structured decisions, then parsing the results back into something your code can depend on." [TypeSafe: Introduction]
Every question you ask Jev is one of three types. That's the entire vocabulary — learn these three and you know the product. Each takes your instructions + criteria and returns a different shape of answer. [docs.typesafe.ai]
| Primitive | The question it asks | What comes back |
|---|---|---|
| Choice | "Which one of these options?" — pick from a fixed set |
choice (the winner) + probabilities over every option + a confidence |
| Score | "How much, on this rubric?" — rate against ordered levels |
score + probabilities per level + a confidence |
| Noul | "Is this statement true?" — a binary judgement |
a single probability from 0–1 (no separate confidence) |
switch statement.
Score = a graded slider (urgency 1–5, quality 1–10).
Noul = a probabilistic if — "is X the case?" as a number, not a hard boolean.
A request is just state (everything a panel of experts would need to judge) and a questions object. Here's a support ticket being routed — our running example:
POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer $TYPESAFE_API_KEY
{
"model": "jev-latest",
"state": "Help! My payouts have been failing for 3 days.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "Payments, invoicing, refunds",
"technical": "Bugs, outages, integrations",
"sales": "Pricing, upgrades, new accounts"
}
}
}
}
And the answer — already the shape your code wants:
{
"model": "jev-1.13.0",
"answers": {
"department": {
"type": "choice",
"choice": "technical",
"probabilities": { "billing": 0.08, "technical": 0.85, "sales": 0.07 },
"confidence": 0.82
}
},
"usage": { "input_tokens": 312, "output_tokens": 48 }
}
Wire format per the LiteTLM/TypeSafe pass-through reference. [LiteLLM: TypeSafe]
questions is a map. Add priority (a Score) and is_angry (a Noul) beside
department and they all evaluate in parallel against the same state. TypeSafe:
"adding questions typically adds very little latency, although additional question text still contributes
token cost." One round trip, a whole dashboard of decisions.
[docs]
Don't just take choice. The probabilities and confidence are the point —
they let your code decide how much to trust the call:
A clean winner at 0.85 with confidence 0.82 → auto-route. But if the top two were
0.44 / 0.41, your code can choose to send it to a human instead. That threshold is
your logic, not the model's — which is exactly the control the parsing-a-paragraph approach never gave you.
if. The model judges; your app decides.
This is the part that answers your real question — where would I use this? Run any task through these four checks. The more yes-es, the more it's Jev's job rather than a chat LLM's:
if/router/queue — yes. If a person reads it — no, that's a chat LLM.Retrieval, not recognition — answer before you reveal. The effort is what makes it stick.
Primary source to read next: TypeSafe — Introduction (now that you have the map, the "System One vs text" framing will click).
Reference: Glossary & primitives cheat-sheet · Next: Lesson 02 — the first real call in TypeScript (ask me to build it).