Skip to content
JevDirectory.org
Practices & Patterns#primitives#choice#score#noul#design

Choice, Score, or Noul? How to Pick the Right Primitive

The most common Jev design mistake is asking a question that does not match the primitive. Here is how to choose by the shape of the answer you need back.

Every Jev request starts with the same design question: what shape is the answer? Jev can answer three kinds of questions, a Choice, a Score, or a Noul, and picking the wrong one is the most common reason a question comes back with a low confidence or a wrong label.

The primitives overview is the canonical reference. This is the design-side companion: how to choose between the three when you are staring at a feature request.

Start with the shape of the answer

Noul: one probability

A Noul asks a yes/no question and returns a single probability from 0 to 1. There is no separate confidence, because the probability already describes the whole distribution. In code, you threshold it:

wants_human = response.nouls["is_human_escalation"].noul > 0.9

Reach for a Noul when the answer is genuinely binary and both outcomes are actionable: is this urgent, does this message ask for a refund, does this draft contain a leaked secret. Optional criteria.true and criteria.false descriptions are how you pin down the boundary when the question is subtle.

Two design notes. First, ask one question per Noul; "is this urgent and about billing" is two questions wearing a trench coat. Second, a Noul is not a degree scale. A value of 0.7 does not mean "quite urgent", it means a 70% chance of yes. If you need intensity, that is a Score.

Score: an ordered spectrum

A Score rates content against an ordered list of 2 to 10 levels and returns a probability-weighted score that can land between levels. Levels are numbered by array position from 0, and the model sees the descriptions, not the numbers:

"severity": Score(
    instructions="How severe is the reported issue?",
    criteria=[
        "Cosmetic; no impact to functionality",
        "Broken or degraded feature, but workaround exists",
        "Blocking issue; no workaround exists",
    ],
),

Scores are the right primitive for triage, ranking, and rubric work. Two traps: levels are judged separately, so describing one level as "worse than the previous" adds no signal, and the primitive is weak at exact numeric calibration. Use the score to route into bands in code, not as a measurement. If you need several dimensions, break the judgment into atomic scores and combine them yourself, as the composite scoring pattern shows.

Choice: one of your options

A Choice picks one option from a set you define, up to 255, and returns the chosen option, the full probability distribution, and a confidence. When an option name is self-explanatory, its description can be null; otherwise the description is your chance to define scope, including what the option is not for.

Choice is the workhorse for classification, intent routing, and tool selection. For deep hierarchies, chain choices level by level rather than passing the whole tree: the hierarchical classification cookbook walks patent and product taxonomies that way.

A decision table

What you needPrimitiveWhat comes back
A yes/no gateNoulOne probability, thresholded in code
An intensity or severity bandScoreWeighted score, per-level probabilities, confidence
One label from a setChoiceLabel, full distribution, confidence
A label plus "how sure"ChoiceUse the confidence to route
A measurement like "how many"NoneCount in code, one question per item

That last row is deliberate. Counting and arithmetic are among Jev's known weak spots, covered in the jaggedness list. The primitive that does not exist is the one you should implement yourself.

Mix them in one request

Primitives compose. A single call can carry a Noul, a Choice, and a Score, and each runs in parallel:

questions={
    "billing": Noul(instructions="Is this ticket about billing?"),
    "tone": Choice(
        instructions="What is the customer's tone?",
        criteria={"calm": None, "frustrated": None, "angry": None},
    ),
    "urgency": Score(
        instructions="How urgent is this ticket?",
        criteria=["can wait", "this week", "today"],
    ),
}

Answers come back grouped by type as response.nouls, response.choices, and response.scores. The speculative fan-out pattern builds on this idea: ask everything the branches might need in one request, then let code ignore the answers it does not use.

When the answer is "not sure"

No primitive returns an "I don't know" label. Uncertainty shows up as a low confidence on a Choice or Score, or as a Noul value near the middle. Deciding what to do with those values is the actual design work, and it is the subject of confidence gates in production.

As a starting point: set thresholds per action by the cost of being wrong, keep human review in the middle band, and pin your questions and thresholds behind labeled fixtures before you automate anything.

The short version

  • Binary and both outcomes actionable: Noul.
  • Ordered intensity: Score, then band it in code.
  • One label from a list you control: Choice.
  • Numbers, dates, or counting: keep the model out of it.

Get that mapping right and most of the remaining design work is state, thresholds, and tests, which is exactly what the patterns section is for.

From the directory

The resources behind this article.

Pick one option from a set you define. Returns the option, the full probability distribution, and 0-1 confidence, with up to 255 options and parallel questions that barely add latency.
Practices & Patterns#official#primitives#choice
Official
Rate content against 2 to 10 ordered levels. Returns a probability-weighted score that can land between levels, per-level probabilities, and confidence, with the arithmetic left to code.
Practices & Patterns#official#primitives#score
Official
The yes/no primitive: one probability from 0 to 1, where the value is the answer and no separate confidence is needed. True and false criteria pin down subtle boundaries.
Practices & Patterns#official#primitives#noul
Official
The three TypeSafe question types, the typed answers they return, how to choose between them, and how to ask several in a single call.
Practices & Patterns#official#primitives#choice
Official
Instructions, option descriptions, score levels, and noul criteria all accept JSON, so you can label question parts, pass schemas and taxonomies, and keep candidate paths alive.
Practices & Patterns#official#primitives#architecture
Official
Back to all articles

More articles

Confidence is not accuracy, and a single global threshold is rarely the right policy. A practical guide to per-action gates, measured thresholds, and the logs you will want later.
Practices & Patterns#confidence#routing#evaluation
Read article
Jev cannot count, reads dates as text, and takes instructions literally. These are not bugs to work around quietly; they are design constraints with known guardrails.
Practices & Patterns#evaluation#state#dates
Read article

From the community

Posts from builders shipping with Jev right now.

Vercel's fx safety reviewer, 18x faster

We're seeing extraordinary results from @typesafeai. Default mode in 𝚏𝚡 is auto, with a safety reviewer analyzing every command. That reviewer runs on GPT Luna today. Jev is up to 18x faster (p95) *and* more accurate. It's coming to @vercel AI Gateway and likely new default.

Pranit
Pranit
Vercel
@fazxes

We benchmarked fx auto mode (safety) classifier with @typesafeai's Jev. tl;dr: ~5-18x faster and more accurate than 𝚐𝚙𝚝-𝟻.𝟼-𝚕𝚞𝚗𝚊, our current top choice

Image
Reply

Jev lands on OpenRouter