Jev primitives: Choice, Score, and Noul for software decisions

Artificial Intelligence 5 min
Editorial diagram of Jev primitives: structured state flowing into Choice, Score, and Noul question cards
Jev primitives are Choice, Score, and Noul. Send state plus typed questions; get constrained answers with probabilities your code can act on. Day 1 of the oguzhan.co Jev series.

Jev primitives are three typed questions TypeSafe’s System One model accepts. Choice: one option from a closed list. Score: a spot on ordered rubric levels. Noul: probability that a yes/no statement is true. You send structured state plus a map of named questions. You get typed answers with probabilities your code can threshold, sort, or fan into the next call. No free-text generation. That is day 1 of this series, the whole product surface.

Yesterday’s TypeSafe Jev hub covered why System One exists. Today I stay on the API: how to define a question, when to pick each type, what comes back, how field paths work, and why parallel speculative questions beat one-question-per-call habits. Wider desk: keep the AI notes hub open. Primary docs: docs.typesafe.ai/primitives.

Editorial diagram of Jev primitives: structured state flowing into Choice, Score, and Noul question cards

⚡ What Jev primitives are

TypeSafe’s primitives page is blunt. Ask for one snap judgment per question. “Does this message convey urgency?” fits. “Analyze this message and decide the best course of action” does not. That second prompt wants slow reasoning. Split it. Compose answers in your own code.

Every question has an ID (your key, e.g. refund_requested), a type (choice, score, or noul), and instructions (the actual judgment text). Choice and Score also take criteria: a map of options for Choice, an ordered list of levels for Score. Noul can take optional criteria that clarify what yes and no mean. Question IDs are for your code. They never go to the model. Write the full question in instructions even when the ID looks obvious.

🧩 When to pick Choice, Score, or Noul

Choice fits unordered closed sets. Route a ticket to a department. Classify a document type. Detect a language. List every option. Add other or none of the above when coverage might miss.

Score fits a spectrum you can name: bug severity, customer frustration, skill level. You define the levels. The model returns a position along them. That position can land between two labeled levels.

Noul fits a clean yes/no where the probability itself is the signal. Does the message contain PII? Is the customer asking for a refund? Does the resume mention distributed systems? A Noul of 0.5 means equal yes/no probability. It does not mean “medium skill.” Need skill level? Use Score with defined levels. Need a binary gate? Write a crisp condition in the instructions.

Two types both seem to fit? Prefer the one your code can act on directly. Choice maps to switch branches. Score maps to a threshold. Noul maps to an if.

📊 What answers return

Answers are primitives too. Constrained to the options you supplied. Independent of each other in the same request.

Type Answer fields How to read it
Choice choice, probabilities, confidence Selected option, full distribution, peakedness summary
Score score, legend, probabilities, confidence Position on your levels (can sit between them), level legend, distribution
Noul noul P(yes) in [0, 1]. Near 1 strong yes, near 0 strong no, near 0.5 uncertain. No separate confidence field

That independence is the architectural win. Add or remove questions without poisoning the others. Never scrape a label out of generated prose.

🧠 State, field paths, and parallel fan-out

State is often JSON: a ticket, an order, a policy. When a question is about one part, name it with a backtick-wrapped dot-and-index path in the instructions. Examples: `ticket.messages[0].text` or `order.charges`. Explicit paths tell the model which slice to judge.

Send every question that shares the same state in one request. Mix types freely. System One evaluates them in parallel. Extra questions barely move latency and cost only a few question tokens. TypeSafe’s parallel-questions cookbook claims batching 13 questions into one call is about 11.5x cheaper and 9.6x faster than 13 separate calls, with the same answers.

Speculative fan-out is the pattern I keep recommending. Ask every question your code might need, including ones that only matter for some inputs, then ignore the rest in application logic. Ticket is not a bug report? Drop the severity Score. Coding agents love one question per call. Fight that habit. Official TypeSafe agent skills push the same advice.

Questions in one request are independent. One answer is not hidden context for another. If a later judgment truly needs the earlier answer (to fetch more data, reshape state, or pick the next Choice options), make a second request in code. Otherwise ask together and combine in your weights.

🛠️ SDKs and community tools that speak primitives

cobanov/awesome-jev’s Start here section is the shortest honest brief: state + typed questions, schema-valid ≠ correct, validate on your data. Concrete repos that already wrap the primitives:

  • typesafe-sdk-js and typesafe-sdk-python: official clients with typed Choice, Score, Noul builders and inferred answer types. Python 0.7.0 (18 Sep 2026) moved serialization to Pydantic.
  • hunch: Ruby probabilistic control flow. Hunch.likely?("fraudulent", given: order) branches on a typed answer, with graded predicates from possibly? to definitely?.
  • zod-jev: local Zod shape validation paired with Jev semantic validation. Structure first, judgment second.
  • jev-axi: CLI for pick / rate / check / rank / triage / guard from the shell.
  • advocaat and jevclient: small typed clients for dataset questions and async Python calls.

Provider note for later days in the series: Vercel AI Gateway’s Boolean primitive maps to TypeSafe’s Noul. Pin model IDs when you compare.

✅ Schema-valid is not correct

Jev cannot emit an out-of-schema string. That is the “can’t hallucinate” marketing line, and The Register already called the category game. A Choice can still pick the wrong department. A Score can rate a calm customer as furious. A Noul can be 0.9 on a false claim. Your job: thresholds, evals on your traffic, deterministic checks in front of irreversible tools, a human fallback. awesome-jev’s Start here says the same. Tomorrow’s post goes deeper on confidence and RLCD. For now, treat primitives as a clean interface, not an audit stamp.

📚 Sources

Oğuzhan Koçaklı

Oğuzhan Koçaklı writes and advises on AI engineering, agents, GenAI products, and applied ML. Daily digests and deep dives in EN + TR at oguzhan.co.

All posts

Leave a Reply

Your email address will not be published. Required fields are marked *