Hacker News — AI on Front Page · · 8 min read

Decisions API is in public beta

Mirrored from Hacker News — AI on Front Page for archival readability. Support the source by reading on the original site.

260 pts · 119 comments on Hacker News

The Decisions API evaluates text, images, or both and returns typed answers about 10x faster than the Responses API. Get the probability that a condition is true, a choice from a fixed set, or a score against a rubric. Use those answers to classify content, route requests, and prioritize work in your application.

Try the Decisions API in the Playground to experiment with questions and inputs before writing code.

The Decisions API is in public beta, and we expect to GA in the coming weeks. gpt-6-luna is the only model currently available. Use the dedicated POST /v1/decisions endpoint.

To run the SDK examples below, use these OpenAI SDK versions or later: Python 3.26.0, JavaScript 7.30.0, Go 3.73.0, Ruby 0.101.0, and Java 4.78.0. See OpenAI SDK for installation instructions.

How decisions work

A request has three parts:

Field Purpose
model The model that evaluates the request. Currently, only gpt-6-luna is supported.
input Shared evidence for the questions: a text string or user messages containing text and images.
questions What to evaluate, including each question’s type, instructions, and any allowed choices or score levels.

The response contains an answers array. Give each question a unique name to identify its answer; the API echoes that name in the response.

Choose a question type

Type Use it to Main result
predicate Check a condition, such as visible damage or passage relevance. probability: an estimate from 0 to 1 that the condition is true.
choice Select one option, such as a department or content category. choice: one of your supplied values.
score Rate an input against ordered levels, such as issue severity. score: the probability-weighted average of the level indices.

Both choice and score return probabilities over discrete options. Use choice for categories without an order, such as departments. Use score for ordered levels, such as severity; it takes the probability-weighted average of their numeric indices to produce a score that can fall between levels.

Use Decisions when your application needs one of these answer types. Use Structured Outputs with the Responses API when you need to generate an object that follows your own JSON schema, such as extracted fields or a written explanation, or function calling when you need a model to request a tool call with arguments.

Check an image for visible damage

Use a predicate question to check a product photo for visible damage. This request combines the image with instructions to look for a crack, tear, or dent.

Does this item have a dent?

A smooth sage-green travel cup
A blue camping mug with a pronounced dent
probability
Please cancel my subscription before the next renewal.
Can I switch to annual billing and keep my current plan?
I don’t need this anymore. How do I stop future charges?
probability
Question

Can I return an item after 30 days?

Answer
Returns are accepted within 30 days of delivery. After that, items aren’t eligible for a refund.
Start a return from the Orders page in your account.
Standard shipping takes three to five business days.
probability
Check an image for visible damage
curl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22IMAGE_BASE64="$(base64 < product.png | tr -d '\r\n')"

curl https://api.openai.com/v1/decisions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<JSON
{
  "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,$IMAGE_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."
  }]
}
JSON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35import { readFile } from "node:fs/promises";
import OpenAI from "openai";

const client = new OpenAI();
const imageBase64 = (await readFile("product.png")).toString("base64");
const decision = await 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: `data:image/png;base64,${imageBase64}`,
        },
      ],
    },
  ],
  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.",
    },
  ],
});

const answer = decision.answers[0];
if (answer.type === "refusal") {
  console.log(`Refused: ${answer.name}`);
} else if (answer.type === "predicate") {
  console.log(`Visible damage probability: ${answer.probability}`);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39import base64
from pathlib import Path

from openai import OpenAI

client = OpenAI()
image_base64 = base64.b64encode(Path("product.png").read_bytes()).decode("ascii")

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,{image_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."
            ),
        }
    ],
)

answer = decision.answers[0]
if answer.type == "refusal":
    print(f"Refused: {answer.name}")
elif answer.type == "predicate":
    print(f"Visible damage probability: {answer.probability}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50package main

import (
	"context"
	"encoding/base64"
	"fmt"
	"os"

	"github.com/openai/openai-go/v3"
)

func main() {
	image, err := os.ReadFile("product.png")
	if err != nil {
		panic(err)
	}
	client := openai.NewClient()
	decision, err := client.Decisions.New(context.Background(), openai.DecisionNewParams{
		Model: "gpt-6-luna",
		Input: openai.DecisionNewParamsInputUnion{
			OfDecisionInputMessageArray: []openai.DecisionInputMessageParam{{
				Content: openai.DecisionInputMessageContentUnionParam{
					OfParts: []openai.DecisionInputPartUnionParam{
						{OfInputText: &openai.DecisionInputTextParam{Text: "Inspect the product in this photo."}},
						{OfInputImage: &openai.DecisionInputImageParam{
							ImageURL: "data:image/png;base64," + base64.StdEncoding.EncodeToString(image),
						}},
					},
				},
			}},
		},
		Questions: []openai.DecisionNewParamsQuestionUnion{{
			OfPredicate: &openai.DecisionNewParamsQuestionPredicate{
				Name:         openai.String("visible_damage"),
				Instructions: "Does the product have visible damage, such as a crack, tear, or dent? Ignore shadows and damage to the packaging.",
			},
		}},
	})
	if err != nil {
		panic(err)
	}
	switch answer := decision.Answers[0].AsAny().(type) {
	case openai.DecisionAnswerPredicate:
		fmt.Println(answer.Probability)
	case openai.DecisionAnswerRefusal:
		fmt.Printf("Decision refused for %s\n", answer.Name)
	default:
		panic("unexpected answer type")
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47import com.openai.models.decisions.DecisionCreateParams;
import com.openai.models.decisions.DecisionInputImage;
import com.openai.models.decisions.DecisionInputMessage;
import com.openai.models.decisions.DecisionInputPart;
import com.openai.models.decisions.DecisionInputText;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.List;

String imageBase64 =
    Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of("product.png")));
var message =
    DecisionInputMessage.builder()
        .contentOfParts(
            List.of(
                DecisionInputPart.ofInputText(
                    DecisionInputText.builder()
                        .text("Inspect the product in this photo.")
                        .build()),
                DecisionInputPart.ofInputImage(
                    DecisionInputImage.builder()
                        .imageUrl("data:image/png;base64," + imageBase64)
                        .build())))
        .build();
var decision =
    client
        .decisions()
        .create(
            DecisionCreateParams.builder()
                .model("gpt-6-luna")
                .inputOfDecisionInputMessages(List.of(message))
                .addQuestion(
                    DecisionCreateParams.Question.Predicate.builder()
                        .name("visible_damage")
                        .instructions(
                            "Does the product have visible damage, such as a crack, tear, or"
                                + " dent? Ignore shadows and damage to the packaging.")
                        .build())
                .build());

var answer = decision.answers().get(0);
if (answer.isRefusal()) {
  System.out.println("Refused: " + answer.asRefusal().name().orElse("visible_damage"));
} else {
  System.out.println(answer.asPredicate().probability());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41require "base64"
require "openai"

image_base64 = Base64.strict_encode64(File.binread("product.png"))
client = OpenAI::Client.new

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: "data:image/png;base64,#{image_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."
    }
  ]
)

answer = decision.answers.fetch(0)
case answer
when OpenAI::Models::Decision::Answer::Predicate
  puts(answer.probability)
when OpenAI::Models::Decision::Answer::Refusal
  warn("Decision refused for #{answer.name}")
else
  raise("Unexpected answer type: #{answer.type}")
end

An illustrative response excerpt:

123456789{
  "answers": [
    {
      "type": "predicate",
      "name": "visible_damage",
      "probability": 0.92
    }
  ]
}

The probability is the model’s estimate that the condition is true. Use it to flag photos for review based on a threshold you choose.

Images must be inline base64 data URLs. Hosted HTTP or HTTPS image URLs and file_id inputs aren’t supported by this endpoint. Combine input_text and input_image parts in a user message to evaluate images together with instructions or other context.

Select from fixed options

A choice question selects one value from the options you provide. Use distinct values and descriptions that explain when each option applies.

Which lane should the car choose?

Lane 10.03
Lane 20.94
Lane 30.03
I was charged twice for this month. Can you refund the extra payment?
Every CSV export fails with an error, even after I refresh the page.
I lost my phone and can’t get past two-step verification.
Billing1.00
Technical support0.00
Account access0.00
NORTHLINE STUDIO № 1042

Invoice

Billed to Cedar & Co.

Design services$1,200.00
Amount due$1,200.00

Payment due October 21

Discussion (0)

Sign in to join the discussion. Free account, 30 seconds — email code or GitHub.

Sign in →

No comments yet. Sign in and be the first to say something.

More from Hacker News — AI on Front Page