Skip to main content
TypeSafe’s primitives are the small, typed building blocks you compose in code. They come in pairs: a question defines one judgment for a System One model to make about a state, and its answer is the typed value that comes back. You compose the answers in your code to make decisions. There are three question types, each returning a different shape of answer. You can ask one question or send several together. Every question in a request sees the same state, is evaluated independently, and returns a typed answer under the ID you chose.

Ask for one snap judgment per question

System One models are built for fast, focused judgments. Ask for a judgment a knowledgeable person makes in a second given the right context. “Does this message convey urgency?” is a good question. “Analyze this message and determine the best course of action” is not. That needs slow reasoning, and it is a signal to break the task into small questions and compose the answers in code. If the judgment you want depends on several independent factors, ask about each factor separately and combine the answers with your own logic. Instead of “rate this startup pitch”, ask about market size, technical feasibility, and differentiation, then weight them in code based on their relative importance. When priorities shift, change the value of weights rather than rewriting a prompt. Ask multiple questions together shows how to do this.

Define a question

Every question has an ID, a type, and instructions. Choice and Score questions also take criteria, which define the options for a Choice or the levels for a Score. Noul questions accept criteria as an optional clarification of what yes and no mean.
  • ID. The key you pick, such as refund_requested. It identifies the answer in the response.
  • type. One of choice, score, or noul.
  • instructions. The question you are asking about the state. This is where your evaluation logic goes. Write it as a clear, specific question, or as a statement for the model to judge.
  • criteria. The possible answers: a map of options for a Choice, an ordered list of levels for a Score, and an optional description of yes and no for a Noul. Each question type’s page covers its shape.
This question asks whether a customer requested a refund:
Question IDs are for your code. They are not sent to the model. Write the complete question in instructions, even when the ID seems self-explanatory.

Choose a question type

Pick the type that matches the shape of the answer you need.
  • Choice fits when the answer is one of a known set of options with no order between them: routing a ticket to a department, classifying a document type, detecting a programming language. Give the full list of options, and add an other or none of the above option when the list might not cover every input.
  • Score fits when the answer falls on a spectrum and you can describe what each point on that spectrum means: bug severity, customer frustration, skill level. The levels are yours to define, and the model returns a position along them.
  • Noul fits a clean yes/no question where the probability itself is the useful signal: does this message report a bug, is the customer requesting a refund, does the resume mention distributed systems.
Use Noul for a yes/no judgment and Score to measure a position on a spectrum. “Is this candidate strong in Python?” needs a clear definition of “strong”. A Noul value of 0.5 means the model gives yes and no equal probability. It does not mean the candidate has a medium skill level. An unclear definition makes that probability hard to interpret.If you want to measure skill level, use a Score with defined levels, such as no experience, some familiarity, daily use, and deep expertise. If you need a yes/no decision, define the condition clearly, such as “Does the resume state that the candidate has used Python at work?”
If two types both seem to fit, prefer the one whose answer your code can act on directly. A Choice between refund, rebook, and information maps straight onto three code paths. A Score of customer frustration maps onto a threshold. A Noul maps onto an if.

What comes back

Answers are primitives too. Each question type returns a typed value that your code can compare, threshold, sort, pass into further logic, or put into the state of a follow-up request (see When one question depends on another). Two properties of these answers make them composable:
  • Every answer is constrained to the options you supplied. The model returns a probability distribution over your options or levels, never a value outside them. Your code never has to recover a value from generated prose.
  • Every answer is independent. One question’s answer is not hidden context for another. You can add or remove questions without changing the others’ results.
Confidence explains how confidence is derived from probabilities and how to use it to decide when to act automatically and when to escalate to a person.

Reference specific fields

The content being evaluated, the state, is often a JSON object with several parts: a conversation, a record, a policy. When a question is about one of those parts, name it in the instructions with a dot-and-index path to its key, including the backticks. The model then knows which part of the state to judge. Take the support conversation from the State page:
These two questions point at the customer’s message, the policy, and the charges by path:
Explicit paths make it clear which parts of a structured state should inform each judgment. See State for how to structure the input.

Ask multiple questions together

Send every question that uses the same state in one request. You can mix question types freely. System One models evaluate every question in a request in parallel. Adding questions barely changes the response time and costs only the tokens for the extra questions, which are cheap. Asking a question you might not need is close to free. This request classifies a customer message, checks for urgency, and scores frustration all at once: Our client SDKs provide typed questions and answers. In Python, pass a questions dictionary of Choice, Noul, and Score objects to client.system_one(...). This request sends a ticket and a refund policy once and gets a typed answer for each question:
See client SDKs for installation and usage in your language.

Ask speculative questions

Ask every question your code might need, including ones whose answer only matters for some inputs, and let the code decide which answers to use. If a ticket turns out not to be a bug report, ignore the severity answer. We call this the Speculative fan-out pattern. The Parallel questions cookbook shows how batching 13 questions into one call is 11.5x cheaper and 9.6x faster than 13 separate calls, with no change in the answers. The number of questions in one request is limited only by the request’s token budget, which the state and the questions share. The budget is around 32,000 tokens, roughly 150,000 characters of English text.
Coding agents fall into the one question per call habit more than people do. The TypeSafe agent skill tells your agent to put many questions in each call, including ones that only matter for some inputs.

Split a complex judgment into several questions

A judgment that depends on several things is best split into one question per thing. Combine the answers in your code, giving each a weight for its relative importance. The weights are yours. When the combined result doesn’t match what your team would decide, change them in code and run again. Adding questions barely changes the response time because they run in parallel within one request. The split costs a few extra question tokens. For example, ticket priority might be built from three Scores: how severe the bug is, how frustrated the customer is, and how much the report gives an engineer to work with. The Score page walks through this request and the code that normalizes and weights the answers in Splitting a complex judgment into several Scores. This technique is called the Composite scoring pattern.

When one question depends on another

Questions in the same request are independent: one answer does not become context for another question. If a later judgment depends on an earlier answer, make a second request in code. The dependency is real only when your code cannot build the second request until it has the first answer: it needs the answer to fetch more data for the state, to decide what the state is made of, or to pick the next question’s options. Otherwise, ask the questions together and combine their answers in code. Two requests are the exception, not the rule. If the second request’s questions could have been asked against the original state, ask them in the first request and let the code ignore the ones it doesn’t need. Three cookbooks make a second request for a real reason. Skill suggestion ranks 182 skills in one request, then fetches the full text of the top three and judges them again against that better evidence. Structure recovery asks whether each line break split a sentence, merges lines into blocks from those answers, then classifies the blocks, which did not exist until the first request had answered. Hierarchical classification uses each Choice answer to decide which options the next request offers. See How to build with TypeSafe for guidance on breaking a workflow into focused judgments.

Next steps

Choice

Pick one option from a fixed list.

Score

Rate the state along ordered levels.

Noul

Get the probability that a statement is true.
To see how these compose into system architectures, head to Patterns.