OpenAI Decisions API Public Beta: Faster, Structured Classification for Text and Images
TL‑R; OpenAI Decisions API is now publicly available in beta and lets
- What: A new
/v1/decisionsendpoint that returns typed "decision" answers (probability for predicate ‑ yes‑no - **Why **
- 10‑× 10‑fold ") -
What is the Decisions API?
The Decisions API is a specialised decision‑making service built on top of the gpt‑6‑luna model. It accepts a single request containing:
| Field | Purpose |
|---|---|
model |
Currently only gpt‑6‑luna is supported. |
input |
Text, user‑messages, or base‑64‑encoded images that provide the evidence for the decision. |
questions |
One or more question objects that describe the type of decision you need (predicate, choice, or score). |
The response is an answers array where each answer mirrors the name you gave the question, making it trivial to map results back to your application logic.
When to use Decisions vs Responses API
| Use‑case | Recommended API |
|---|---|
| Binary‑yes/no classification, e.g., “Is there visible damage?” | Decisions API – returns a single probability (0‑1) and is ~10× faster. |
| Choose a category from a fixed list, e.g., routing a support ticket. | Decisions API – returns the chosen value, per‑option probabilities, and a confidence score. |
| Score an item against an ordered rubric (severity, risk, etc.). | Decisions API – returns a probability‑weighted numeric score plus distribution. |
| Need a complex JSON object, free‑form explanation, or function‑calling. | Responses API (structured outputs or function calls). |
In short, use Decisions when you only need a typed answer (predicate/choice/score) and care about latency and cost.
Question types and their outputs
| Type | Typical scenario | Main fields in the answer |
|---|---|---|
predicate |
Yes/No checks – damage detection, compliance, sentiment. | probability (0‑1) |
choice |
Categorical routing – department, product type, language. | choice (selected value), probabilities (array), confidence |
score |
Ordered rating – severity, priority, quality grade. | score (float), probabilities (per‑level), confidence |
Predicate returns a single probability. Choice returns the selected value plus a full probability distribution and an overall confidence metric. Score returns a weighted average that can fall between discrete levels, useful for fuzzy ranking.
Quick‑start code snippets (Python, Node, Go, Java, Ruby)
All SDK examples require OpenAI SDK ≥ Python 3.26.0, JavaScript 7.30.0, Go 3.73.0, Ruby 0.101.0, Java 4.78.0.
Python (predicate – image damage detection)
import base64, pathlib
from openai import OpenAI
client = OpenAI()
img_b64 = base64.b64encode(pathlib.Path('product.png').read_bytes()).decode()
decision = client.decisions.create(
model='gpt-6-luna',
input=[{
'role': 'user',
'content': [
{'type': 'input_text', 'text': 'Inspect the product in this photo.'},
{'type': 'input_image', 'image_url': f'data:image/png;base64,{img_b64}'}
]
}],
questions=[{
'type': 'predicate',
'name': 'visible_damage',
'instructions': 'Does the product have visible damage (crack, tear, dent)?'
}]
)
print(decision.answers[0].probability)
Node (choice – ticket routing)
import OpenAI from 'openai';
const client = new OpenAI();
const decision = await client.decisions.create({
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, refunds'},
{value: 'technical', description: 'Product usage problems'},
{value: 'shipping', description: 'Delivery & tracking'},
{value: 'other', description: 'Anything else'}
]
}]
});
const ans = decision.answers[0];
console.log(`${ans.choice} (confidence ${ans.confidence})`);
Go (score – issue severity)
import (
"context"
"encoding/base64"
"os"
"github.com/openai/openai-go/v3"
)
func main() {
img, _ := os.ReadFile("product.png")
client := openai.NewClient()
decision, _ := client.Decisions.New(context.Background(), openai.DecisionNewParams{
Model: "gpt-6-luna",
Input: openai.DecisionNewParamsInputUnion{OfString: openai.String("Export fails in Safari but works in Chrome.")},
Questions: []openai.DecisionNewParamsQuestionUnion{{
OfScore: &openai.DecisionNewParamsQuestionScore{
Name: openai.String("severity"),
Instructions: "How severe is this issue?",
Levels: []openai.DecisionNewParamsQuestionScoreLevel{{Label: "Cosmetic"}, {Label: "Workaround"}, {Label: "Blocked"}},
},
}},
})
fmt.Println(decision.Answers[0].AsAny().(openai.DecisionAnswerScore).Score)
}
(Other language snippets are identical in structure; see the full documentation for Ruby and Java.)
Performance & cost
- Latency – Public‑beta measurements show median 160‑175 ms end‑to‑end, 95th‑percentile ~285 ms, with a worst‑case of ~743 ms (see comment by @agentdev001). This is roughly 10× faster than the generic Responses API for comparable workloads.
- Pricing – Only input tokens are billed at $0.10 per 1 M tokens for
gpt‑6‑luna. There are no output‑token charges because the API returns only structured decision fields. - Data controls – Supports Zero Data Retention (ZDR) and HIPAA‑eligible usage. Regional processing is available in the US and EEA + Switzerland.
Community insights from Hacker News
| Commenter | Key take‑away |
|---|---|
| @simonw | Shared a ready‑to‑use llm-openai-decisions plugin and highlighted that the endpoint may become a de‑facto standard for other providers. |
| @agentdev001 | Reported real‑world latency (160‑175 ms median) and confirmed the 1 M‑token window with multimodal image support. |
| @TSiege | Argues that cheap binary‑yes/no scores could commodify the AI market, pushing providers into price wars. |
| @AM1010101 | Noted the lack of caching, which could affect bulk processing where a long system prompt would otherwise be reused. |
| @armcat | Ran statistical experiments: predicate probabilities are well‑calibrated, but choice probabilities can be biased by option order. |
| @solatic | Points out the pricing gap versus Jev (OpenAI $0.10 vs Jev $0.042 per 1 M input tokens). |
| @mritchie712 | Emphasised the ability to accept image inputs—a feature missing from many competing classifiers. |
| @bob1029 | Warns that exposing raw probabilities may erode user confidence if the numbers are mis‑interpreted. |
| @Sunny_Fung | Frames Decisions as the “cerebellum” for LLM‑powered agents, handling fast, deterministic routing. |
Overall sentiment: developers are excited about the speed and multimodal capability, but there are concerns about calibration, pricing, and the long‑term strategic positioning of a dedicated decision model.
Best‑practice checklist
- Pick the right question type – Use
predicatefor binary checks,choicefor unordered categories,scorefor ordered rubrics. - Name each question uniquely – The
namefield is echoed in the answer and is your primary key for downstream logic. - Provide clear instructions & distinct choices – Ambiguous wording leads to low confidence scores.
- Set thresholds based on calibrated data – Validate that a reported 0.9 probability corresponds to ~90 % real‑world accuracy for your domain.
- Include a fallback option – For
choicequestions, add an “other” value to capture out‑of‑scope inputs. - Consider ZDR & regional processing – Enable these flags if you handle PHI, GDPR‑sensitive data, or need data residency guarantees.
- Monitor latency & cost – Use the
usageblock in the response to track token consumption; combine with OpenAI’s cost‑analysis tools.
Future outlook
OpenAI plans to move the Decisions API to GA in the coming weeks, likely expanding the model catalog beyond gpt‑6‑luna. The community expects tighter integration with the Live API for voice‑driven decisions and possible inclusion of the endpoint in the broader Responses family once the model matures.
Bottom line – The Decisions API gives developers a fast, cost‑effective way to obtain structured, typed classifications from text and images, positioning it as a practical alternative to building custom classifiers or over‑engineering prompts with the generic Responses API.
Sources
Related
- Dispatch
- Dispatch
- Dispatch
- Dispatch
- Dispatch