Not Every Decision Needs a Genius. Meet Decision Models.

AI Microsoft AI Models

Meet decision models: fast, low-cost models for routing, classification, and agent control. How Microsoft-Decision-1 and Jev work, and how to try them.

Not Every Decision Needs a Genius. Meet Decision Models.

Audio version

Listen to this article

Narrated by Microsoft Foundry.

0:00 0:00
↓

Picture an AI agent working through a normal task. Before it finishes, it makes maybe twenty tiny decisions. Is this email urgent? Which tool should I use? Did that step work? Is this answer good enough to send? Should I continue, or ask a person?

Today, most agents send every one of those questions to the same large model. That model thinks about it, writes a paragraph explaining itself, and charges you for every word. It's like asking a professor to sort your mail. The professor can do it. It's just slow and expensive for a job that needs a quick yes or no.

A new kind of model was built for exactly this. In the past few weeks it went from one startup's idea to something nearly every AI company is shipping, including Microsoft. They're called decision models, and I think they'll change how agents are built.

One note, as always: I work at Microsoft. Where I quote numbers for Microsoft's model, they're Microsoft's own, and I'll say when someone else has tested them.

What a decision model is

A normal language model writes text. A decision model doesn't write anything. You give it a question and a fixed list of possible answers, and it gives back a score for each one.

"Is this support ticket urgent? Yes or no." Back comes something like: yes, 94%. No, 6%. That's the whole output. Your software can read it directly and act on it, without parsing a paragraph, and the number tells you how sure the model is.

The company behind the first one, TypeSafe AI, calls this a "System One" model, borrowing from the idea of fast and slow thinking. System One is the quick, intuitive part of your mind that recognizes a face or catches a bad smell. System Two is the slow, careful reasoning you use on a hard problem. Large language models are mostly System Two. Decision models are System One: fast, narrow, and cheap.

Where it started: Jev

The first decision model that got the world's attention was Jev, from a startup called TypeSafe AI. Its founder, Diogo Almeida, used to be a researcher at OpenAI, where he worked on ChatGPT and on RLHF (reinforcement learning from human feedback, the training method that taught chatbots to do what people want). About two years ago he left with a different idea, as he told TechCrunch when Jev launched.

His reasoning was simple. We had become very good at teaching computers to speak human language, but software doesn't speak human language. Software needs a decision it can act on, not a paragraph it has to read and interpret.

The name. Jev is named after William Stanley Jevons, a 19th-century economist known for the Jevons paradox: when something gets cheaper, people don't use less of it, they use far more. Almeida's bet is that intelligence works the same way. If a decision costs almost nothing, software will make thousands of them, for every email, every command and every step of an agent. It's the same math as the twenty decisions at the start of this post.

What's inside. TypeSafe hasn't shared the architecture. TechCrunch describes Jev as a transformer-based model that isn't a language model in the usual sense, because it doesn't produce text, and outside observers suspect it's built on top of an open-weight language model. TypeSafe says it was trained only on synthetic data, meaning data it generated itself, using a method Almeida calls reinforcement learning from calibrated decisions. Output tokens are free, and input tokens are priced by the billion instead of by the million.

The first reactions. Developers noticed quickly. Demand was so high that the company briefly couldn't serve its API. Pranit Sharma, an engineer at Vercel, reported replacing an OpenAI model that reviewed commands for safety with Jev, and getting results five to 18 times faster, with better accuracy. Nikhil Mudholkar, CTO of Bryo AI, tested Jev against Gemini on business emails and found Gemini slightly more accurate but 10 to 20 times more expensive. What he liked most was the confidence score, a real probability he could build workflows on. These are developers' own reports, collected in the TechCrunch story.

Armin Ronacher, CTO of Earendil, described the trade-off well. A decision model hands part of the reliability problem to you. If it answers with 50% probability, treat it as a coin toss. If it answers with 95%, you can act. Uses mentioned in the same story include checking what agents are doing, catching jailbreak attempts, and routing a request to the right model.

By late September, a post on Microsoft's Azure developer community blog already showed how to use Jev with agents in Microsoft Foundry. The category moved fast, and everyone was trying it.

Why it suddenly exists

Jev launched in early access on September 15. Within weeks, the rest of the industry answered. OpenAI put a Decisions API (a way for software to call the model) into public beta. Cloudflare, Perplexity, Snowflake and Liquid AI shipped their own, and several open-source models appeared too. By The Register's count, there are now more than a hundred.

A fair question is whether this is really new. Researchers have built classifiers, models that sort things into categories, for many years. What's different is the interface. You don't train anything. You write your question in plain language, list your options, and the model answers. For a developer, that's a big difference.

And speed matters more than it sounds. Microsoft makes the point with simple math: if each decision adds 100 milliseconds and an agent makes 20 decisions in a row, the user waits two extra seconds. Those delays add up quickly once an agent starts acting on its own.

Microsoft-Decision-1

On October 9, Microsoft released its entrant, Microsoft-Decision-1, in Microsoft Foundry, its platform for building AI apps, and through OpenRouter, a service that gives you one API for many models. It's built for what Microsoft lists as routing, classification, prioritization, verification and workflow control. It handles yes or no questions, multiple choice and ratings, and it can also grade an AI answer or an agent's proposed action against a rubric, a checklist of what good looks like.

A few details worth knowing:

How it's built. Microsoft post-trained Qwen3.5-9B, an open-weight model from Alibaba, to make single-pass decisions. Microsoft says it will soon rebase the model on other models, including its own MAI (Microsoft AI) family from my last series and OpenAI's.

The claims. Microsoft reports the highest accuracy across 36 benchmarks covering nearly 150,000 questions that were kept blind from training. For speed, it says the model is 2.5 times faster than the runner-up and 35 times faster than a large frontier model in its tests. The Register adds that Microsoft measured it at 2.8 times faster than Jev.

The price. $0.042 per million input tokens, and output tokens are free. Because the output is just a score, there's very little to pay for.

Robustness. A decision shouldn't change because you reworded the question or shuffled the options. Microsoft says its model changes its decision on only 1.3% of such changes on average, and never when options are reordered.

Early internal tests. Xbox Research used it to sort more than 10,000 pieces of player feedback into themes, and reported quality close to a large model, at over 14 times the speed and 200 times lower cost. The Copilot team used it to check the quality of responses and found it competitive and 100 times faster.

What it's good for

The jobs share a shape: many small decisions, fast, with a limited set of answers.

Routing. Decide which model or tool should handle a request, so the expensive model only sees hard questions.

Guarding agents. Look at an agent's proposed next step and decide: continue, stop, retry, or hand off to a person.

Judging answers. Check an AI-written response against quality rules and decide whether to accept, revise or reject it.

Labeling. Sort thousands of reviews, tickets or messages into themes.

Screening. Classify requests or outputs by risk, then allow, block or escalate.

In my own agent newsroom, I have a validator that checks every article against the editorial rules before anything moves on. That is a decision job, and it's the first place I'd test a model like this.

What to watch

The speed claims are easy to believe. The quality claims deserve more care, and others have already started testing.

Techstrong reported that Amplitude tested Jev and found that the large, expensive models were more accurate than the decision model on its benchmark. Cisco's researchers compared decision models against a classifier trained on their own safety policy, and the trained classifier won on catching harmful content at strict error limits. Jev did hold up well without any training, landing close to a 31-billion-parameter model used as a judge. So the pattern looks like this: very good for the price, not always as good as a specialist or a big model.

One independent developer, Anass Kartit, also ran Decision-1 against 13 other decision models on 82 questions he wrote himself. It got every everyday question right, never changed an answer when he reversed the options, and finished sixth overall. Jev finished third. It also did something to remember: it followed an instruction hidden inside a customer review that said to answer yes. It's a small test by one person, not a formal benchmark, but it points at the right habit. Treat any text written by users as untrusted.

You'll also hear that decision models can't hallucinate, because they can only pick from your list. That's true in a narrow way: they can't invent an answer outside your options. But they can still pick the wrong option, and pick it confidently. A wrong answer in a tidy format is still wrong.

That's why the confidence score matters. A good decision model is calibrated, meaning a 90% score should be right about nine times in ten. When you know that, you can use it: act on high confidence, and send low confidence to a bigger model or a person.

Which decisions should a model make?

My rule is simple. Let the fast model make decisions that are small, frequent and easy to undo. Is this ticket urgent? Which category is this? Does this answer meet the rubric? If it's wrong occasionally, nothing breaks, and you can correct it.

Keep people in the loop for decisions that are expensive or can't be reversed: sending money, deleting data, anything with real consequences for someone. And use the confidence score as the bridge, so the system knows when to stop guessing and ask.

The model that decides fast on the cheap calls frees the slow, expensive thinking for the calls that deserve it.

Your first decision call

Let's walk through a support ticket. It says the API returns a server error on every call. We want to know which team should handle it: billing, engineering, or support. We'll use Microsoft Foundry, but the idea is the same everywhere: you send some content, called the state, plus named questions, and you get numbers back.

If you're listening, you don't need to follow the syntax. I'll explain what each example does and why it matters. The runnable commands and code are in the written article.

First, deploy Microsoft-Decision-1 from the model catalog in Foundry. Microsoft has a step-by-step guide. Your application needs three things: the address of your Foundry resource, the name you gave your deployment, and a sign-in token from Microsoft Entra ID, Azure's sign-in service.

export AZURE_ENDPOINT="<your-foundry-resource-endpoint>"
export DEPLOYMENT_NAME="<your-deployment-name>"
export AZURE_ENTRA_TOKEN=$(az account get-access-token \
  --resource https://cognitiveservices.azure.com \
  --query accessToken --output tsv)

The request sends the ticket and asks, "Which team should handle this?" Each possible answer has a description: billing handles charges and refunds, engineering handles bugs and outages, and support handles how-to and account questions. Those descriptions tell the model what each category means. You can send the request with curl, a command-line tool for sending web requests.

curl "$AZURE_ENDPOINT/providers/microsoft/v1/systemone" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AZURE_ENTRA_TOKEN" \
  -d '{
    "model": "'"$DEPLOYMENT_NAME"'",
    "state": "The API returns 500 on every call.",
    "questions": {
      "team": {
        "type": "choice",
        "instructions": "Which team should handle this ticket?",
        "criteria": {
          "billing": "Charges, invoices, and refunds",
          "engineering": "Bugs, errors, and outages",
          "support": "How-to and account questions"
        }
      }
    }
  }'

One setup detail matters: the request identifies your deployment by the name you gave it, not by the model's catalog name.

The response gives your software a selected team and a probability for each option. Imagine it chooses engineering with 97 percent probability, compared with one percent for billing and two percent for support. Those are made-up numbers to illustrate the response, not a measured result. The data comes back as JSON, a text format that software can read directly.

{
  "model": "microsoft-decision-1",
  "answers": {
    "team": {
      "type": "choice",
      "choice": "engineering",
      "probabilities": { "billing": 0.01, "engineering": 0.97, "support": 0.02 }
    }
  },
  "usage": { "input_tokens": 87, "output_tokens": 3 }
}

No paragraph, no explanation. A choice, and a probability for every option.

Three kinds of question

There are three question types, and one request can mix them.

choice picks one option from a list. Use it for routing and classification.

noul is the API's unusual name for a yes or no question. You get the probability that the answer is yes. A value of 0.9, for example, means a 90 percent probability of yes.

score places something on an ordered scale you describe, from lowest to highest, such as cosmetic, minor, major, critical.

Questions about the same content can share one request, which saves calls and keeps the context the same. Imagine a customer writes, "Checkout is down again. This is my third request." You can ask three things at once: which team should handle it, how severe the issue is, and whether the customer has contacted support before. Each question looks at the same message, but asks for a different kind of decision.

{
  "model": "<your-deployment-name>",
  "state": {
    "message": "Checkout is down again. This is my third request.",
    "customer_contact_count": 3
  },
  "questions": {
    "team": {
      "type": "choice",
      "instructions": "Which team should handle this request?",
      "criteria": {
        "billing": "Charges, invoices, and refunds",
        "engineering": "Bugs, errors, and outages",
        "support": "How-to and account questions"
      }
    },
    "severity": {
      "type": "score",
      "instructions": "How severe is this issue?",
      "criteria": ["Cosmetic", "Minor", "Major", "Critical"]
    },
    "repeat_contact": {
      "type": "noul",
      "instructions": "Has the customer contacted support before?"
    }
  }
}

Act, or ask a person

This is where the probability becomes useful in a workflow. The routing example asks the model to choose a team, then checks the probability of that choice. If it is at least 85 percent, the software routes the message. If it is lower, the software asks a person instead.

There is also a fourth option: "cannot tell." If the model chooses that, the message goes to a person regardless of the probability. The Python example implements those two checks.

import json
import os
import urllib.request

from azure.identity import DefaultAzureCredential

ENDPOINT = os.environ["AZURE_ENDPOINT"].rstrip("/")
DEPLOYMENT = os.environ["DEPLOYMENT_NAME"]
TOKEN_SCOPE = "https://cognitiveservices.azure.com/.default"
CREDENTIAL = DefaultAzureCredential()

TEAMS = {
    "billing": "Charges, invoices, and refunds",
    "engineering": "Bugs, errors, and outages",
    "support": "How-to and account questions",
    "cannot_tell": "The message does not clearly fit any other team",
}


def ask_team(text, options):
    """Ask the decision model which team should handle a message."""
    body = json.dumps({
        "model": DEPLOYMENT,
        "state": text,
        "questions": {
            "team": {
                "type": "choice",
                "instructions": "Which team should handle this message?",
                "criteria": options,
            }
        },
    }).encode("utf-8")

    request = urllib.request.Request(
        f"{ENDPOINT}/providers/microsoft/v1/systemone",
        data=body,
        headers={
            "Authorization": f"Bearer {CREDENTIAL.get_token(TOKEN_SCOPE).token}",
            "Content-Type": "application/json",
        },
        method="POST",
    )
    with urllib.request.urlopen(request, timeout=60) as response:
        return json.load(response)["answers"]["team"]


def route(text, threshold=0.85):
    """Route the message, or hand it to a person when the model is unsure."""
    answer = ask_team(text, TEAMS)
    choice = answer["choice"]
    confidence = answer.get("probabilities", {}).get(choice, 0.0)

    if choice == "cannot_tell" or confidence < threshold:
        return {"action": "ask_a_person", "guess": choice, "confidence": confidence}
    return {"action": "route", "team": choice, "confidence": confidence}

Two details matter here. Giving the model a "cannot tell" option means it can say "none of these," rather than being forced to pick a team that doesn't fit. Microsoft's documentation recommends this.

And 85 percent is only an example threshold, not a guarantee that routing is safe. Choose your own cut-off by testing messages whose correct teams you already know. Check which mistakes each threshold would let through, and which messages it would send to a person.

Does the order change the answer?

Microsoft's documentation also suggests testing whether shuffling your options changes the results. A good decision model should read the options, not just prefer the first one.

The test is simple. Ask which team should handle a message and record the answer. Then ask about the same message five more times, shuffling the team order each time. Count how often the answer differs from the original. Repeat that across a set of real messages.

import random

from route import TEAMS, ask_team


def flip_rate(messages, options=TEAMS, runs=5):
    """How often does shuffling the option order change the answer?"""
    flips = 0
    total = 0
    for text in messages:
        baseline = ask_team(text, options)["choice"]
        for _ in range(runs):
            items = list(options.items())
            random.shuffle(items)
            if ask_team(text, dict(items))["choice"] != baseline:
                flips += 1
            total += 1
    return flips / total

That gives you a flip rate: the fraction of shuffled requests where the answer changed. Zero means no changes; a rate of 0.1 means the answer changed in ten percent of the shuffled requests. Lower is better, but a stable answer can still be wrong. Check accuracy separately. To run the Python test, save the routing example as route.py and pass your real messages to the test function.

The same call through OpenRouter

If you'd rather use a gateway than an Azure account, OpenRouter serves the same model through its Decisions API. The idea stays the same: send the ticket, your question, and the possible teams. You authenticate with an OpenRouter API key instead of an Azure sign-in token, and identify Microsoft-Decision-1 using OpenRouter's model identifier.

curl https://openrouter.ai/api/alpha/decisions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "microsoft/microsoft-decision-1",
    "state": "The API returns 500 on every call.",
    "questions": {
      "team": {
        "type": "choice",
        "instructions": "Which team should handle this ticket?",
        "criteria": {
          "billing": "Charges, invoices, and refunds",
          "engineering": "Bugs, errors, and outages",
          "support": "How-to and account questions"
        }
      }
    }
  }'

Two warnings. This is OpenRouter's alpha endpoint, so details can change. And it's a different API from chat, so the usual chat libraries won't work with it.

And Jev

Jev is on OpenRouter too, and it speaks the same API. OpenRouter has a Jev tutorial if you want the full reference. To ask Jev the same question, change the model identifier from Microsoft's model to Jev version 1.13. The ticket, question, and team descriptions stay the same.

-    "model": "microsoft/microsoft-decision-1",
+    "model": "typesafe/jev-1.13",

That's the swap-friendly setup I keep asking for. You can compare the models without rewriting the task.

The comparison example uses a customer whose checkout page goes blank after clicking Pay, even after trying two browsers. It asks both models which team should own the ticket, and whether the customer is reporting a software defect. For each model, it reports the chosen team, that team's probability, the probability that the message describes a bug, and the reported request cost. These are answers to compare, not proof that either model is right.

import json
import os
import urllib.request

URL = "https://openrouter.ai/api/alpha/decisions"
MODELS = ["microsoft/microsoft-decision-1", "typesafe/jev-1.13"]

TICKET = "My checkout page shows a blank screen after I click Pay. I have tried two browsers."
QUESTIONS = {
    "team": {
        "type": "choice",
        "instructions": "Which team should own this ticket?",
        "criteria": {
            "payments": "Checkout, billing, or payment processing issues.",
            "frontend": "Rendering, layout, or browser compatibility issues.",
            "account": "Login, permissions, or profile issues.",
        },
    },
    "is_bug": {
        "type": "noul",
        "instructions": "Is the customer reporting a software defect?",
        "criteria": {
            "true": "The customer describes broken or unexpected product behavior.",
            "false": "The customer is asking a question or requesting a feature.",
        },
    },
}


def decide(model):
    body = json.dumps({"model": model, "state": TICKET, "questions": QUESTIONS}).encode("utf-8")
    request = urllib.request.Request(
        URL,
        data=body,
        headers={
            "Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
            "Content-Type": "application/json",
        },
        method="POST",
    )
    with urllib.request.urlopen(request, timeout=60) as response:
        return json.load(response)


for model in MODELS:
    result = decide(model)
    team = result["answers"]["team"]
    chance_of_bug = result["answers"]["is_bug"]["noul"]
    print(model)
    print(f"  team:   {team['choice']} ({team['probabilities'][team['choice']]:.2f})")
    print(f"  is_bug: {chance_of_bug:.2f}")
    print(f"  cost:   {result['usage'].get('cost')}")

A few things worth knowing when you compare them.

Read the probability yourself. In the answers I saw, Jev's choice answers include a confidence number that summarizes how concentrated the probabilities are, and Decision-1's did not. Rather than relying on that extra field, the routing logic reads the probability assigned to the chosen team. That works with both models.

Pin your version. Jev has a latest-version alias that always points to the newest release. If you tuned your thresholds against version 1.13, request that specific version so the model doesn't quietly change under you. It's the same lesson as my model series: the model you build on will change, so decide when.

Questions don't see each other. When you put several questions in one request, they're answered in parallel and can't see each other's answers. Don't write a question that depends on another.

TypeSafe also offers its own JavaScript and Python SDKs, which you can point at OpenRouter if you already use them.

Try it yourself

Pick one step in an agent you already run that currently asks a big model a yes or no question. Take 200 real examples from your own data, with the correct answers labeled. Run them through your current model and through a decision model, and compare three things: how often each is right, how long it takes, and what it costs. Then shuffle the options and check how often the answers change.

Start with one small, reversible decision and a clear rule for when to ask a person. The written article includes the routing, option-shuffling, and model-comparison code so you can try this on your own data.

Microsoft-Decision-1 is in the Foundry catalog and on OpenRouter, and Jev and several open models are easy to try too. Whatever you pick, test it on your data, not on someone's benchmark. Your questions are the only benchmark that counts.

The right model for the role

If you've followed this series, you know my rule for building with AI: don't pick one model, hire a team. A decision model is a new role on that team. Not the thinker, not the writer, but the fast one at the door, sorting what comes in and deciding who deals with it.

Not every decision needs a genius. The skill is knowing which ones do.

Pass it on

Share this article

LinkedIn X

Read next

Related articles