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 need | Primitive | What comes back |
|---|---|---|
| A yes/no gate | Noul | One probability, thresholded in code |
| An intensity or severity band | Score | Weighted score, per-level probabilities, confidence |
| One label from a set | Choice | Label, full distribution, confidence |
| A label plus "how sure" | Choice | Use the confidence to route |
| A measurement like "how many" | None | Count 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.
