Decisions
POST /v1/decisions is for model calls that exist to make a decision: route a ticket, check whether a message is urgent, score a passage, classify a record. Instead of prose you have to parse, you get typed answers with probabilities to set thresholds on. It follows OpenAI's Decisions API.
Decision models include gpt-6-luna-decisions and microsoft-decision-1.
Ask questions
curl https://api.cloakray.com/v1/decisions \
-H "Authorization: Bearer $CLOAKRAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-luna-decisions",
"input": "Help! My payouts have been failing for 3 days.",
"questions": [
{
"type": "choice",
"name": "department",
"instructions": "Which team should handle this?",
"choices": [
{ "value": "billing", "description": "Payments, invoicing, refunds" },
{ "value": "technical", "description": "Bugs, outages, integrations" }
]
},
{ "type": "predicate", "name": "is_urgent", "instructions": "Does this convey urgency?" },
{
"type": "score",
"name": "impact",
"instructions": "Rate the operational impact.",
"levels": [{ "label": "None" }, { "label": "Limited" }, { "label": "Critical" }]
}
]
}'
Question types
| Type | Asks | Answer |
|---|---|---|
predicate | Whether something is true | probability from 0 to 1 |
choice | Which of your choices applies | choice, a probability per option, and confidence |
score | A rating on your ordered levels, lowest first | score, probabilities, and confidence |
The response
{
"model": "gpt-6-luna-decisions",
"answers": [
{
"type": "choice",
"name": "department",
"choice": "billing",
"probabilities": [
{ "value": "billing", "probability": 0.88 },
{ "value": "technical", "probability": 0.12 }
],
"confidence": 0.81
},
{ "type": "predicate", "name": "is_urgent", "probability": 0.93 },
{ "type": "score", "name": "impact", "score": 1.7, "confidence": 0.74 }
]
}
Answers come back in the order you asked, each with its question's name. A choice keeps the type of the value you gave — string or boolean. A question the model declines comes back as {"type": "refusal", "name": ...} while the others are still answered.
Using the answers
const byName = Object.fromEntries(result.answers.map((answer) => [answer.name, answer]));
if (byName.is_urgent.probability > 0.8) escalate(ticket);
route(ticket, byName.department.choice);
Set thresholds from your own data: label a few hundred examples, look at the probabilities, and pick the cut-off that balances misses against false alarms.
Pricing
Decisions are billed on input tokens; the answers themselves carry no output charge. Prices are on each model's page.