Jev Noul: The Yes/No Question Type
Last verified against the TypeSafe docs on 22 September 2026 · model jev-1.13.0
What a Noul question looks like
Every Noul question has three fields. `type` is always `"noul"`. `instructions` holds the yes/no question you want answered, or a statement for the model to judge. `criteria` is optional: an object with a `true` and a `false` description that pins down what counts as a yes and what counts as a no.
The request below sends one support message and asks two questions about it. The first relies on its instructions alone; the second adds criteria because the boundary is less obvious.
{
{
"state": : "I have asked three times now. Can I please just talk to a real person?",
,
"questions": {
: {
"is_human_escalation": {
: {
"type": : "noul",
,
"instructions": : "Is the customer asking for a human agent?"
},
},
"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"
}
}
}
}
}
}
}
}from typesafe_sdk typesafe_sdk import Noul, NoulCriteria, TypeSafeClient
Noul, NoulCriteria, TypeSafeClient
with TypeSafeClient() TypeSafeClient() as client:
response = client.system_one(
model= client:
response = client.system_one(
model="jev-latest",
state=,
state="I have asked three times now. Can I please just talk to a real person?",
questions={
,
questions={
"is_human_escalation": Noul(
instructions=: Noul(
instructions="Is the customer asking for a human agent?",
),
,
),
"is_repeat_contact": Noul(
instructions=: Noul(
instructions="Has the customer contacted support about this before?",
criteria=NoulCriteria(
true=,
criteria=NoulCriteria(
true="Mentions a prior attempt, ticket, or that they have asked before",
false=,
false="No sign of any previous contact",
),
),
},
)
print(response.answers[,
),
),
},
)
print(response.answers["is_human_escalation"].noul)
print(response.answers[].noul)
print(response.answers["is_repeat_contact"].noul)].noul)The question IDs, `is_human_escalation` and `is_repeat_contact`, are yours to choose. They identify the answers in the response and are never sent to the model, so the full question belongs in `instructions` even when the ID looks self-explanatory.
What comes back
The response carries one entry in `answers` per question, under the IDs you sent:
{
{
"model": : "jev-1.13.0",
,
"answers": {
: {
"is_human_escalation": {
: {
"type": : "noul",
,
"noul": : 0.99
},
},
"is_repeat_contact": {
: {
"type": : "noul",
,
"noul": : 0.93
}
},
}
},
"usage": {
: {
"input_tokens": : 360,
,
"output_tokens": : 39
}
}
}
}Both values are close to 1. The customer asks to talk to a real person, so `is_human_escalation` comes back at 0.99, and "I have asked three times now" matches the `true` description on the second question, which lands at 0.93.
How to read the number
A value near 1 is a strong yes. A value near 0 is a strong no. A value near 0.5 means the model gives yes and no similar probability.
These are the values the TypeSafe docs record for `jev-1.13.0` on the question "Is the customer asking for a human agent?", across six different messages:
| State | `noul` |
|---|---|
| Thanks, that fixed it! | 0.02 |
| How do I reset my password? | 0.07 |
| I need this sorted today, whatever it takes. | 0.26 |
| Are you a bot? | 0.40 |
| Is there any way to speak to someone about my invoice? | 0.84 |
| I have asked three times now. Can I please just talk to a real person? | 0.99 |
The top and bottom of that table are easy. The interesting ones are in the middle. "I need this sorted today, whatever it takes" is urgent but never asks for a person, and lands at 0.26. "Are you a bot?" hints at wanting a human without asking for one, and the model splits almost evenly at 0.40. Those are exactly the messages your threshold has to decide about.
Why a Noul has no confidence value
Choice and Score answers carry a `confidence` field. Noul does not, and reading `.confidence` off a Noul answer will not give you one.
The reason is in the shape of the distribution. A Noul has only two outcomes, yes and no, so a single number describes the whole distribution: 0.93 for yes leaves 0.07 for no, and there is nothing left to summarize. A Choice spreads probability across your options and a Score across your levels, and `confidence` exists to describe how peaked that spread is. With two outcomes, the probability already is the certainty.
Choosing a threshold
The threshold lives in your code, not in the model. Most of the time you turn the value into a boolean and branch on it:
wants_human = response.answers[wants_human = response.answers["is_human_escalation"].noul > ].noul > 0.9
if wants_human:
route_to_agent(ticket)
wants_human:
route_to_agent(ticket)
else:
route_to_bot(ticket):
route_to_bot(ticket)Where to put the line depends on what being wrong costs. Use 0.5 when a yes and a no are equally easy to act on. Raise it when acting on a false yes is expensive, like paging someone or issuing a refund. Lower it when missing a true yes is expensive, like failing to flag a safety issue.
A third option is to not decide at all. Send values in the middle to a person and keep both code paths for the clear cases:
YES = YES = 0.8
NO =
NO = 0.2
wants_human = answers[
wants_human = answers["is_human_escalation"].noul
].noul
if NO < wants_human < YES:
send_to_review(message)
NO < wants_human < YES:
send_to_review(message)
elif wants_human > YES:
route_to_agent(message)
wants_human > YES:
route_to_agent(message)
else:
route_to_bot(message):
route_to_bot(message)The gap between `NO` and `YES` is a dial. If reviewers are seeing too many messages, narrow it. If too many wrong routes are getting through, widen it.
A Noul is not a scale
The value runs from 0 to 1, which makes it tempting to read as a measurement. It is not. It is the probability that the answer is yes, and when the underlying question is really about degree, that probability does not measure the degree.
The TypeSafe docs make the point with four candidates, asking a Noul "Is the candidate strong in Python?" next to a Score with four levels — no experience, some familiarity, regular use in a job, deep expertise:
| Candidate | Noul | Score |
|---|---|---|
| My experience is in Java and Go. I have not used Python. | 0.03 | 0.0 |
| I have used Python occasionally for small scripts alongside my main Java work. | 0.14 | 1.0 |
| I used Python every day for two years in my last job, mostly data pipelines. | 0.81 | 2.05 |
| I have written Python daily for eight years, including maintaining a large Django codebase. | 0.92 | 2.89 |
You could decide in your own code that 0.3 to 0.7 means "some experience", but the model never sees those bands, so nothing in the answer was judged against them. A middle value can mean medium experience or an unclear case, and the spacing between candidates is not something you chose. The Score judges each level description on its own, so every candidate lands on or near a level you wrote.
If you want the degree, write a Score with levels you define.
Writing a good Noul question
- Ask one thing. "Is the customer angry and asking for a refund?" makes the model judge two conditions at once and the number means less. Ask two Nouls and combine them in code.
- Phrase it so a high value means yes. "Does the message contain personal data?" is clear. "Is the message free of personal data?" inverts the meaning, and code that reads it later will get it backwards.
- Remove the middle ground. "Does this candidate have any Python experience?" works well because "any" leaves nothing in between.
- Add criteria only when the boundary is subtle. The instruction alone is enough for most Nouls. Try your questions both ways on your own documents and keep whichever answers better.
- A statement works as well as a question. For "The customer is requesting a refund", a value near 1 means the statement is true.
Noul, Choice or Score
| Noul | Choice | Score | |
|---|---|---|---|
| Asks | Is this true? | Which of these options? | Which level? |
| `criteria` shape | Optional object with `true` and `false` descriptions | Map of option name to description | Ordered array of level descriptions |
| Returns | `noul` | `choice`, `probabilities`, `confidence` | `score`, `legend`, `probabilities`, `confidence` |
| Value range | 0 to 1 | One of your option keys | 0 to the top level number |
| Has `confidence` | No | Yes | Yes |
| Size limit | — | Up to 255 options | At least 2 levels, up to 10 |
| Your code does | An `if` | Branches per option | Compares to a threshold |
flowchart TD
A[What shape is the answer?] --> B{Yes or no?}
B -- Yes --> C[Noul]
B -- No --> D{Do the answers<br/>have an order?}
D -- No --> E[Choice]
D -- Yes --> F{Can you describe<br/>each level?}
F -- Yes --> G[Score]
F -- No --> Euse a Choice when the answer is one of several options with no order between them, and a Score when it is a position on a spectrum you can describe in steps. A common mistake is asking three separate Nouls where one Choice would do: if exactly one of the options is true, a Choice gives you the winner plus the full distribution in one answer.
When to use a Noul
Nouls fit filters, gates and checklists: does this message contain personal data, does this ticket ask for a refund, does this passage support the claim it cites. They are also good in bulk. Because questions in one request are evaluated independently and in parallel, a checklist of twenty conditions is twenty Nouls in a single call, and your code decides what the combination means.
They fit badly when the answer is a degree, when the question has two conditions in it, or when you want something extracted rather than judged.
Related primitives
FAQ
Does a Noul return true or false?
No. It returns a number between 0 and 1, the probability that the answer is yes. Turning it into a boolean is your code's job, and where you draw that line is a decision about what being wrong costs.
What does a Noul of 0.5 mean?
That the model gives yes and no roughly equal probability. It does not mean "medium" or "halfway". If your question is really about degree, use a Score instead.
Does a Noul have a confidence value?
No, and this is the one field difference between Noul and the other two types. A Noul distribution has only two outcomes, so the single value describes it completely.
Can I ask several Nouls in one request?
Yes, and the TypeSafe docs recommend it. Questions in a request are evaluated in parallel and independently, so adding Nouls barely changes the response time and costs only the extra question tokens.
Do two opposite Nouls add up to 1?
Not necessarily. Each question is judged on its own, so "Does this mention Python?" and "Does this avoid mentioning Python?" are two separate judgments, not two halves of one. If you want the complement of a Noul, compute `1 - noul` in your code.
Is "noul" a word?
In Jev it is the name of the yes/no question type and the name of the field its answer comes back in. It is unrelated to the Romanian word or the storm name you may find searching for the term on its own.
Sources
jev-ai.dev is an independent guide and is not affiliated with TypeSafe AI.