Choice
Pick a tool.
An agent holds a handful of tools and has to decide which one a request needs, if any. A Choice question picks one option from a fixed set and returns a probability for every option, so your code can see whether the pick was clear or whether two tools were nearly tied.
Choice
Pick a tool
Shows recorded and illustrative answers. This site's own live testing is unavailable.
Chosen: calendar
Read or change events on the user's own calendar
- calendar93.0%
- search2.0%
- email2.0%
- none2.0%
- calculator1.0%
This illustrative answer puts 93.0% on calendar, with search next at 2.0%. Probabilities describe the distribution over the options, not a guarantee that the choice is correct. Confidence: 0.91.
Not a live or recorded response. Shown to illustrate the shape of an answer.
Build this
import { choice, TypeSafeClient } from "@typesafe-ai/sdk"; const client = new TypeSafeClient(); // reads TYPESAFE_API_KEY, defaults to jev-latest const request = "Move my 1:1 with Priya from Thursday to Friday at the same time."; const { answers } = await client.systemOne({ state: request, model: "jev-latest", questions: { tool: choice( "Which tool should handle this request? Pick the single tool that would do most to answer it. Pick none when no tool applies and the assistant should answer directly.", { search: "Look up current information on the public internet, such as news, prices, or anything that changes", calendar: "Read or change events on the user's own calendar", email: "Draft or send an email on the user's behalf", calculator: "Evaluate an arithmetic expression exactly", none: "No tool applies. The assistant should answer directly from what it already knows", }, ), },}); const { choice: result, probabilities, confidence } = answers.tool; // Your code decides what to do with the answer.if (confidence < 0.5) { console.log("Unsure. Route to a person.", probabilities);} else { console.log("Route to " + result + " (confidence " + confidence.toFixed(2) + ")");}Type-checked against @typesafe-ai/sdk 0.6.0 as part of this site's build. Not executed against the live API by this guide.
npm install @typesafe-ai/sdk. Requires Node.js 20+. Set TYPESAFE_API_KEY in your environment.
Keep TYPESAFE_API_KEY on the server. Never embed it in client code or ship it in a browser bundle.
Reading the three samples
One tool fits. Moving a meeting is a calendar operation and nothing else in the set comes close. The probability should sit almost entirely on one option, which is what a request you can route automatically looks like.
No tool needed. A question about mutexes and semaphores wants an explanation, not an action. The answer should be “none”, and an agent that always reaches for a tool will search the web for something it already knows.
Two tools compete. Converting currency “right now” needs a live rate, which is a lookup, and then arithmetic, which is a calculation. Neither option is wrong, and the winning probability should sit barely above the runner-up. The label alone hides that. This is the sample worth watching.
The margin matters more than the label
A Choice answer always names a winner. It does so whether one option took almost all the probability or whether two split it nearly evenly, and the winner reads exactly the same in both cases. Your code sees the difference only if it looks at the distribution:
const { choice, probabilities, confidence } = answers.tool;
const [top, runnerUp] = Object.values(probabilities).sort((a, b) => b - a);
if (confidence < 0.5 || top - runnerUp < 0.15) {
askTheUser(choice); // Two plausible tools. Confirm before acting.
} else if (choice !== "none") {
invoke(choice);
}This is confidence-gated routing: the answer tells you what, and confidence tells you whether to act on it. A tool call is a side effect, so acting on a coin flip is worse here than in a recipe that only classifies.
Why “none” is an option here, and a gate in real systems
This recipe puts “none” in the option set because a single Choice has nowhere else to put it. That is a real simplification, and it has a cost: a Choice spreads probability across its options, so “none” competes with the tools rather than standing apart from them. Adding it does not give you uncertainty detection either, since the model can pick “none” confidently and can pick a tool confidently when it should have picked none.
TypeSafe's skill suggestion cookbook separates the two questions instead. It asks one Choice across the whole roster, which always names a best candidate, and alongside it a set of Noul gate questions such as whether the assistant is being asked to act on the user's system at all. Code then applies a threshold to those gates to decide whether to use anything. Whether to act and which thing to use are different judgments, and it asks them separately.
Where this fails
It picks exactly one tool. A request that genuinely needs two, like looking up a rate and then converting with it, has no correct answer in this design, and the near tie in the third sample is the model reporting that rather than making a mistake.
It returns a tool name and no arguments. Knowing to use the calendar is not the same as knowing which event, which day, or whose calendar.
The options are the ones you listed. A request needing a tool you did not include cannot be routed correctly, and will usually land on the nearest neighbour rather than on “none”.
How the TypeSafe cookbooks differ
Both cookbooks this adapts are multi-question designs. Function calling sends 54 questions in one request: a Choice for the function, a Choice for each closed-set argument, and Nouls for flags, for each member of a set argument, and for whether an optional argument was stated at all. It asks about every function's arguments at once, before knowing which function wins, so it produces a complete typed call rather than a name. Skill suggestion asks its roster-wide Choice plus the Noul gates described above, then spends a second request re-checking the top candidates. This page is one question, which is why it stops at the name.
For whether a decision like this belongs with Jev or a general-purpose model, see Jev vs LLMs.