Creuto is now an OpenAI Select Partner Read More
The three Jev question types explained with examples: what Choice, Score and Noul return, when to use each, the 255 option limit, and asking several at once.

One of the three Jev question types comes back without a confidence value, and that is deliberate rather than an omission. The three types are Choice, Score and Noul. Choice picks one option from a set you defined. Score places the content on a scale you wrote. Noul returns a single number: the probability that a statement is true. Pick the wrong one and the answer is still typed, still valid, and much harder to act on.
This is the working reference for someone who has just made their first call. Every field and limit below comes from TypeSafe's primitives documentation. The worked examples are ours, clearly marked, and we do not print response numbers we did not record. If you are still deciding whether this class of model belongs in your stack, start with when a decision model beats an LLM instead.
Every question you send has an ID you choose, a type, and instructions. Choice and Score also take criteria. Noul takes criteria only if you want to spell out what yes and no mean.
| Type | Returns | Use when |
|---|---|---|
| Choice | choice, probabilities, confidence | The answer is one of a known set of options with no order between them |
| Score | score, legend, probabilities, confidence | The answer is a position on a spectrum you can describe in steps |
| Noul | noul (0 to 1) | The answer is yes or no and the probability itself is the signal |
The question ID is for your code only. TypeSafe's docs are explicit that IDs are not sent to the model, so refund_requested as a key does not help the model — write the whole question in instructions even when the key looks self-explanatory.
A Choice question takes criteria as a map. Each key is an option name, each value is a description of that option. Both the names and the descriptions go to the model, so the descriptions are where you separate options that look similar.
{
"department": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"returns": "Exchanges, wrong or damaged items",
"shipping": "Delivery status, delays, lost packages",
"billing": "Charges, invoices, payment problems"
}
}
}
The answer carries three values besides its type: choice, the option with the highest probability; probabilities, the full distribution across every option, summing to 1; and confidence, a number from 0 to 1 computed from how peaked that distribution is.
The interesting case is a split. In the Choice documentation, a ticket that mentions a wrong size and a double charge returns returns at 0.61, with billing holding 0.35 and confidence dropping to 0.42. The model has not failed there. It has told you the ticket belongs to two teams, which is something a bare label could never say. TypeSafe's own example code uses that: it assigns the ticket to the winning team, then copies in any other team holding more than 0.25.
Add an other or none of the above option whenever your list might not cover every input. Without one, the model has to put its probability somewhere, and it will be somewhere wrong.
A Score question takes criteria as an ordered array of level descriptions, low end first. Each entry's position in the array is its number, starting at 0.
{
"bug_severity": {
"type": "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"
]
}
}
The answer is a score, which is the probability-weighted mean of the level numbers and can land between two levels, plus probabilities per level, a legend mapping numbers back to your descriptions, and confidence. For the bug report "the export button crashes the settings page in Safari; it works in Chrome, but a few of our customers only use Safari", the Score documentation records a score of 1.43 at confidence 0.35, from probabilities of 0.57 on level 1 and 0.43 on level 2.
Two things about that number are easy to get wrong. It is not a percentage of anything — 1.43 does not mean 43% of customers lack a workaround. And different distributions produce the same score: a 1.0 can mean all the probability sits on level 1, or that it is split evenly between levels 0 and 2. Read probabilities and confidence alongside the score if the difference matters.
Write levels as situations, not degrees. TypeSafe's docs make the point with a test: the same misaligned-button report scored 0.0 at confidence 1.0 against descriptive levels, and 0.55 at confidence 0.33 when the levels were the bare strings "0", "1" and "2". The model never sees a level's number or its neighbours, so "worse than the previous level" means nothing to it. The API accepts up to 10 levels; use as many as you can describe distinctly, and no more.
A Noul is a yes/no question, and the answer is one number from 0 to 1. Near 1 is a strong yes, near 0 a strong no, near 0.5 means the model gives both sides similar weight. criteria is optional and takes true and false descriptions when the boundary is subtle.
{
"is_repeat_contact": {
"type": "noul",
"instructions": "Has the customer contacted support about this before?",
"criteria": {
"true": "Mentions a prior attempt, ticket, or that they have asked before",
"false": "No sign of any previous contact"
}
}
}
This is the type with no confidence field, and the reason is arithmetic rather than policy. A Noul's distribution has two outcomes, so the single value already describes it completely. A Choice or Score spreads probability over several options, and confidence summarises that spread.
The Noul documentation publishes recorded jev-1.13.0 answers to "Is the customer asking for a human agent?" that show how the middle behaves: "Thanks, that fixed it!" returns 0.02, "I need this sorted today, whatever it takes" returns 0.26, "Are you a bot?" returns 0.40, and "I have asked three times now. Can I please just talk to a real person?" returns 0.99. The two middle cases are the ones your threshold has to have an opinion about.
Two rules make Nouls behave. Ask one condition per question — "Is the customer angry and asking for a refund?" makes the model judge two things at once and the number stops meaning much. And phrase it so a high value means yes, because "Is the message free of personal data?" inverts the sense and some future reader of your code will get it backwards.
Use Choice when the options have no order between them: a team, a category, a language. Use Score when the answer is a position and you can describe each point on the way. If both seem to fit, TypeSafe's advice is to pick the type whose answer your code can act on directly — a Choice maps onto branches, a Score onto a threshold, a Noul onto an if.
The trap is using a Noul where you meant a Score. The Noul documentation runs the same four resumes through both: asked "Is the candidate strong in Python?", a candidate who used Python daily for two years returns 0.81, and one with eight years returns 0.92. Asked as a Score with four described levels, the same two return 2.05 and 2.89 against levels you wrote. A Noul of 0.5 does not mean medium skill; it means the model splits evenly on the word "strong". If the question is really about degree, the Noul is not measuring the degree.
A Choice question accepts a maximum of 255 options. That is a real ceiling, but it is much higher than most people's first instinct, and TypeSafe's guidance is to give the model the full list of teams, categories or products rather than a shortlist, because each extra option costs only a few tokens.
When your taxonomy is genuinely larger than 255 — a product catalogue, a document hierarchy — the documented approach is to chain Choice questions level by level, using each answer to decide which options the next request offers. That is two or more round trips by design, and one of the few cases where TypeSafe says a second request is the right answer rather than a mistake.
Score has a much tighter ceiling: at least two levels, at most 10. If you find yourself wanting 20 levels, you probably want a Choice, or several Scores combined in code.
Every question in a request sees the same state, is evaluated independently and in parallel, and returns under its own ID. TypeSafe's docs say adding questions barely changes response time and costs only the tokens for the extra questions. Its parallel questions cookbook reports that batching 13 questions into one call ran 11.5x cheaper and 9.6x faster than 13 separate calls, with no change in the answers — a vendor figure, but one consistent with how the pricing works, since output tokens are free.
The practical consequence is that speculative questions are close to free. Ask the severity question on every ticket even though it only matters for bug reports, and let your code ignore the answer when the category comes back as something else.
There is one thing you cannot do this way. Questions in the same request cannot see each other's answers. If a later judgment genuinely depends on an earlier one — because you need the first answer to fetch more data, or to decide what the next question's options are — that is a second request you make in code.
The example below is ours, not TypeSafe's, and it is a request only. We have not run it against a client workload, so there are no response numbers here to quote. It mixes all three types against one state, in the shape of the enterprise workflow tools we build:
{
"state": {
"ticket": "Line 3 conveyor stopped mid-shift. Restarted it twice, keeps tripping after about ten minutes. We are behind on today's despatch.",
"asset": {"id": "CNV-03", "last_service": "2026-06-14"}
},
"model": "jev-latest",
"questions": {
"trade": {
"type": "choice",
"instructions": "Which maintenance trade should attend `ticket`?",
"criteria": {
"electrical": "Power, control panels, sensors, drives",
"mechanical": "Bearings, belts, alignment, physical wear",
"software": "PLC logic, SCADA, integration faults",
"other": "A fault that fits none of the above"
}
},
"line_impact": {
"type": "score",
"instructions": "How badly is production affected in `ticket`?",
"criteria": [
"Running normally; issue noted for later",
"Running with reduced throughput or manual workarounds",
"Line stopped; output has halted"
]
},
"needs_parts": {
"type": "noul",
"instructions": "Does `ticket` describe a fault likely to need a replacement part?"
}
}
}
Three answers come back, and your code does the combining: route by trade.choice, escalate when line_impact.score crosses a threshold you set, and pre-open a parts request when needs_parts.noul is high. Note the backticks around ticket in each instruction — that is the documented way to point a question at one field of a structured state.
Note also what is not in that request. There is no question asking the model what to do about the conveyor. That judgment involves shift rosters, spares on hand and who is on site, and it belongs in your code, where a shift supervisor can argue with the rule and you can change it.
Choosing between the three types takes an afternoon. Writing criteria that hold up on your own data takes considerably longer, and it is the only part that determines whether the integration is worth having. TypeSafe's own docs keep saying it: test your levels against your own examples, because two wordings of the same scale behave differently.
That is the same discipline as any other model evaluation. You need a set of real examples with known answers, and a way to score the whole path rather than one answer in isolation, which is the argument we made about scoring the trajectory rather than the final answer. It is also the reason a typed model does not remove the need to measure — it just makes the measuring easier, because there is no prose to interpret first.
If none of your decisions can be written as one of these three shapes, that is useful information too, and usually means the decision was never a single judgment. Breaking it into the questions you can ask is the work; we do it as a mapping exercise in the software we build for clients before any model is chosen, and our AI engineering team treats a decision nobody can phrase as a decision that was not ready to automate. The alternative — training your own model — is a much longer road, and worth it far less often than it looks.
A Noul is a yes/no question type that returns a single number from 0 to 1: the probability that the statement is true. Near 1 is a strong yes, near 0 a strong no, and near 0.5 means the model gives both answers similar weight.
Use a Score when the answer is a position on a spectrum you can describe in steps, such as bug severity or customer frustration. Use a Choice when the options have no order between them, such as which team handles a ticket or which category a product belongs to.
TypeSafe does not publish a fixed limit on questions per request; the constraint is the token budget, which is 64k per request for Jev 1.13. Questions run in parallel against the same state, so the documentation recommends sending every question your code might need in one call.
A Noul's probability distribution has only two outcomes, yes and no, so the single noul value describes it completely. Choice and Score spread probability across several options or levels, and their confidence value summarises how peaked or flat that spread is.
A Choice question accepts a maximum of 255 options. TypeSafe advises giving the full list rather than a shortlist, since each option costs only a few tokens. For taxonomies larger than 255, the documented approach is chaining Choice questions level by level.
A Score should have at least two levels and the API accepts up to 10. Each level is a description of a situation, and its number is its position in the array starting at 0. Use as many levels as you can describe distinctly, and no more.
Ready to take the first step towards unlocking opportunities, realizing goals, and embracing innovation? We're here and eager to connect.
11th Floor, O-Hub, Chandaka Industrial Estate, Infocity, Bhubaneswar, Odisha 751024
Level 4, 11 York Street Sydney Startup Hub Sydney, NSW – 2000
30 N. Đinh Nghệ, Phước Mỹ Sơn Trà, Đà Nẵng / Da Nang City – 550000
Level 25, AIDP Business Tower, Dubai Marina, United Arab Emirates
50 Beauchamp Street, Wellington, WGN 5028, New Zealand