Skip to main content
Use a Choice when the answer is one of a fixed set of options. For example, which team handles a ticket, which category a product belongs to, or which language a code snippet is written in. If the answer is a position on a spectrum, use a Score. If it’s a yes or no, use a Noul. Choose a question type compares all three. A Choice answer is the selected option in choice. The model also returns a probability for every option in probabilities, and a confidence value for the selected option. Example questions:

Request structure

The POST request body to the TypeSafe API has a specific structure. The top level has three fields: state, the content to evaluate; model; and questions, a map from question ids you choose to question objects. Each Choice question has the following fields:
  • type: Always "choice".
  • instructions: The question the model answers.
  • criteria: The answer options, as a map. Each key is an option name and each value is a description of that option.
Below is a request where the state is a support ticket from an online shoe store and the question is which team should handle it: You choose the question id, department in this case. The answer is returned under the same id. The model never sees the question id. The option names and their descriptions are both sent to the model, so write descriptions that separate the options from each other. Our client SDKs provide typed questions. In Python, the same question is a Choice:
Use the system_one method or the https://api.typesafe.ai/v1/systemone endpoint to call a System One model. The model field selects which model handles the request. How to build with TypeSafe covers where in your code to call it. Use one of our client SDKs or call the HTTP API directly. If a coding agent is writing the integration for you, install the TypeSafe agent skill first so it knows the request and response shapes.
instructions and each entry in criteria can be a string, an object, or an array. Start with a string. Use an object when a description needs several kinds of guidance, such as what an option covers, what it doesn’t cover, and some examples. See Structured instructions and criteria below and the API reference.

Response structure

The response has one entry in answers per question, under the ids from the request. This is the response to the example request above:
Besides type, each Choice answer has three values:
  • choice: The option with the highest probability.
  • probabilities: The full probability distribution across every option. The sum of all values is 1.
  • confidence: A number from 0 to 1 computed from how probabilities is spread. A flat shape, with probability spread across several options, means low confidence. A single peak on one option means high confidence.
This ticket is an easy one, so all of the probability is on returns and confidence is 1.0. A ticket that mentions a wrong size and a missing refund would split probability between returns and billing, and confidence would drop.

Good practice: ask more than one question per call

Ask every Choice your code might need in a single request rather than one request per question. Questions are evaluated in parallel. Adding questions barely changes the response time, and the code can ignore answers it doesn’t need. Extra questions still cost tokens. Ask multiple questions together explains this in full; the next section shows five Choices in one call. The same logic applies to the options inside a single Choice. A Choice accepts up to 255 options, and adding options costs a few tokens each, so give the model the full list of teams, categories, or products rather than a shortlist. Add an other or none of the above option when the list might not cover every input, so the model can say none of the others fit. To classify documents through a deep hierarchy or large taxonomy, chain Choice questions level by level. The Hierarchical Classification cookbook shows how to run a beam search over Choice probabilities, keeping the best K candidate paths at each level instead of committing to a single greedy path.

A more complex example

The basic example above routes a ticket to a team. A bigger support system might also need the return reason, the delivery problem, what the customer wants, and the customer’s tone. The request below asks five Choice questions about a ticket that is more ambiguous than the first: it involves three teams and doesn’t say what the customer wants. Two of these Choice questions are speculative: return_reason only matters if the department is returns, and shipping_issue only matters if it’s shipping. The tone question uses null descriptions because the option names are clear on their own. The TypeSafe response:
Each question is answered on its own against the ticket:
  • The department answer is returns with a 0.60 probability, but billing has 0.38 probability because of the double charge. This lowers the confidence to 0.39. The top option is clear enough to act on, but the second option is not noise.
  • The return_reason is wrong_size with a confidence of 1.0, which is expected because it says this clearly in the ticket.
  • The shipping_issue answer is split between delayed and other. It’s a speculative question and department didn’t come back as shipping, so it can be ignored by the code, as shown in the example code snippet below.
  • The requested_resolution confidence is 0.16 because of the flat probability distribution of the answers. This is because the customer didn’t say what they want.
  • The tone answer is frustrated with a probability of 0.92 and a confidence of 0.88.
The example code below reads the answers it needs, ignores the rest, and treats a low-confidence answer as a reason to ask rather than act:
For the ticket above, this assigns the ticket to the returns team with issue wrong_size, sends the billing team a copy, and asks the customer what they want. The code does not use the shipping_issue answer. One request, five answers, and the routing logic is ordinary if statements. If you later need to know the customer’s language, or which product the ticket is about, add another Choice to TRIAGE_QUESTIONS; the request count stays at one. The smart home assistant demo evaluates every user request against a long list of Choice questions in one call: the request category, the room, the device, and the action. Most of those questions are irrelevant to any one request and the code ignores them.

Structured instructions and criteria

Start with a one-line description per option. When two options are similar and the model keeps confusing them, describe each one with an object instead of a string. Give it fields for what the option covers, what belongs to a neighboring option instead, and a few example inputs. The two answer options below, return_policy and return_status, are easy to confuse. A ticket about either one can mention returns and refunds, so each option says what it is not for. The response is return_status at confidence 1.0:
The field names question, focus, what, not_for, and examples are not part of the API, and none are reserved. You choose them, the same way you choose option names. The model sees the names along with the values, so use short names that label what follows.