Jump to the TypeScript quickstart: one client.evaluate() call asks a choice(), a score() and a booleanQuestion() about the same support message.
Try it online (sign-in required): Phishing email check
A note on naming: on system-one.dev, "System One" means our open-source TypeScript SDK (
@system-one-ai/core) plus a hosted decision API. "Decision model" in this article means the model category. The Jev docs use "System One model" as their own category name; we use it only to describe the same kind of model.
Where a decision model fits in an agent
The name borrows Daniel Kahneman's System 1 / System 2 split from Thinking, Fast and Slow. In an agent that becomes a division of labour:
- LLM (System 2): generate, summarize, rewrite, explain, and reason when you cannot list the possible answers in advance.
- Decision model (System 1): judgments whose answer space you can list in advance: which one, how much, yes or no.
In practice: user input → decision model (route, gate or rank) → your code acts on the typed result. Low-confidence or open-ended cases go to an LLM or a person.
The Jev docs describe a System One model as one that evaluates state and returns typed answers with probabilities: it reads natural language like an LLM, but it doesn't write replies or code and doesn't explain its reasoning. Microsoft's Microsoft-Decision-1 docs draw the same line: use a generative LLM to create, summarize, rewrite or explain content, or combine the two by using the decision model to route or gate requests first. For routing requests between small and large models, see LLM model routing.
The three primitives: Choice, Score, Noul
System One uses the same names as the Jev docs:
- Choice (which one?): picks one of your options and returns a probability for each. Agent use: tool and task routing.
- Score (how much?): a probability-weighted score on an ordered rubric, which can land between two levels. Agent use: ranking and priority by relevance, urgency or quality. See using an ordered rubric.
- Noul (yes or no?): P(true), from 0 to 1. Agent use: intent, rule and completion checks. See estimating P(true).
OpenAI uses slightly different names: its yes/no type is predicate, alongside choice and score. The idea is the same.
Jev and the OpenAI Decisions API
Jev. The flagship model from TypeSafe; its docs call it the first System One model. You call it with POST /v1/systemone, and it supports Choice, Score and Noul. According to the Jev docs, Jev currently takes text only (strings, JSON objects, arrays of text), not images, audio or video. English is its primary training language; the docs say other languages work but recommend testing on your own content. system-one.dev offers Jev.
OpenAI Decisions API. OpenAI announced an open public beta on its developer forum on October 6, 2026. The docs say it is in beta with general availability expected in the coming weeks. It currently supports one model, gpt-6-luna, through a dedicated POST /v1/decisions endpoint, and it can evaluate text, images or both (images must be inline base64).
Others. Microsoft-Decision-1 is deployed in Microsoft Foundry, takes text or JSON state and supports noul, choice and score questions. See Microsoft-Decision-1: what it does.
The comparison table at the end gives a source and check date for every cell.
Where System One fits
System One isn't trying to be another one of these models. It addresses a different problem: keeping your question definitions in your own code.
- Define questions and handle typed results with the SDK. Connect to the System One hosted API, or configure another supported model service directly. Your code controls what happens next.
- Billing (hosted API): every 4KB of request is one block, and anything under 4KB still counts as one block. Cost = blocks × questions × the model's price per block. Credits are reserved before inference and refunded for inferences recorded as failed. Successful replays with the same Idempotency-Key and the same request body aren't charged again. New accounts get 100 free credits on sign-up. See pricing.
- Request limits (from the docs): up to 32 questions, 255 Choice options, 10 Score levels and a nesting depth of 32. Text-only requests are capped at 65,536 bytes. The selected model may set tighter limits;
GET /v1/modelsis authoritative. - Hosted models: system-one.dev offers Jev, Clef Flash and Clef. Get exact model IDs, prices and limits from
GET /v1/models.
When to use a decision model, and when not to
Use one when:
- you can list the possible answers in advance: a tool list, queues, rubric levels, yes/no;
- the call is frequent and latency- or cost-sensitive;
- you want to split traffic by threshold: act automatically when confident, hand off to a person or a reasoning model when not.
Don't use one for:
- open-ended generation such as replies, code or summaries;
- tasks where you need the model to show its reasoning;
- questions where the answer space itself is unknown.
The System One docs recommend that you define the allowed answer space first, keep business actions in application code, send uncertain decisions to a person or a reasoning model, and validate on representative inputs before you rely on a threshold.
Can you trust the probabilities? (and how is this different from logprobs?)
What the official docs confirm:
- The Jev docs say System One models are trained for calibrated decisions, with probabilities meant to reflect uncertainty. But calibration holds across a set of predictions; it doesn't guarantee that any single answer is correct.
- In the Jev docs,
confidenceis a statistic derived from the probability distribution, not "the probability of being right". For Choice it measures how far the top probability is from a uniform spread; Score also considers how far probability sits from the most likely level; Noul has no separate confidence. - Confidence algorithms differ between models, so a threshold tuned on Jev doesn't transfer to another model. OpenAI's and Microsoft's docs both recommend setting thresholds from labelled examples from your own application and weighing the cost of false positives against false negatives.
A rigorous comparison with logprobs is planned as a separate article; we draw no conclusion here.
TypeScript quickstart
This code comes from the dev team's example (examples/decision-articles/01-what-is-a-decision-model.ts). It asks one Choice, one Score and one Noul (booleanQuestion) about a support message. Your application still assigns the work.
ts/**
* Article 1 — What is a decision model?
*
* A decision model here is application-owned: shared `state` plus named
* questions built with the published SDK. System One returns a choice, a
* score on your rubric, and P(true). It does not classify tickets, assign
* owners, or call tools.
*
* Packages used: @system-one-ai/core, adapter-system-one, transport-fetch.
* Hosted endpoint: POST /v1/systemone (SDK path `{baseURL}/systemone`).
* There is no separate "classify" or "score" URL.
*/
import { createSystemOne, choice, score, booleanQuestion } from '@system-one-ai/core';
import type { EvaluationClient } from '@system-one-ai/core';
import { systemOneAdapter } from '@system-one-ai/adapter-system-one';
import { createFetchTransport } from '@system-one-ai/transport-fetch';
export const classifyAndScoreQuestions = {
team: choice('Choose the team that should review this message.', {
billing: 'Payments, invoices, and refunds',
support: 'Technical issues with the product',
review: 'Needs a person; the request is incomplete or consequential',
}),
urgency: score('Rate urgency using this ordered rubric.', [
'Routine review',
'Timely response',
'Immediate human attention',
]),
refundRequested: booleanQuestion('Does the message report a request for a refund?'),
};
export function createHostedClient() {
const apiKey = process.env.SYSTEM_ONE_API_KEY;
const baseURL = process.env.SYSTEM_ONE_BASE_URL;
const model = process.env.SYSTEM_ONE_MODEL;
if (!apiKey || !baseURL || !model) {
throw new Error('Set SYSTEM_ONE_API_KEY, SYSTEM_ONE_BASE_URL (…/v1), and SYSTEM_ONE_MODEL from GET /v1/models.');
}
return createSystemOne({
apiKey,
baseURL,
model,
adapter: systemOneAdapter,
transport: createFetchTransport(),
timeoutMs: 30_000,
maxRetries: 0,
});
}
/** Classify a support message and score urgency. Application code still assigns work. */
export async function classifyAndScore(client: EvaluationClient, message: string) {
const result = await client.evaluate({
state: { message },
questions: classifyAndScoreQuestions,
});
return {
team: result.answers.team.choice,
urgency: result.answers.urgency.score,
refundRequested: result.answers.refundRequested.probability,
model: result.model,
requestId: result.response.requestId,
};
}
async function main() {
const message = process.env.EXAMPLE_MESSAGE ?? 'I was charged twice. Please refund the duplicate.';
const decision = await classifyAndScore(createHostedClient(), message);
console.log(JSON.stringify(decision, null, 2));
}
if (process.argv[1] && import.meta.url.endsWith(process.argv[1].split(/[\\/]/).pop() ?? '')) {
main().catch((error: unknown) => {
console.error(error instanceof Error ? error.message : error);
process.exitCode = 1;
});
}
Run it (from the example README; real calls are billed and need a key and a model from the catalog):
bashexport SYSTEM_ONE_API_KEY=...
export SYSTEM_ONE_BASE_URL=https://system-one.dev/v1
export SYSTEM_ONE_MODEL=... # exact ID from GET /v1/models
node --experimental-strip-types examples/decision-articles/01-what-is-a-decision-model.ts
Notes:
- The hosted API has one evaluation endpoint,
POST /v1/systemone. There is no separate classify or score URL. - Take the model ID from
GET /v1/models; don't invent aliases. A full model ID selects a model, but it can't pin a model version. - Without credentials, the example throws a configuration error (it fails closed).
Next: docs, TypeScript SDK, API reference, pricing, npm @system-one-ai/core, or try the demos.
No latency or accuracy column: the speed claims available are vendor statements we have not measured.