Skip to content

triage-ticket

Ticket triage on typesafe.ai’s Jev, a model that is not a chat model. Its API answers typed questions about a state — which option? is this true? — with calibrated probabilities, so the typesafe() provider serves exactly the asks whose output type it can express: a string literal union (Department) becomes a choice question with one option per value, a number literal union (Priority) a choice question decoded back to the number, a boolean (urgent, refundRequested) a yes/no question that is true at probability ≥ 0.5, and a flat object of those (Triage) one request with one question per property. The JSDoc comment on each property is that question’s instructions.

src/triage.tsi
export type Department = "billing" | "shipping" | "account" | "other";
export type Priority = 1 | 2 | 3;
export interface Triage {
/** Which team owns this ticket? */
department: Department;
/** Does the customer express urgency? */
urgent: boolean;
/** 1 = low, 3 = high */
priority: Priority;
/** Is the customer asking for a refund? */
refundRequested: boolean;
}
export infer function triageTicket(.ticket: string) {
return ask ..`triage the support ticket`<Triage>;
}

Free text, numbers, arrays and nested objects are not served: the provider fails before the network with an error naming the property, so a mixed project pairs it with a general model through fallback([typesafe(), openai("gpt-5-mini")]) — see Providers API.

This is the one example whose committed config names a live vendor (model: typesafe()), because the vendor is the point. Put TYPESAFE_API_KEY=… in .env first.

Terminal window
npx nola-lang run src/main.ts # needs TYPESAFE_API_KEY
# offline: edit nola.config.ts to the mockProvider line in its comment

Scaffold: npm create nola my-app -- --template triage-ticket — the scaffolder skips the Select an inference provider: question for this template and its next steps say to set the key. Source: examples/triage-ticket on GitHub.

Next: Introduction — back to the start.