OpenAI's Decisions API: A Fast Classifier for Agent Routing, and the Calibration Test You Have to Run Yourself
On October 6, 2026, OpenAI moved the Decisions API from the limited preview announced at DevDay into public beta for every developer, with general availability promised in the coming weeks. It is a small API. It does one thing: you give it some text or an image, a question, and the complete list of acceptable answers, and it gives you back an answer with a probability attached. No prose, no JSON to parse, no retry when the model wanders off the schema.
That one thing happens to be the most common thing an agent does. Route this request. Decide whether the tool call is safe. Pick the next step from the list of allowed steps. Rate how bad this bug report is. Most production agents spend more calls on these questions than on generating anything, and most of them answer the questions by prompting a general model for free text and parsing what comes back. The Decisions API is OpenAI saying that step deserves its own endpoint. It is right about that. We have been using it on the routing step of a multi-agent system we work on, and the improvement was real. The interesting part is what you find when you measure it, which is what the rest of this post is about.
What Shipped
The endpoint is POST /v1/decisions. The only supported model is gpt-6-luna, OpenAI's cheapest current model. Input is a plain string or a list of user messages that mix text and inline base64 images. Hosted image URLs and file IDs are not accepted. Pricing is $0.10 per million input tokens with no charge for output tokens and no cache charges. OpenAI claims responses arrive about ten times faster than the same model through the Responses API, and launch coverage puts that at roughly 150 milliseconds against 1.6 seconds, from a demo that routed ten thousand support requests across three departments. The methodology behind that number has not been published, so treat it as a vendor figure until you have your own.
A request carries one or more questions, and there are three kinds.
A predicate asks whether a statement is true and returns a single probability.
{
"model": "gpt-6-luna",
"input": [{
"role": "user",
"content": [
{"type": "input_text", "text": "Inspect the product in this photo."},
{"type": "input_image", "image_url": "data:image/png;base64,..."}
]
}],
"questions": [{
"type": "predicate",
"name": "visible_damage",
"instructions": "Does the product have visible damage, such as a crack, tear, or dent? Ignore shadows and damage to the packaging."
}]
}{"answers": [{"type": "predicate", "name": "visible_damage", "probability": 0.92}]}A choice asks the model to pick one of the values you supply and returns the pick, a probability for every option, and an overall confidence.
{
"model": "gpt-6-luna",
"input": "I was charged twice for my order.",
"questions": [{
"type": "choice",
"name": "department",
"instructions": "Which department should handle this complaint?",
"choices": [
{"value": "billing", "description": "Payments, invoices, and refunds."},
{"value": "technical", "description": "Problems using the product."},
{"value": "shipping", "description": "Delivery and tracking."},
{"value": "other", "description": "Requests outside these categories."}
]
}]
}{
"answers": [{
"type": "choice",
"name": "department",
"choice": "billing",
"probabilities": [
{"value": "billing", "probability": 0.95},
{"value": "technical", "probability": 0.02},
{"value": "shipping", "probability": 0.01},
{"value": "other", "probability": 0.02}
],
"confidence": 0.93
}]
}A score rates the input against an ordered set of levels. The returned score is the probability-weighted average of the level indices, so it can land between levels. A bug that is probably "workaround available" with some chance of "fully blocked" scores 1.1 on a three-level scale.
Independent questions can share one request and one input. If a second question depends on the answer to the first, you send two requests. OpenAI's own guidance says to include a fallback option such as other whenever your categories do not cover every input, and to set thresholds for routing, filtering, or review from labeled examples out of your own application, weighing what a false positive costs against what a false negative costs. Zero data retention and HIPAA eligibility are available, and data residency covers the US and the EEA plus Switzerland.
Where It Belongs in an Agent
The reason this endpoint exists is a pattern anyone who has shipped an agent will recognize. The model that plans and writes is a poor fit for the dozens of narrow yes or no questions around it, and it is expensive and slow to ask it anyway. So teams write a classifier prompt, ask for a one-word answer or a tiny JSON object, parse it, validate it against the allowed set, retry when it fails validation, and log the whole exchange. That code is boring, it is everywhere, and it is where a surprising share of production incidents start, because the parsing path is the one nobody tested with the odd inputs.
A decision endpoint replaces that loop with a bounded call. You list the answer space before you ask. The response is guaranteed to come from that space. What you get back is a distribution, which means the application can act on uncertainty instead of flattening it: route to a human when the top two options are close, require confirmation when a predicate sits in the middle, escalate when the severity score crosses a line you chose from your own data.
That makes the Decisions API a candidate for a specific layer of the agent stack. The orchestrator holds the state. A capable model does the planning and the generation. A decision layer answers narrow questions about routing, risk, priority, and completion. A policy layer holds the permissions. The action layer executes and the audit log records everything. The decision layer is the part that should be fast, cheap, and boring. It should never be the part that grants permission. A model's probability that a transaction is safe is one input to a policy check.
Seen that way the natural uses are the ones OpenAI listed and a few it did not. Routing support requests to queues. Gating a tool call as allow, confirm, or block. Choosing between a fast path, a deep path, retrieval, and a human. Picking an agent's next action from an allowlist. Deciding whether a generated answer is complete enough to return. Checking an uploaded image against a content rule before a more expensive step runs. All of these are decisions where you can enumerate the answers in advance, and that is the test for whether the endpoint applies. If you cannot write the list, you want generation.
What We Saw, and What Other Testers Found
Our own use is the routing layer of a production multi-agent system: a supervising agent that has to decide which specialized agent takes the user's turn, with context that spans the whole conversation. That step was a general-model prompt with a parsed answer, and it was the most retried and most logged call in the pipeline. Moving the classification onto the Decisions API gave a clear performance improvement on that step, with the routing answer coming back faster and the parse-and-retry path gone. What took the time was the labeled set of real routing cases we used to set the thresholds, and that is the part we would not skip again.
The developer forum thread under the beta announcement is more useful than most launch coverage, because other people measured other things, and their findings point at the same places we found needed care.
The sharpest finding came from a developer who ran a calibration check. They set up a biased coin, seventy percent heads, and asked the model about it in both formats. As a predicate, the returned probabilities tracked the expected rate. As a choice between heads and tails, the model picked heads ninety-eight percent of the time. Then they reordered the options and the probabilities moved. Their advice to other developers was to stay away from choice questions for now and to lean on predicates when the probability itself matters. OpenAI's documentation says nothing about calibration at all. It tells you to set thresholds from labeled data, which is correct advice, and which is also an admission that the numbers are estimates you have to check.
The second finding is competitive. Jev, a startup that only builds decision models, has been serving this exact shape of request for a while, including through OpenRouter. A developer who ran the same hard judgment calls through both reported that Jev was more accurate, faster, and cheaper, and that gpt-6-luna produced about three times as many confident wrong answers. Every, which had preview access, published an informal comparison in which the Decisions API chose the correct interface control in 76 of 78 computer-use steps against Jev's 73, while on conversation classification the two tied on accuracy and Jev answered in 161 milliseconds against 309. Small samples, task-specific, and not a ranking you should generalize. The point they make together is that there is now more than one serious supplier for this layer, and that the right one depends on your task, which you can only learn by running your own set through both.
The third finding is about money. There is no input caching on the Decisions API yet, and an OpenAI staff member confirmed in the thread that it is not available for now. On the Responses API, the long instruction prefix of a classifier is served from cache at a fraction of the input price after the first call. On Decisions the whole prompt is billed at the full input rate every time. For a high-volume classifier with a long rubric, the developer who raised it concluded that moving over from the Responses API does not pay yet. The headline price is attractive. The per-decision price depends on how much context you send, and for rubric-heavy questions it can be higher than what you are paying today.
Image inputs were measured at around 0.8 seconds on a slow connection, which is a payload cost more than a model cost, since the image has to travel as base64 in the request body. And several people asked when the endpoint reaches Azure and AWS. Nobody from OpenAI answered.
What To Do Before It Goes in a Production Loop
The endpoint is worth adopting for the shape of the problem it solves. Our own rollout and the beta findings tell you what the engineering around it has to look like.
First, build the labeled set before you build the integration. A few hundred real inputs with the answer a person would give, drawn from your own traffic, is the only way to set the thresholds OpenAI tells you to set and the only way to find out whether the probabilities mean anything for your question. If you do not have the set, you are shipping a confidence number you cannot interpret.
Second, prefer predicates when the number matters. Decompose a choice into independent predicates where the categories allow it, and keep choice questions for cases where you only act on the top pick and never on the probability. If you must use a choice, test it with the options in a different order and see whether your routing changes. If it does, you have found out something important before your users did.
Third, always include the fallback option and always validate the answer against your own allowlist in code, even though the API promises to stay inside it. Treat a timeout as uncertainty, not as a no. Log the raw response with the question name, the version of the instructions, and the model, because when a decision is wrong three months from now you will want to know which rubric produced it.
Fourth, do the cost math with your real prompt. Count the tokens in your rubric and your typical input, multiply by your call volume, and compare against the same classifier on the Responses API with caching. The answer will differ by use case, and the cheap-sounding headline will be wrong for some of them until caching ships.
Fifth, keep permission out of the decision layer. A probability that an action is safe should feed a policy engine that owns the final allow or block. The model estimates. The policy decides.
Sixth, run a second supplier through the same set. Jev exists, and so does the obvious fallback of a small model with constrained output. A decision layer is the easiest part of an agent to make swappable, and the week-one results say the ranking between suppliers is task-dependent.
None of this is specific to OpenAI. It is what owning a classifier in production has always required. What the Decisions API changes is that the classifier is now a cheap, fast, first-class primitive, which removes the excuse for building the step badly and removes none of the obligation to measure it.
Working with Vindler
Vindler designs and runs production agent systems, and the routing, gating, and evaluation steps are where most of our hardening work goes. We have already moved the routing classification of a production multi-agent system onto the Decisions API, labeled set and thresholds included. We have written before about why agent dashboards mislead and about evaluating agents at scale, and the discipline is the same here: a decision you cannot measure is a decision you cannot trust.
If you are deciding whether to move your classifiers and routers onto a decision endpoint, or you have an agent in production whose routing step nobody has measured, book a call. For more on how we build and run agent infrastructure, see our case studies or contact us directly.
Sources
OpenAI's Decisions API guide, which is the source for the endpoint, question types, examples, pricing, and compliance notes above. The public beta announcement and discussion thread on the OpenAI developer forum, October 6 and 7, 2026, which is the source for the calibration test, the Jev comparison, and the caching exchange. The OpenAI Developers announcement on X from DevDay. AlphaSignal's coverage of the beta, including Every's informal comparison and the latency figures from the launch demo. Pricing for gpt-6-luna on the Responses API is from OpenAI's published model pricing.
Published October 15, 2026.




