> ## Documentation Index
> Fetch the complete documentation index at: https://mixroute.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAI Decisions API

> 通过 gpt-6-luna 调用 OpenAI 兼容 Decisions 接口：判断、分类、评分的参数、结构化结果与错误处理。

通过 MixRoute 的 OpenAI 兼容 Decisions 接口，对同一份输入提出具名问题并获得结构化答案。模型使用 `gpt-6-luna`；此协议与 Jev System One 不同。

## 接入方式

`POST https://api.mixroute.ai/v1/decisions`

请求头使用 `Authorization: Bearer $MIXROUTE_API_KEY` 和 `Content-Type: application/json`。API Key 仅保存在服务端。模型和渠道权限取决于账户；模型出现在列表中不代表所有接口均可用。

> [!WARNING]
>
> 使用 `input`，不是 `state`；`questions` 是可带 name 的数组，不是以问题 ID 为键的对象。真假判断用 `predicate`，不是 `noul`；分类用 `choices`，评分用 `levels`，不是 Jev 的 `criteria`。响应中的 `answers` 也是数组。Jev 协议见 [System One](https://mixroute.ai/docs/zh-Hans/api-reference/endpoint/jev.md)。

## 请求参数

| 字段 | 类型 | 要求 | 说明 |
| - | - | - | - |
| `model` | string | 必填 | 使用 gpt-6-luna；不能直接替换成其他聊天模型或 Jev ID。 |
| `input` | string / array | 必填 | 所有问题共同评估的输入：文本，或按顺序排列的消息、函数调用及结果、自定义工具调用及结果数组。 |
| `questions` | object\[] | 必填 | 包含 1-400 个 predicate、choice 或 score 问题的数组。各问题独立评估；若依赖上一个答案，应分开请求。 |
| `prompt_cache_key` | string / null | 可选 | 调用方提供的缓存分区标识，最多 64 个字符。 |
| `prompt_cache_options` | object / null | 可选 | 可选缓存设置。mode 为 implicit（默认）或 explicit；ttl 当前支持 30m。实际缓存可用性和计费取决于路由。 |
| `safety_identifier` | string / null | 可选 | 不透明的终端用户标识，最多 128 个字符；建议使用稳定且不含个人信息的标识。 |

## 问题字段

| 字段 | 类型 | 要求 | 说明 |
| - | - | - | - |
| `type` | string | 必填 | predicate、choice 或 score。 |
| `instructions` | string / array | 必填 | 要作出的判断。使用文本字符串或非空的受支持内容项数组。文本和图片项直接放入 instructions，不加消息外层。 |
| `name` | string | 可选 | 响应中原样返回的名称，建议每个问题使用不同名称；未命名的问题可返回 name=null。 |
| `choices` | object\[] | 按类型 | choice 必填，包含 2-255 个互不相同的选项。每项必填 value（字符串或布尔值），可选 description（字符串）。字符串 "true" 与布尔值 true 是不同值。 |
| `levels` | object\[] | 按类型 | score 必填，包含 2-10 个从低到高排列的等级。每项必填 label（字符串），可选 description（字符串）；等级索引从 0 开始。 |

## 答案类型

| 类型 | 说明 |
| - | - |
| `predicate` | probability 是条件成立的估计概率，范围 0-1，不是布尔值。 |
| `choice` | choice 是给定的字符串或布尔选项。probabilities 是 value/probability 对象数组，另有 confidence 字段。 |
| `score` | score 是等级索引的概率加权平均值，范围为 0 到 levels.length-1，可为小数。probabilities 包含 value（索引）、label 和 probability。 |

任何问题都可能返回 type=refusal，其他问题仍可正常返回。按 name 或问题顺序匹配，先判断 type，再读取对应字段，并显式处理拒答。置信度和概率不保证判断正确。

## 请求示例

调用前设置 `MIXROUTE_API_KEY`。示例只提交一次，不自动重试；客户端超时不代表服务端没有执行推理。

> [tab] cURL
>
> ```bash theme={null}
> curl --request POST "https://api.mixroute.ai/v1/decisions" \
>   --header "Authorization: Bearer $MIXROUTE_API_KEY" \
>   --header "Content-Type: application/json" \
>   --data '{
>   "model": "gpt-6-luna",
>   "input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
>   "questions": [
>     {
>       "type": "choice",
>       "name": "team",
>       "instructions": "Which team should handle this ticket?",
>       "choices": [
>         {
>           "value": "engineering",
>           "description": "Software defects"
>         },
>         {
>           "value": "billing",
>           "description": "Payments and refunds"
>         }
>       ]
>     },
>     {
>       "type": "score",
>       "name": "urgency",
>       "instructions": "How soon does the customer need help?",
>       "levels": [
>         {
>           "label": "No deadline",
>           "description": "No deadline is specified."
>         },
>         {
>           "label": "This week",
>           "description": "Help is needed within a week."
>         },
>         {
>           "label": "Today",
>           "description": "Help is explicitly required today."
>         }
>       ]
>     },
>     {
>       "type": "predicate",
>       "name": "needs_human",
>       "instructions": "Does the customer request a human agent?"
>     }
>   ]
> }'
> ```

> [tab] Python
>
> ```python theme={null}
> import json
> import os
> import requests
>
> payload = json.loads(r'''{
>   "model": "gpt-6-luna",
>   "input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
>   "questions": [
>     {
>       "type": "choice",
>       "name": "team",
>       "instructions": "Which team should handle this ticket?",
>       "choices": [
>         {
>           "value": "engineering",
>           "description": "Software defects"
>         },
>         {
>           "value": "billing",
>           "description": "Payments and refunds"
>         }
>       ]
>     },
>     {
>       "type": "score",
>       "name": "urgency",
>       "instructions": "How soon does the customer need help?",
>       "levels": [
>         {
>           "label": "No deadline",
>           "description": "No deadline is specified."
>         },
>         {
>           "label": "This week",
>           "description": "Help is needed within a week."
>         },
>         {
>           "label": "Today",
>           "description": "Help is explicitly required today."
>         }
>       ]
>     },
>     {
>       "type": "predicate",
>       "name": "needs_human",
>       "instructions": "Does the customer request a human agent?"
>     }
>   ]
> }''')
> response = requests.post(
>     "https://api.mixroute.ai/v1/decisions",
>     headers={"Authorization": "Bearer " + os.environ["MIXROUTE_API_KEY"]},
>     json=payload,
>     timeout=60,
>     allow_redirects=False,
> )
> response.raise_for_status()
> result = response.json()
> if not isinstance(result.get("answers"), list):
>     raise ValueError("Expected an answers array")
> for answer in result["answers"]:
>     kind = answer["type"]
>     if kind == "refusal":
>         print(answer.get("name"), "refused")
>         continue
>     field = {"predicate": "probability", "choice": "choice", "score": "score"}.get(kind)
>     if field is None:
>         raise ValueError("Unexpected answer type: " + kind)
>     print(answer.get("name"), answer[field])
> ```

> [tab] JavaScript
>
> ```javascript theme={null}
> const apiKey = process.env.MIXROUTE_API_KEY;
> if (!apiKey) throw new Error("Set MIXROUTE_API_KEY");
> const payload = {
>   "model": "gpt-6-luna",
>   "input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
>   "questions": [
>     {
>       "type": "choice",
>       "name": "team",
>       "instructions": "Which team should handle this ticket?",
>       "choices": [
>         {
>           "value": "engineering",
>           "description": "Software defects"
>         },
>         {
>           "value": "billing",
>           "description": "Payments and refunds"
>         }
>       ]
>     },
>     {
>       "type": "score",
>       "name": "urgency",
>       "instructions": "How soon does the customer need help?",
>       "levels": [
>         {
>           "label": "No deadline",
>           "description": "No deadline is specified."
>         },
>         {
>           "label": "This week",
>           "description": "Help is needed within a week."
>         },
>         {
>           "label": "Today",
>           "description": "Help is explicitly required today."
>         }
>       ]
>     },
>     {
>       "type": "predicate",
>       "name": "needs_human",
>       "instructions": "Does the customer request a human agent?"
>     }
>   ]
> };
> const response = await fetch("https://api.mixroute.ai/v1/decisions", {
>   method: "POST",
>   headers: {
>     Authorization: "Bearer " + apiKey,
>     "Content-Type": "application/json",
>   },
>   body: JSON.stringify(payload),
>   signal: AbortSignal.timeout(60000),
>   redirect: "error",
> });
> const result = await response.json();
> if (!response.ok) {
>   throw new Error(result.error?.message ?? "HTTP " + response.status);
> }
> if (!Array.isArray(result.answers)) throw new Error("Expected an answers array");
> for (const answer of result.answers) {
>   if (answer.type === "refusal") {
>     console.log(answer.name, "refused");
>     continue;
>   }
>   const field = { predicate: "probability", choice: "choice", score: "score" }[answer.type];
>   if (!field) throw new Error("Unexpected answer type: " + answer.type);
>   console.log(answer.name, answer[field]);
> }
> ```

## 响应示例

同步返回 JSON 对象，不是 Chat Completions 的 choices 数组，也不是需要轮询的任务。概率和 token 用量会随请求变化。

```json theme={null}
{
  "model": "gpt-6-luna",
  "answers": [
    {
      "type": "choice",
      "name": "team",
      "choice": "engineering",
      "probabilities": [
        {
          "value": "engineering",
          "probability": 1
        },
        {
          "value": "billing",
          "probability": 0
        }
      ],
      "confidence": 1
    },
    {
      "type": "score",
      "name": "urgency",
      "score": 2,
      "probabilities": [
        {
          "value": 0,
          "label": "No deadline",
          "probability": 0
        },
        {
          "value": 1,
          "label": "This week",
          "probability": 0
        },
        {
          "value": 2,
          "label": "Today",
          "probability": 1
        }
      ],
      "confidence": 1
    },
    {
      "type": "predicate",
      "name": "needs_human",
      "probability": 1
    }
  ],
  "usage": {
    "input_tokens": 416,
    "input_tokens_details": {
      "cached_tokens": 0,
      "cache_write_tokens": 0
    },
    "output_tokens": 0,
    "output_tokens_details": {
      "reasoning_tokens": 0
    },
    "total_tokens": 416
  }
}
```

| 字段 | 说明 |
| - | - |
| `model` | 实际执行判断的模型。 |
| `answers` | 与问题顺序一致的数组；先检查每项的 type 和 name。 |
| `usage.input_tokens` | 本次请求的输入 token 用量。 |
| `usage.input_tokens_details` | cached\_tokens、cache\_write\_tokens 已包含在 input\_tokens 中，不要重复相加。 |
| `usage.output_tokens / usage.output_tokens_details` | 输出用量及 reasoning\_tokens，不代表返回了聊天文本。 |
| `usage.total_tokens` | 接口报告的总 token 用量。 |

## 结构化与图片输入

user 消息的 content 可包含 input\_text（text）、input\_image（image\_url）、input\_json（data）。JSON data 必须是对象或对象数组；其中的键仅为待判断的数据，不会触发图片抓取或创建消息。JSON 输入最多 32 层容器、10,000 个值、256 KiB 的紧凑 UTF-8 JSON。

```json theme={null}
{
  "model": "gpt-6-luna",
  "input": [
    {
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "Evaluate the ticket record."
        },
        {
          "type": "input_json",
          "data": {
            "ticket": {
              "feature": "CSV export",
              "fails": true,
              "deadline": "today"
            }
          }
        }
      ]
    }
  ],
  "questions": [
    {
      "type": "predicate",
      "name": "deadline_today",
      "instructions": "Does the ticket require action today?"
    }
  ]
}
```

图片使用公开 HTTP(S) URL 或 Base64 data URL，不使用 file\_id。detail 可选 auto、low、high、original。developer/system 消息使用文本；assistant 消息使用输出文本或拒答项。工具结果通过 call\_id 与调用匹配。此协议不接受文件、音频或条目引用。以上为协议格式，高级输入的实际可用性取决于 MixRoute 路由。

将示例图片地址替换为可公开访问的商品图片或 Base64 data URL。

```json theme={null}
{
  "model": "gpt-6-luna",
  "input": [
    {
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "Inspect this product photo."
        },
        {
          "type": "input_image",
          "image_url": "https://example.com/product.png",
          "detail": "auto"
        }
      ]
    }
  ],
  "questions": [
    {
      "type": "predicate",
      "name": "visible_damage",
      "instructions": "Does the product show a crack, tear, or dent?"
    }
  ]
}
```

## 可选提示词缓存

共享 input 至少达到 1,024 tokens 才具备缓存条件；questions 不属于可复用输入前缀。默认使用隐式断点；显式断点在共享 input 的文本或图片项中设置 `prompt_cache_breakpoint: {"mode": "explicit"}`。prompt\_cache\_options.mode=explicit 且没有显式断点时不使用缓存。问题 instructions 不支持缓存断点。不要将上游缓存折扣或价格直接视为 MixRoute 费率。

## 错误与计费

先检查 HTTP 状态。网关错误可能包含 error.message、error.type、error.code、error.param，其中 param 可能为空。排查时保留 x-oneapi-request-id，不记录完整 API Key。

| HTTP | 说明 |
| - | - |
| 400 invalid\_request | 检查 input 和 questions 数组；问题对象映射属于 Jev 格式，不适用于本接口。 |
| 401 / 403 | 检查认证及接口、模型权限。 |
| 503 model\_not\_found | 当前 Key／分组没有该模型的可用渠道，不是模型返回的判断结果。 |
| 429 / 其他 5xx | 存在 Retry-After 时遵循该值，仅在适当情况下有限重试；结果不确定的超时不要自动重复提交。 |

```json theme={null}
{
  "error": {
    "message": "questions must be a non-empty array",
    "type": "mixroute_error",
    "param": "",
    "code": "invalid_request"
  }
}
```

结合 usage 与当前[模型广场](https://console.mixroute.ai/models)确认计费。不要假定 Responses 或 Chat Completions 的费率适用于 Decisions；实际费用取决于账户倍率和路由定价。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.