Noul (yes/no) questions
TL;DR
{"type": "noul", "instructions": "<yes/no question or statement>"}, with an optionalcriteria: {"true": "...", "false": "..."}. The answer is{"type": "noul", "noul": <0..1>}— the probability that the answer is yes. There is noconfidencefield on a Noul answer. Thresholdnoulin your code when you need a boolean.
When to use / when not to use
Use a Noul when the answer is yes or no: does this message ask for a refund, does this resume mention distributed systems, does this comment contain personal data.
- If the answer is one of several options → Choice questions.
- If it's a position on a spectrum → Score questions.
- Comparison of all three: Choosing between Choice, Score, Noul.
Example questions from raw/docs/primitives__noul.md:
"Is the customer requesting a refund?"
"Does this resume mention experience with distributed systems?"
"Does the message contain personally identifiable information?"
"Does the room have a minifridge?"
Probability-that-yes semantics
A Noul answer is a single number, noul, the probability that the answer is yes. It ranges from 0 to 1.
- Near 1 → a strong yes.
- Near 0 → a strong no.
- Near 0.5 → the model gives yes and no similar probability.
Phrase the instruction so that a high probability means "yes", so the returned answer is unambiguous in its meaning. Most often you will threshold noul into a boolean when your code needs a hard decision.
0.5 is not "medium"
Noul does not return a separate confidence value, and 0.5 does not mean a medium amount of the thing you asked about. For "Is the candidate strong in Python?", 0.5 means the model splits its probability between yes and no — not that the candidate has medium skill. Define what "strong" means, or use a Score questions with defined levels (no experience, some familiarity, daily use, deep expertise). An unclear definition makes the probability hard to interpret.
If what you want is a measurement rather than a decision, that is a Score question, not a Noul. See Confidence vs probability for how Choice and Score confidence differs from a Noul probability.
Request contract
| Field | Required | Type | Description |
|---|---|---|---|
type |
Yes | "noul" |
Must be "noul". |
instructions |
Yes | string | object | array |
The yes/no question or statement to evaluate. |
criteria |
No | object with true / false |
Optional { true, false } descriptions clarifying what a yes and a no mean. |
Per raw/docs/api.md, criteria.true is "What a yes (value near 1) means" and criteria.false is "What a no (value near 0) means". Both may be a string, an object, an array, or null — see Structured instructions, options, levels, criteria.
In the JavaScript SDK both parameters are optional: noul(instructions?, criteria?), with instructions defaulting to null (JavaScript/TypeScript SDK: install, client, choice/score/noul).
Example request — one Noul with criteria, one without
{
"state": "I have asked three times now. Can I please just talk to a real person?",
"model": "jev-latest",
"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"
}
}
}
}
Response
{
"model": "jev-latest",
"answers": {
"is_human_escalation": {
"type": "noul",
"noul": 0.99
},
"is_repeat_contact": {
"type": "noul",
"noul": 0.93
}
},
"usage": {
"input_tokens": 360,
"output_tokens": 39
}
}
A Noul answer carries only type and noul. There is no probabilities map and no confidence.
Python SDK
from typesafe_sdk import Noul, TypeSafeClient
with TypeSafeClient() as client:
response = client.system_one(
state="I have asked three times now. Can I please just talk to a real person?",
questions={
"is_human_escalation": Noul(
instructions="Is the customer asking for a human agent?",
),
"is_repeat_contact": 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",
},
),
},
)
print(response.answers["is_human_escalation"].noul)
print(response.answers["is_repeat_contact"].noul)
(The Noul(instructions=..., criteria={...}) construction and reading .noul off response.answers[id] are both attested in raw/docs/primitives.md and raw/docs/primitives__noul.md; this combined snippet is assembled from those two shapes — (inferred) only in that the upstream Noul page shows the request as JSON rather than Python.)
Writing a Noul question
- A Noul evaluates one yes/no question. It is defined by its
instructions. - Phrasing. Beyond a plain question, you can phrase the instruction as a statement for the model to evaluate for truthfulness: for "the customer is requesting a refund", a value near 1 means the statement is true. Try both phrasings with your own data to see what works best.
- Optional
criteria. The instruction is enough for most Noul questions, but when the boundary between yes and no is subtle, passcriteriawithtrueandfalsedescriptions to pin down what each outcome means. Try your Noul prompts with and without criteria to see which works better in your use case. - Keep
truemeaning yes. Per Jev 1.13 jaggedness: known failure modes, a Noul wheretruemaps to "no" andfalsemaps to "yes" performs worse. Treat the criteria as an extension of the instruction and align the two.
Structured true/false objects (a definition plus examples on each side) are shown in Structured instructions, options, levels, criteria and in Writing instructions and criteria that Jev reads correctly.
Using the number in code
YES = 0.5 # up to you on what you want the threshold to be, depends on your usecase.
The threshold is yours to pick and belongs in your code, not in the prompt. Two cautions from Jev 1.13 jaggedness: known failure modes:
- Don't carry a threshold tuned on a Noul over to a Choice. A Choice over options is relative (which option wins), while each Noul is absolute and can be low for all of them.
- Don't expect arithmetic identities between separate questions. On the ticket "I was charged twice for the same order. Can someone look into this?", the question and its negation asked as two Nouls returned:
refund |
not_refund |
Sum |
|---|---|---|
| 0.72 | 0.47 | 1.19 |
P(noul) and 1 - P(not noul) are not directly comparable.
For a counting use case, ask one Noul per item and add up the thresholded answers in code rather than asking for a count — the worked snippet is in Jev 1.13 jaggedness: known failure modes.
Gotchas
- No
confidencefield exists on a Noul answer; a value near 0.5 is the only "uncertain" signal you get. - 0.5 means split probability, not a medium quantity.
- Vague predicates ("strong", "important", "recent") make the number uninterpretable. State the exact condition ("Does the resume state that the candidate has used Python at work?").
- A Noul and a yes/no Choice on the same text can disagree sharply. Example from Jev 1.13 jaggedness: known failure modes on "I'm not happy with the fit. What are my options here?": Noul
noul0.22 versus Choiceprobabilities["yes"]0.01 withconfidence0.97.
Related
- Primitives: Choice, Score, Noul — the three types and how to batch them
- Choice questions, Score questions — the other two primitives
- Choosing between Choice, Score, Noul — decision table
- Writing instructions and criteria that Jev reads correctly — phrasing and negation pitfalls
- Structured instructions, options, levels, criteria — structured
true/falsecriteria - Confidence vs probability — why Noul has no separate confidence
- HTTP API: POST /v1/systemone and GET /v1/models — wire contract
- Cookbook: Classifying RAG passages — Noul as a relevance filter
Sources
- raw/docs/primitives__noul.md (https://docs.typesafe.ai/primitives/noul)
- raw/docs/api.md (https://docs.typesafe.ai/api)
- raw/docs/primitives.md (https://docs.typesafe.ai/primitives)
- raw/docs/model-jaggedness__jev-1.13.md (https://docs.typesafe.ai/model-jaggedness/jev-1.13)