Lesson 03 · TypeSafe Jev — System One models
One ticket, one call — but now three judgements at once: which team (Choice), how urgent (Score), is the customer angry (Noul). Then we combine them in code, name the three patterns you'll reuse forever, and finish by pointing Jev at your own product.
questions is a map. Put three differently-typed questions in it and Jev answers
all three in parallel against the same state — one round trip, barely more latency. Then
your code fuses them into a decision.
Same ticket as before. We add a Score (urgency 1–5) and a Noul (is the customer angry?) beside the Choice (department):
{
"model": "jev-latest",
"state": "Help! My payouts have been failing for 3 days. This is unacceptable.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": {
"billing": "Payments, invoicing, refunds",
"technical": "Bugs, outages, integrations",
"sales": "Pricing, upgrades, new accounts"
}
},
"priority": {
"type": "score",
"instructions": "How urgent is this ticket?",
"criteria": {
"1": "Trivial, no time pressure",
"3": "Normal, handle this week",
"5": "Critical, revenue or outage now"
}
},
"is_angry": {
"type": "noul",
"instructions": "The customer is angry or frustrated."
}
}
}
The response mirrors the request — one answer per key, each with its own shape:
{
"model": "jev-1.13.0",
"answers": {
"department": { "type": "choice", "choice": "technical",
"probabilities": { "billing": 0.08, "technical": 0.85, "sales": 0.07 },
"confidence": 0.82 },
"priority": { "type": "score", "score": "5",
"probabilities": { "1": 0.02, "3": 0.19, "5": 0.79 },
"confidence": 0.79 },
"is_angry": { "type": "noul", "probability": 0.88 }
},
"usage": { "input_tokens": 341, "output_tokens": 63 }
}
choice + probabilities + confidence.
Score → score (a level key) + probabilities + confidence.
Noul → a bare probability, no confidence — the number is the signal.
Extend Lesson 02's types with Score and Noul, as a discriminated union on type:
interface ChoiceAnswer { type: "choice"; choice: string;
probabilities: Record<string, number>; confidence: number; }
interface ScoreAnswer { type: "score"; score: string;
probabilities: Record<string, number>; confidence: number; }
interface NoulAnswer { type: "noul"; probability: number; }
type JevAnswer = ChoiceAnswer | ScoreAnswer | NoulAnswer;
interface JevResponse { model: string;
answers: Record<string, JevAnswer>; usage: { input_tokens: number; output_tokens: number }; }
Now the fusion — this is the part the model never does for you. Small judgements in; one business decision out:
const CONFIDENCE = 0.75;
const ANGRY = 0.7;
function decide(res: JevResponse) {
// In strict code, narrow on a.type; here we know the keys.
const dept = res.answers.department as ChoiceAnswer;
const urgency = res.answers.priority as ScoreAnswer;
const angry = res.answers.is_angry as NoulAnswer;
const score = Number(urgency.score); // "5" -> 5
const fastLane = score >= 4 || angry.probability >= ANGRY;
// Low confidence on the routing? A human triages.
if (dept.confidence < CONFIDENCE) {
return { action: "escalate", fastLane, score, top: dept.choice };
}
return { action: "auto", team: dept.choice, fastLane, score };
}
// -> { action: "auto", team: "technical", fastLane: true, score: 5 }
if yourself. That's what keeps the system testable, tunable, and reliable —
each threshold is a knob you own.
Almost every Jev integration is one of these — often several stacked in a single call:
| Pattern | Primitive | What it does |
|---|---|---|
| Routing | Choice | Send an item down one of N known paths: team, queue, workflow branch, which tool an agent calls next. |
| Gating / moderation | Noul | A yes/no checkpoint before an action: is this spam? safe to auto-send? does it need review? Gate on the 0–1 value. |
| Prioritisation | Score | Rank items by urgency/quality/risk so code can sort a queue or trigger a fast lane. |
You wanted to know where this fits your real work. Take your instructor SaaS that messages parents over WhatsApp. Run each idea through the four-question test from Lesson 01 — all three score high:
billing_query · reschedule ·
complaint · general. High confidence → fire the matching template automatically;
low → drop into the instructor's inbox. Code consumes it, fixed set, gate on confidence, high volume — 4/4.0.9 → hold for human
review. A cheap safety net on every outbound message. Binary judgement feeding an if — textbook Noul.Retrieval, not recognition — answer before revealing.
Primary source to read next: docs.typesafe.ai — the Patterns & Confidence pages (you now have the vocabulary to read them fast).
Reference: Glossary & cheat-sheet · Prev: Lesson 02 · Next: pick a use case above and let's build it for real.