# OpenAI Decisions API 怎么用：限量预览期先用 GPT-6 Luna 上线

> 截至 2026 年 10 月 6 日，OpenAI Decisions API 仍是限量预览，没有公开文档和价格。要上线有限选项判断，可先用 GPT-6 Luna 加严格枚举 schema 实现，开放后再替换。

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

**截至 2026 年 10 月 6 日**，OpenAI Decisions API 还用不上：它是 DevDay 2026（9 月 29 日）发布的限量预览接口，只对 OpenAI 选定的 API 客户开放，开发者文档里没有它的请求格式、模型 ID、价格和限额。第三方测试中，普通 API Key 调用会被 403 拦下。

如果你的产品现在就要做"从几个固定选项里选一个"的判断，比如工单分流、内容分类、审核，或者让 Agent 决定下一步调用哪个工具，可以先用已经正式开放的 GPT-6 Luna（`gpt-6-luna`）加严格枚举的结构化输出实现同样的功能。把判断封装成一个独立函数，Decisions API 开放后只替换函数内部。按每次 400 输入、15 输出 token 估算，Luna 方案每百万次判断约 **$47.50**；这是 Luna 的价格，不是 Decisions API 的价格。

## OpenAI Decisions API 是什么：在你给定的答案里选一个

OpenAI 在开发者社区的 [DevDay 2026 公告](https://community.openai.com/t/devday-2026-announcements-and-developer-resources/1402006)里这样描述它：让 Luna 的能力集中在开发者定义的一组问题上，每个问题只有有限的预设答案，用于实时决策；它用 Luna 对输入分类、对请求做路由，或从预设答案里选出下一个动作。状态写的是"限量预览"（In limited preview）。

按 OpenAI 发布会回顾和 OpenAI Developers 账号的说法（[eesel 转引](https://www.eesel.ai/blog/openai-decisions-api)），用法分三步：

1. 传入上下文：文本或图片，例如一张工单、一段对话记录、用户上传的截图或商品照片。
2. 定义问题和候选答案：每个问题允许返回哪些答案，由你事先列全。
3. 拿回一个选择：接口从你的列表里返回答案，你的代码据此执行分类、路由或下一个动作。

它和普通对话接口的区别在于输出不是一段文字，而是一个预设选项。OpenAI 强调的卖点是速度，下文单独讲。

两个同名对象别混：Decisions 也是一个与 OpenAI 无关的低代码平台（decisions.com），它文档里的 OpenAI Module 是该平台自己的集成模块；decisionapi.net 是第三方网站，不是 OpenAI 文档。

## 截至 2026 年 10 月 6 日：已公布和未公布的内容

能确定的只有用途、输入类型和状态。写代码需要的东西全部缺失：[developers.openai.com 的文档索引](https://developers.openai.com/llms.txt)、[API 更新日志](https://developers.openai.com/api/docs/changelog)和定价页里都没有 Decisions API 的条目。

| 项目 | 状态 | 依据 |
| --- | --- | --- |
| 用途：分类、路由、选择 Agent 下一步动作 | 已公布 | OpenAI 社区公告 |
| 输入：文本或图片 | 已公布 | 发布会回顾（转引） |
| 底层模型：Luna | 已公布 | OpenAI 社区公告 |
| 访问方式：仅限选定 API 客户 | 已公布 | OpenAI Developers（转引） |
| 全面开放时间 | 9 月 29 日说"未来几天"，截至 10 月 6 日未见开放 | 发布会回顾（转引） |
| 请求与响应格式、SDK 方法 | 未公布 | 文档中无此页面 |
| 价格与计费单位（按 token、按次还是按问题） | 未公布 | 定价页无此行 |
| 速率限额、每次最多几个问题或选项、图片大小上限 | 未公布 | 文档中无此页面 |
| 是否返回置信度 | 说法冲突，按未知处理 | 见下文 |
| 数据驻留、可用地区 | 未公布 | 文档中无此页面 |

在文档发布之前，任何 Decisions API 的请求体示例都只能是猜测，不要照着写生产代码。

## 调用 v1/decisions 返回 403 是什么意思

意思是你的账号不在预览名单里，而不是请求写错了。

第三方 eesel 在 [2026 年 10 月 1 日和 2 日的测试](https://www.eesel.ai/blog/openai-decisions-api)里，用普通 API Key 请求 `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
  }
}
```

同一测试里，`/v1/decisions/create`、`/v1/beta/decisions` 这类相近路径返回 404，而且请求体为空时也直接返回 403。测试者据此判断：这个路由真实存在，但前面有一道按账号开放的功能开关，报错不会透露任何请求格式信息。

据此可以得出三点：

- 改请求体、换 SDK 版本、换模型名都不会让 403 消失。
- OpenAI 没有公布申请预览的公开渠道，"选定客户"的标准也没有说明。
- 任何第三方 API 网关都拿不到这个接口。它是 OpenAI 自己按账号开放的端点，宣称"可以代调 Decisions API"的服务都要谨慎对待。

## 等 Decisions API 开放，还是现在用 GPT-6 Luna 上线

多数场景应该现在就上线 Luna 方案，把判断逻辑封装好，等 Decisions API 有文档、有价格后再做对比测试。真正值得等的，只有"每次判断必须在亚秒级完成"的场景。

| 你的情况 | 建议 | 理由 |
| --- | --- | --- |
| 邮件、工单、内容审核等异步队列 | 现在用 Luna 上线 | 1 秒多和几百毫秒的差别，用户感知不到 |
| 离线重新打标、历史数据回填 | 现在用 Luna 的 Batch 处理 | 价格是 Standard 的一半，不需要实时返回 |
| 在线客服、实时聊天里的路由 | 先用 Luna 上线，开放后优先对比延迟 | 每轮多等 1 秒以上，用户能感觉到 |
| Agent 一个任务里要做很多次小判断 | 先用 Luna，同时控制判断次数；开放后第一时间测试 | 延迟会逐次累加 |
| 输入大量是截图、照片 | 留在 OpenAI 体系内 | Luna 和 Decisions API 都支持图片输入 |
| 判断错误会直接发消息、扣款、改数据 | 不管用哪个接口，都要先加兜底路径 | 两者都只保证答案在列表里，不保证答对 |

"等"的成本是功能推迟上线，而且开放日期、价格都没有公布；"先上"的成本是开放后可能要改一次调用层。只要按下文把判断封装成独立函数，改一次调用层的成本很小。

## 用 GPT-6 Luna 和严格枚举 schema 实现有限选项判断

[GPT-6 Luna](https://developers.openai.com/api/docs/models/gpt-6-luna) 支持文本和图片输入，也支持结构化输出（Structured Outputs），`reasoning.effort` 可以设为 `none`，Responses、Chat Completions 和 Batch 三个端点都能调用。按 OpenAI 的[结构化输出指南](https://developers.openai.com/api/docs/guides/structured-outputs)，把输出约束成一个只有 `enum` 字段的 JSON Schema，并打开 `strict`，模型返回的答案就只能是你列出的选项之一。

### 第一步：选项里留一个"交给人工"

结构化输出指南明确说了两件事：模型会尽量遵守 schema，当输入和问题完全无关时，这种"必须选一个"的约束可能导致胡乱作答；结构化输出仍然可能出错。所以候选答案里要有一个出口，例如 `needs_human`（信息不足、无法判断或与问题无关），提示词里写清什么情况选它。

### 第二步：用 Responses API 调用（官方直连）

下面的 Python 示例需要 `openai` SDK 和环境变量 `OPENAI_API_KEY`。`decide()` 接收上下文文本、可选的图片地址、问题和选项列表，返回一个保证在列表内的答案：

```python
import json
import time
from openai import OpenAI

client = OpenAI()  # 读取环境变量 OPENAI_API_KEY

def decide(context: str, question: str, options: list[str],
           fallback: str = "needs_human", image_url: str | None = None) -> dict:
    """在 options 中选一个答案；任何异常情况都返回 fallback。"""
    if fallback not in options:
        options = options + [fallback]

    content = [{"type": "input_text", "text": context}]
    if image_url:  # 公网 URL 或 data:image/png;base64,... 均可
        content.append({"type": "input_image", "image_url": image_url})

    start = time.perf_counter()
    resp = client.responses.create(
        model="gpt-6-luna",
        reasoning={"effort": "none"},
        input=[
            {"role": "developer",
             "content": f"{question}\n只能从给定选项中选一个。"
                        f"信息不足、无法判断或输入与问题无关时，选 {fallback}。"},
            {"role": "user", "content": content},
        ],
        text={"format": {
            "type": "json_schema",
            "name": "decision",
            "strict": True,
            "schema": {
                "type": "object",
                "properties": {"answer": {"type": "string", "enum": options}},
                "required": ["answer"],
                "additionalProperties": False,
            },
        }},
    )
    latency_ms = round((time.perf_counter() - start) * 1000)

    answer = fallback
    if resp.status == "completed" and resp.output_text:  # 拒答或输出被截断时 output_text 为空
        try:
            parsed = json.loads(resp.output_text).get("answer")
        except json.JSONDecodeError:
            parsed = None
        if parsed in options:
            answer = parsed

    return {
        "answer": answer,
        "model": resp.model,
        "latency_ms": latency_ms,
        "input_tokens": resp.usage.input_tokens,
        "output_tokens": resp.usage.output_tokens,
    }

ROUTES = ["billing", "shipping", "technical", "other", "needs_human"]
print(decide("我的订单 #4471 被扣了两次钱", "这张工单应该分到哪个队列？", ROUTES))
```

成功的判断标准：返回的 `answer` 是 `ROUTES` 里的一个值；`input_tokens`、`output_tokens` 有数，下一节算成本要用。

一次要回答好几个问题（比如"分到哪个队列"和"能不能自动回复"）时，在 schema 里放多个枚举字段即可，每个字段都要列进 `required`。结构化输出指南规定，一个 schema 里所有枚举值加起来不超过 1,000 个。

### 第三步：经 OpenAI 兼容网关时改用 Chat Completions

如果你通过 OpenAI 兼容网关调用（下文讲国内路线），一般走 Chat Completions 接口（`/v1/chat/completions`）。结构化输出在 Chat Completions 里写在 `response_format` 中，其余逻辑不变：

```python
import json, os
from openai import OpenAI

client = OpenAI(base_url="https://api.laozhang.ai/v1",
                api_key=os.environ["LAOZHANG_API_KEY"])

options = ["billing", "shipping", "technical", "other", "needs_human"]
resp = client.chat.completions.create(
    model="gpt-6-luna",
    reasoning_effort="none",
    messages=[
        {"role": "developer",
         "content": "这张工单应该分到哪个队列？只能从给定选项中选一个；无法判断时选 needs_human。"},
        {"role": "user", "content": [
            {"type": "text", "text": "快递显示已签收，但我没收到"},
            # 有截图时追加：{"type": "image_url", "image_url": {"url": "https://..."}}
        ]},
    ],
    response_format={"type": "json_schema", "json_schema": {
        "name": "decision",
        "strict": True,
        "schema": {
            "type": "object",
            "properties": {"answer": {"type": "string", "enum": options}},
            "required": ["answer"],
            "additionalProperties": False,
        },
    }},
)

choice = resp.choices[0]
answer = "needs_human"
if choice.finish_reason == "stop" and not choice.message.refusal:
    try:
        parsed = json.loads(choice.message.content).get("answer")
        answer = parsed if parsed in options else "needs_human"
    except (TypeError, json.JSONDecodeError):
        pass  # 返回的不是合法 JSON，说明 json_schema 可能没有生效
print(answer, resp.usage)
```

两段代码都在本地再校验一次答案是否在列表里。原因很简单：官方直连时，严格 schema 已经保证这一点；经第三方网关时，这一层校验能兜住 `response_format` 没被透传的情况。

### 第四步：把 decide() 当成以后可替换的接口

让业务代码只依赖 `decide(context, question, options)` 和它返回的 `answer`，不直接接触 `gpt-6-luna`、`text.format` 这些实现细节。问题文本和选项列表放在配置里集中管理，每次调用把输入版本、答案、模型、延迟和 token 数写进日志。

Decisions API 开放后，你只需要按它的正式文档另写一个 `decide()` 的实现，用同一批已标注的样本跑两遍，再决定切不切。它的请求格式现在没人知道，所以不要提前把字段名写死。

![decide() 封装流程图：工单与截图连同问题和选项进入 decide()，现在调用 gpt-6-luna，开放后换成 Decisions API；合法答案按动作风险执行，needs_human、拒答、截断或列表外结果走兜底路径](https://www.aifreeapi.com/posts/zh/openai-decisions-api/img/decide-wrapper-flow.webp)

## 每千次、每百万次判断要花多少钱：用自己的 token 数复算

Decisions API 的价格没有公布，连按 token、按次还是按问题计费都不知道。能算的是 Luna 方案的成本。按 [Luna 模型页](https://developers.openai.com/api/docs/models/gpt-6-luna)的 Standard 价格（输入 $0.10、输出 $0.50，单位都是每百万 token）：

**单次成本 = 输入 token × $0.10 ÷ 1,000,000 + 输出 token × $0.50 ÷ 1,000,000**

`reasoning.effort` 设为 `none` 时没有推理 token，下表的 token 数都是假设值：

| 假设 | 输入 token | 输出 token | 单次 | 每千次 | 每百万次 |
| --- | ---: | ---: | ---: | ---: | ---: |
| 短文本工单，Standard | 400 | 15 | $0.0000475 | $0.0475 | $47.50 |
| 输入翻倍，Standard | 800 | 15 | $0.0000875 | $0.0875 | $87.50 |
| 短文本工单，Batch（半价） | 400 | 15 | $0.00002375 | $0.02375 | $23.75 |

以第一行为例：400 × $0.10 ÷ 1,000,000 = $0.00004，15 × $0.50 ÷ 1,000,000 = $0.0000075，合计 $0.0000475，乘以 100 万次得 $47.50。Batch 是异步处理，只适合离线重新打标这类不急着要结果的任务。

![GPT-6 Luna 方案每百万次判断的成本算例：短文本工单 $40.00 加 $7.50 共 $47.50，输入翻倍共 $87.50，Batch 半价离线打标共 $23.75](https://www.aifreeapi.com/posts/zh/openai-decisions-api/img/luna-cost-per-million.webp)

换成你自己的数：拿 20 条真实样本跑一遍 `decide()`，取 `input_tokens`、`output_tokens` 的平均值代入公式。有几个因素会让数字变化：

- **图片**：图片按尺寸折算成输入 token，带截图的判断要单独统计，不能套纯文本的数。
- **推理强度**：把 `reasoning.effort` 调到 `low` 或 `medium` 会产生推理 token，费用随之上升。eesel 的测试里，同一批工单在不推理时约每千张 $0.047，`medium` 时约每千张 $0.089。
- **超长输入**：单次输入超过 272K token 时整次请求按更高价格计费，判断类请求一般碰不到。

吞吐方面，Luna 在 Tier 1 的限额是每分钟 500 次请求、50 万 token。每分钟最多能做的判断数 = min(500, 500,000 ÷ 单次总 token)。400 + 15 token 的请求先撞上 500 次的请求数上限；单次超过 1,000 token（比如带图）时，token 上限会先到。

想比较 Luna 和 Sol 在同样 token 用量下的花费，可以看 [GPT-6 Luna 与 Sol 价格对比：API 和 Codex 分别怎么算](/zh/posts/gpt-6-luna-vs-sol-price)。

## 速度差距：OpenAI 称几百毫秒以内，Luna 方案中位约 1.46 秒

Decisions API 唯一有出处的速度说法来自 OpenAI 员工 Thibault Sottiaux 在 X 上的帖子：它经过调优，能在"几百毫秒以内"端到端完成判断。流传更广的"150 ms""比 Luna 快 10 倍"出现在媒体报道、社交平台和发布会幻灯片里（据 [Firecrawl 的描述](https://www.firecrawl.dev/blog/openai-decisions-api-vs-jev)），OpenAI 文档里没有，测试条件也没有公开。这些都是厂商说法，不是测量结果。

Luna 方案有一份公开测试可以参考。eesel 用 20 张客服工单、每种设置跑两遍，从笔记本电脑测端到端耗时（含网络往返）：

| 设置 | 中位耗时 | 最快 | 最慢 |
| --- | ---: | ---: | ---: |
| GPT-6 Luna，推理 none | 1.46 秒 | 0.95 秒 | 2.79 秒 |
| GPT-6 Luna，推理 low | 1.62 秒 | 0.95 秒 | 3.20 秒 |
| GPT-6 Luna，推理 medium | 2.33 秒 | 1.44 秒 | 5.75 秒 |

样本小，又是单一厂商的测试，只能说明数量级。从国内经网关调用还会多出一段网络延迟，要在你自己的网络环境里测。

差距在哪里有影响：工单、邮件分流基本没有影响；实时聊天里，每轮在回复前多等 1 秒以上，用户能感觉到；Agent 一个任务里做 20 次小判断，按 1.46 秒算光等待就要约 29 秒，这才是 Decisions API 的速度承诺真正有价值的地方。

## 严格 schema 只保证选项合法：会发消息、扣钱的动作要加兜底

严格枚举只能保证答案格式正确，不能保证判断正确。同一份 eesel 测试里，"分到哪个队列"所有设置都是 40 次全对；但"这张工单能不能自动回复"，Luna 不推理时 40 次里对了 33 次。分队列错了，损失的是几分钟；自动回复错了，错误回复会直接发到客户那里。

把判断接到会产生后果的动作之前，按这个顺序处理：

1. **留出口**：每个问题都有 `needs_human` 或"其他"这类选项，选中它就转人工或走默认流程。
2. **先影子运行**：上线初期只记录模型的选择，不执行动作，和人工结果对比一段时间，看清错在哪类输入上。
3. **按后果分级**：可撤销的动作（打标签、分队列）可以直接执行；发消息、退款、封号、改数据这类动作，需要人工复核或第二道规则校验。
4. **留日志**：记录输入版本、选项列表版本、答案和最终结果，换模型或换接口时用来对比。

不要指望 Decisions API 开放后的"置信度"替你做这件事。是否返回置信度目前说法冲突：有媒体报道说会返回，eesel 和 Firecrawl 都没有在 OpenAI 的任何页面或帖子里找到依据。在文档出来之前，不要围绕一个没人见过的字段设计阈值。

## 国内开发者怎么跑起来：直连限制与 OpenAI 兼容网关

OpenAI 的 [API 支持国家和地区列表](https://developers.openai.com/api/docs/supported-countries)里没有中国大陆，页面还写明在列表以外访问可能导致账号被封禁或暂停。所以：

- **有合规海外主体和 OpenAI 账号的团队**：直接用上文的 Responses API 写法，这也是以后接入 Decisions API 的唯一路线。
- **没有这个条件的团队**：Decisions API 本身你暂时拿不到，任何网关都不提供；但 Luna 替代方案可以经 OpenAI 兼容网关调用。

以 [laozhang.ai](https://docs.laozhang.ai/) 为例：截至 2026 年 10 月 6 日，它的模型目录列出 `gpt-6-luna`，走 OpenAI 兼容接口（`/v1/chat/completions`），标价输入 $0.1、输出 $0.5（每百万 token），与 OpenAI 官方 Standard 价格相同（目录更新于 9 月 24 日），实际扣费以控制台和调用日志为准。接入时用上文第三步的 Chat Completions 写法，把 `base_url` 换成 `https://api.laozhang.ai/v1`。

它是否完整透传 `response_format` 的严格 json_schema 和 `reasoning_effort`，公开文档里没有写明。上线前先做一次确认：

1. 发一条正常工单，看返回的 `message.content` 是否是 `{"answer": "..."}` 这样的纯 JSON，且值在列表里。
2. 再发一条和问题完全无关的输入（比如一句闲聊），看返回是否仍是合法 JSON、仍是列表里的值（理想情况是 `needs_human`）。
3. 如果返回了自由文本、被 Markdown 代码块包裹的 JSON 或列表外的值，说明约束没有生效。这时本地校验会把它们兜成 `needs_human`，但兜底比例会变高，需要评估是否改走官方直连。

## 出现这些信号时，再评估切换到 Decisions API

以下任一情况出现，就值得拿同一批已标注样本做一次对比：

- developers.openai.com 上出现 Decisions API 的指南页或 API Reference；
- 定价页出现 Decisions API 的价格和计费单位；
- 你的 API Key 请求 `v1/decisions` 不再返回 403；
- 文档明确了是否返回置信度及其含义。

对比时看四个数：准确率（尤其是"该不该执行动作"这类难判断）、延迟的中位数和长尾、每千次判断的实际费用、限额能否撑住你的峰值。只有在你在意的指标上明显更好时才切换；如果你走的是网关路线，还要先确认官方直连对你是否可行。

## Decisions API 价格、开放时间与 Jev 的常见问题

### OpenAI Decisions API 的价格是多少？

截至 2026 年 10 月 6 日，OpenAI 没有公布价格，也没说按 token、按次还是按问题计费。唯一能参照的是底层模型 GPT-6 Luna 的标价：输入 $0.10、输出 $0.50（每百万 token）。按每次 400 输入、15 输出 token 的假设，每百万次判断约 $47.50，但 Decisions API 开放后的定价可能完全不同。

### OpenAI Decisions API 什么时候全面开放？

没有确定日期。9 月 29 日的发布会回顾说"未来几天"会广泛开放，到 10 月 6 日仍只对选定客户开放，Reddit 上也还有人在问它在哪、什么时候发布。以 developers.openai.com 出现正式文档为准。

### OpenAI Decisions API 和 Jev 有什么不同？

Jev 是 TypeSafe AI 在 9 月 15 日发布的专用判断模型，已经正式开放，只接受文本，返回每个选项的概率（据 [Firecrawl 的对比](https://www.firecrawl.dev/blog/openai-decisions-api-vs-jev)）。Decisions API 支持图片输入，但仍在限量预览，是否返回概率也没有确认。输入里有截图或照片时，目前只能留在 OpenAI 这一边，先用 Luna 方案。
