# OpenAI Decisions APIとは？限定プレビュー中にLunaで同じ判定を作る

> OpenAI Decisions APIは2026年10月6日時点で限定プレビューで、通常のキーでは403が返ります。GPT-6 Lunaで同じ判定を今作る方法と費用を解説します。

- Source: https://www.aifreeapi.com/ja/posts/openai-decisions-api
- Language: ja
- Published: 2026-10-06
- Updated: 2026-10-06
- Publisher: AI Free API (https://www.aifreeapi.com)

OpenAIのDecisions APIは、文章や画像を渡すと、開発者が事前に定義した有限の選択肢から答えを1つ返す判定専用のAPIです。問い合わせの振り分け、コンテンツの分類、エージェントの次の行動選択に使う想定で、中身はGPT-6 Lunaです。ただし**2026年10月6日時点では限定プレビュー**で、使えるのはOpenAIが選んだ一部のAPI顧客だけです。開発者ドキュメントにはリクエスト形式も料金もレート制限も載っていません。

自分のキーで呼んで403が返るなら、それはコードの誤りではなく、アカウントで機能が有効になっていないという意味です。いま実装が必要なら、一般提供中の`gpt-6-luna`とStructured Outputsの列挙型（enum）スキーマで、同じ「選択肢から1つ選ぶ」処理を作れます。1回を入力400・出力15トークンと仮定すると、Standard料金で100万回あたり$47.50です。速度の要件が数百ミリ秒以下でなければ、待つ理由はあまりありません。

## Decisions APIでできること：有限の選択肢から1つ選ぶ判定

OpenAIはDevDay 2026（2026年9月29日）でDecisions APIを発表しました。[OpenAI Developer Communityの告知](https://community.openai.com/t/devday-2026-announcements-and-developer-resources/1402006)では、Lunaの能力を「ユーザーが定義した質問と、事前に決めた有限の回答」に集中させてリアルタイムの判断を行うもので、入力の分類、リクエストの振り分け、事前に定義した回答からの行動選択に使うと説明されています。

入力として渡せるのはテキストと画像です。たとえば問い合わせ本文と添付のスクリーンショットを渡し、「どのチームが担当するか」という質問と「請求・配送・技術・その他」という回答候補を指定すると、候補のどれかが返ってくる、という使い方です。具体的な用途は次のようなものです。

- 問い合わせの振り分け：請求、配送、技術サポートなど、どのキューに入れるか
- コンテンツ分類・モデレーション：投稿や画像を「公開可・要確認・削除」などに分ける
- エージェントの次の行動：注文を調べる、確認の質問をする、返信する、人に引き継ぐ、のどれを選ぶか

どれも文章を生成する必要はなく、決まった選択肢から1つ選べば足りる処理です。汎用モデルでもこなせますが、OpenAIはこの種の判定を専用の窓口に切り出し、速く返すことを狙っています。

## Decisions APIの公開情報と未公開情報（2026年10月6日時点）

実装の判断に関わる項目を、公開済みかどうかで分けると次のとおりです。

| 項目 | 2026年10月6日時点の状況 |
| --- | --- |
| 提供状態 | 限定プレビュー。プレビューは選ばれたAPI顧客のテスト用 |
| 入力 | テキストと画像 |
| 出力 | 開発者が定義した回答候補からの選択 |
| 土台のモデル | GPT-6 Luna |
| リクエスト・レスポンスの形式 | 未公開（APIリファレンスなし） |
| 料金と課金単位 | 未公開（料金表に記載なし） |
| レート制限、1回あたりの質問数・選択肢数の上限 | 未公開 |
| 信頼度スコアの有無 | 情報が食い違っており不明 |
| 一般公開の日付 | 未定 |

[開発者ドキュメント](https://developers.openai.com/api/docs/changelog)の変更履歴や[料金ページ](https://developers.openai.com/api/docs/pricing)にも、2026年10月6日時点でDecisions APIの項目はありません。DevDayの紹介文には「数日内に広く公開予定」とありましたが、その後1週間たっても一般公開は始まっていません。公式のスキーマがない以上、「Decisions APIのリクエスト例」とされるJSONはどれも推測です。

速度については、OpenAIのThibault Sottiaux氏がXで「エンドツーエンドで数百ミリ秒未満の判断ができるよう調整した」と投稿しています（[eeselの解説](https://www.eesel.ai/blog/openai-decisions-api)が引用）。よく見かける「約150ms」「Lunaの約10倍速い」という数字は、報道やSNS、基調講演のスライドを紹介した記事に出てくるもので、OpenAIのドキュメントにはありません。どちらも測定条件が示されていない公称値です。

信頼度スコアについては、The New Stackは「返る」と報じていますが、[Firecrawl](https://www.firecrawl.dev/blog/openai-decisions-api-vs-jev)やeeselはOpenAIのページや投稿にその記述を見つけていません。ドキュメントが出るまでは、信頼度の値でしきい値を設計しないほうが安全です。

## APIキーで使える？403「Decision API is not enabled」の意味

プレビューに選ばれていない通常のキーでは使えません。eeselは2026年10月1日と2日に、通常のAPIキーで`POST https://api.openai.com/v1/decisions`を呼び、どちらの日もHTTP 403と次のエラーを受け取ったと報告しています。

```json
{
  "error": {
    "message": "Decision API is not enabled for this user.",
    "type": "invalid_request_error",
    "param": null,
    "code": null
  }
}
```

![通常のAPIキーでPOST /v1/decisionsは403、/v1/decisions/createは404、gpt-6-lunaとenumスキーマは今使えることを3行で示した図](https://www.aifreeapi.com/posts/ja/openai-decisions-api/img/decisions-403-404.webp)

同じ報告では、`/v1/decisions/create`のような近くのパスは404でした。存在しないパスなら404、存在するが自分には開放されていない機能なら403という区別になり、403は機能の利用許可がないことを示すと読めます。空のリクエストでも403になるため、エラー内容からリクエスト形式を推測することもできません。

このエラーが返ったときの対応は単純です。

- リトライやパラメータの調整では解決しません。リクエストを直しても403のままです。
- 公開の申し込み手順は、2026年10月6日時点で開発者ドキュメントに載っていません。
- 日本は[OpenAI APIの対応国](https://developers.openai.com/api/docs/supported-countries)に含まれているので、日本のアカウントでGPT-6 Lunaを使うこと自体は問題ありません。ただし対応国の一覧は、Decisions APIのプレビュー対象かどうかとは関係しません。

エンドポイントのパスやエラーメッセージは一般公開のときに変わる可能性があります。上のパスとメッセージは、あくまで2026年10月初旬の第三者の観測です。

## 待つか今つくるか：速度の要件で決める

Structured Outputsを使えば、出力を選択肢の中の値に限定することは今でもできます。Decisions APIで新しく得られるのは、OpenAIが公称する速度と、Lunaを判定に「集中」させたことによる精度の上積みがあるかどうか、の2点です。後者はまだ誰も検証できていません。そこで、判断の分かれ目はほぼ速度になります。

参考になる公開データとして、eeselはLunaとStructured Outputsで問い合わせ20件を振り分けるテストを公開しています（ノートPCからのエンドツーエンド計測、計160回の呼び出し）。`reasoning.effort`を`none`にした場合の中央値は1.46秒、`medium`では2.33秒でした。1社による小さなサンプルですが、「今の代替手段で1〜2秒程度」という目安にはなります。

| 状況 | 判断 |
| --- | --- |
| メールやチケットの振り分け、投稿の事後分類など、1〜2秒かかっても誰も気づかない | 今Lunaで作る。待つ利益は小さい |
| 過去データの一括ラベル付けなど、即時の応答が要らない | 今LunaのBatchで作る（料金は半額、ただし非同期） |
| 画像（スクリーンショット、商品写真）を判定に使う | 今Lunaで作る。Lunaは画像入力に対応済み |
| ライブチャットで、ボットが担当を決めるまでの待ち時間が体験を左右する | Lunaで作りつつ、Decisions APIの公開を待って比較する |
| エージェントが1つのタスクで何十回も小さな判断をし、合計待ち時間が問題になる | 同上。速度の公称値が実際に出るかが選択を左右する |
| 判定の確率値を使って「自信がないときは動かない」を制御したい | 確率値を返すと公式に書かれた手段はまだない。後述の「判断できない」選択肢で代用する |

TypeSafe社のJevのように、確率値を返す判定専用モデルは他社にもあります。ただ、OpenAIのAPIだけで完結させたい場合や画像を扱う場合は、Lunaで組むのが現実的です。

## GPT-6 LunaとStructured Outputsで同じ判定を実装する

[GPT-6 Luna](https://developers.openai.com/api/docs/models/gpt-6-luna)は、OpenAIが「集中した大量処理向けの最も効率的なモデル」と位置づけるモデルで、テキストと画像の入力、Structured Outputs、Responses API・Chat Completions・Batchに対応しています。`reasoning.effort`は`none`から`max`まで選べます（既定は`medium`）。判定だけなら`none`から始め、精度が足りない質問だけ上げるのが順当です。

### スキーマ：選択肢を列挙型（enum）に入れ「判断できない」を必ず含める

[Structured Outputsのガイド](https://developers.openai.com/api/docs/guides/structured-outputs)に従い、`strict: true`のJSON Schemaで答えのフィールドを列挙型にします。こうすると、モデルはリストにない値を返せなくなります。ガイドの制約のうち、判定で関係するのは次の点です。

- オブジェクトには必ず`additionalProperties: false`を付け、フィールドは`required`にすべて入れる
- スキーマ全体の列挙値は合計1,000個まで（250個を超える場合は文字数の制限も加わる）

ここで注意したいのは、厳格なスキーマが保証するのは「答えがリストの中の値であること」までで、答えが正しいことではない点です。eeselのテストでは、振り分け先のキューは40回中40回正しかった一方、「この問い合わせに自動返信してよいか」という判断は推論なしで40回中33回でした。キューを間違えても数分の遅れで済みますが、誤った自動返信はそのまま顧客に届きます。

そのため、メッセージ送信、課金、データ変更につながる判定には、選択肢に「判断できない（unsure）」を加え、それが選ばれたら人の確認に回す経路を最初から作っておきます。信頼度スコアがない以上、「動かない」という選択肢を明示的に用意するのがいちばん確実な歯止めです。

![入力からdecide()とgpt-6-lunaを経て、選択肢の値ならアプリが処理を実行し、unsureや拒否、応答切れなら人の確認キューに回す流れを示した図](https://www.aifreeapi.com/posts/ja/openai-decisions-api/img/luna-decide-flow.webp)

### Pythonの実装例（Responses API）

下のコードは、公式ガイドに記載されたパラメータに沿って組んだ例です。本番に入れる前に、自分のデータで動作と精度を確かめてください。`OPENAI_API_KEY`は環境変数に設定されている前提です。

```python
import json
from dataclasses import dataclass, field

from openai import OpenAI

client = OpenAI()  # 環境変数 OPENAI_API_KEY を使う
UNSURE = "unsure"


@dataclass
class Decision:
    answer: str                      # options のいずれか、または UNSURE
    detail: dict = field(default_factory=dict)


def decide(context, question: str, options: list[str],
           model: str = "gpt-6-luna", effort: str = "none") -> Decision:
    """context は文字列、または Responses API の content 配列（画像入り）"""
    schema = {
        "type": "object",
        "properties": {
            "answer": {"type": "string", "enum": options + [UNSURE]},
        },
        "required": ["answer"],
        "additionalProperties": False,
    }
    response = client.responses.create(
        model=model,
        reasoning={"effort": effort},
        input=[
            {
                "role": "system",
                "content": f"{question}\n選択肢から1つだけ選ぶ。"
                           f"判断材料が足りなければ {UNSURE} を選ぶ。",
            },
            {"role": "user", "content": context},
        ],
        text={
            "format": {
                "type": "json_schema",
                "name": "decision",
                "strict": True,
                "schema": schema,
            }
        },
        max_output_tokens=50,
    )

    if response.status == "incomplete":
        return Decision(UNSURE, {"reason": "incomplete"})

    message = next((o for o in response.output if o.type == "message"), None)
    part = message.content[0] if message and message.content else None
    if part is None or part.type == "refusal":
        return Decision(UNSURE, {"reason": "refusal"})

    data = json.loads(part.text)
    return Decision(data["answer"], {"usage": response.usage})


result = decide(
    "注文 #4471 の代金が二重に引き落とされています。",
    "この問い合わせを担当するキューはどれか。",
    ["billing", "shipping", "technical", "other"],
)
print(result.answer)  # options のいずれか、または unsure
if result.answer == UNSURE:
    pass  # 人の確認キューへ回す
```

応答が途中で切れた場合（`incomplete`）と安全上の拒否（`refusal`）は、ガイドが例外処理として挙げているケースです。どちらも`unsure`に寄せておくと、呼び出し側は「選択肢のどれか」か「人に回す」かの2通りだけを扱えば済みます。

Chat Completionsを使う場合は、`text.format`の代わりに`response_format: {"type": "json_schema", ...}`で同じスキーマを渡します。

### 画像を含む入力

問い合わせにスクリーンショットが付いている場合は、`context`に文字列ではなく、テキストと画像を並べた配列を渡します。

```python
context = [
    {"type": "input_text", "text": "アプリが起動しません。画面を添付します。"},
    {"type": "input_image", "image_url": "https://example.com/screenshot.png"},
]
result = decide(context, "担当キューはどれか。",
                ["billing", "shipping", "technical", "other"])
```

画像は大きさに応じて入力トークンが増えるため、後述のコスト計算は画像の分だけ高くなります。

### 後でDecisions APIに差し替えやすくする境界

Decisions APIの形式は未公開なので、今から形式を合わせることはできません。できるのは、差し替える範囲を1か所に閉じ込めておくことです。

- アプリ側は`decide(context, question, options)`だけを呼び、`answer`だけを受け取る。プロンプトやスキーマを呼び出し元に書かない
- 質問と選択肢の一覧は設定ファイルなどにまとめ、コードの各所に散らさない
- 判定ごとに答え、所要時間、トークン数を記録する。切り替え時の比較材料になる
- 正解ラベル付きのサンプル（数十〜数百件）を用意しておく。Decisions APIが使えるようになったら、同じセットで両方を走らせて比べられる

こうしておけば、切り替えるときに書き換えるのは`decide()`の中身だけで済みます。

## 1,000回・100万回あたりのコスト：入力400・出力15トークンで$47.50

Decisions APIの料金は2026年10月6日時点で未公開で、トークン課金か、1回ごとか、質問ごとかもわかりません。いま計算できるのは、代わりに使うGPT-6 Lunaの費用です。Lunaの[Standard料金](https://developers.openai.com/api/docs/models/gpt-6-luna)は、100万トークンあたり入力$0.10、出力$0.50です。BatchとFlexはその50%です。

1回あたりの費用は次の式で出ます。

> 入力トークン数 × $0.10 ÷ 1,000,000 ＋ 出力トークン数 × $0.50 ÷ 1,000,000

入力400トークン（指示文と問い合わせ本文）、出力15トークン（`{"answer":"billing"}`程度）と仮定し、`reasoning.effort`を`none`にした場合の結果です。

| 条件 | 1回 | 1,000回 | 100万回 |
| --- | ---: | ---: | ---: |
| 入力400・出力15、Standard | $0.0000475 | $0.0475 | $47.50 |
| 入力400・出力15、Batch（非同期） | $0.00002375 | $0.02375 | $23.75 |
| 入力800・出力15、Standard | $0.0000875 | $0.0875 | $87.50 |

内訳は、入力400×$0.10÷100万＝$0.00004、出力15×$0.50÷100万＝$0.0000075、合計$0.0000475です。トークン数は仮定の値なので、自分の指示文と典型的な入力でトークン数を数え、式に入れ直してください。計算に影響する条件は次のとおりです。

- 画像を渡すと、その分の入力トークンが加わる
- `reasoning.effort`を上げると推論の分だけ費用が増える。eeselのテストでは、推論なしで1,000件あたり約$0.047、`medium`で約$0.089だった
- 指示文が長く毎回同じなら、キャッシュされた入力（100万トークンあたり$0.01）が適用される場合がある
- Batchは結果がすぐ返らないため、リアルタイムの振り分けには使えない

処理量の面では、Lunaの最下位のTier 1でも毎分500リクエストまで送れます。月100万回は平均すると毎分約23回なので、ピークが極端でなければ収まります。

GPT-6 Solで判定する場合との料金差は、[GPT-6 SolとLunaの料金比較：APIとCodexでどう違う？](/ja/posts/gpt-6-luna-vs-sol-price)で同じトークン量の計算をしています。

## Decisions APIへの切り替えを検討するシグナル

Lunaで作った判定をDecisions APIに移すかどうかは、次のどれかが起きた時点で見直します。

- developers.openai.comにDecisions APIのガイドかAPIリファレンスが公開された
- 料金ページにDecisions APIの行が載り、課金単位がわかった
- 自分のキーで呼んだときの403が解消した、または一般公開が告知された
- 信頼度や確率を返すフィールドがドキュメントに記載された。「自信がなければ動かない」をしきい値で制御できるようになる
- 自分のサービスで、判定待ちの時間がユーザー体験やエージェント全体の処理時間の問題になっている

切り替えるかどうかは、用意しておいた正解ラベル付きのサンプルで両方を比べてから決めます。比べるのは正解率、所要時間の中央値と遅い側の値、そして100万回あたりの費用です。Decisions APIが速くても、自分のデータで正解率が下がるなら、速度が必要な判定だけを移す選択もあります。

## Decisions APIの料金・公開時期・Jevとの違い

### OpenAI Decisions APIの料金はいくら？

2026年10月6日時点で未公開です。トークン単位で課金されるのかどうかもわかっていません。目安にできるのは土台のGPT-6 Lunaの料金（100万トークンあたり入力$0.10、出力$0.50）だけで、Decisions API自体の価格はこれと違う可能性があります。

### Decisions APIの一般公開はいつ？

日付は発表されていません。DevDayの紹介文には「数日内に広く公開予定」とありましたが、2026年10月6日時点ではまだ限定プレビューのままです。

### Decisions APIとJevの違いは？

TypeSafe社のJevは2026年9月15日に登場した判定専用モデルで、誰でも使え、テキストのみに対応し、選択肢ごとの確率を返します。Decisions APIは画像も扱えますが、限定プレビュー中で、確率や信頼度を返すかどうかは公式に示されていません。

### Decisions APIはChatGPTで使える？

DevDayの告知ではAPIの項目として発表されており、ChatGPTの画面から使う機能としては説明されていません。使うにはOpenAI APIのアカウントと、プレビューへの参加が必要です。
