Make decisions from evidence
The Decisions API evaluates evidence against one or more typed questions and returns probabilities, choices, or scores instead of generated prose. Light weight alternative to traditional LLMs, it is ideal when an application must take a predictable action from unstructured or structured evidence.
For example, a support workflow can decide whether to escalate a ticket, select the team that should receive it, and score its urgency in one request. Because the response follows a typed schema, your application can act on it directly without parsing a natural-language answer.
Common uses include:
- classifying and routing support tickets, documents, or events;
- checking evidence against compliance or moderation policies;
- ranking a case against an ordered severity or quality scale;
- selecting the next step in an automated workflow; and
- combining several related decisions in one model call.
Two request contracts are available:
| Contract | Endpoint | Best for |
|---|---|---|
| OpenAI-compatible Decisions | POST /api/v1/predict/decisions | Ordered predicate, choice, and score questions, typed choice values, and applications adopting the OpenAI Decisions shape |
| System One | POST /api/v1/predict/decisions/systemone | Stable question IDs, structured application state, and noul, choice, and score questions |
Both contracts provide typed outcomes. Choose the contract that best matches your application data and integration; model availability is listed below.
See the generated NUA OpenAPI reference for the complete schemas.
Authentication and availability
Authenticate with a NUA key in the X-NUCLIA-NUAKEY header.
Your account must have the Decisions feature enabled.
| Model | Zone | Images | Maximum input |
|---|---|---|---|
jev-1.13.0 | All public cloud zones | No | 64,000 tokens |
gpt-6-luna-decisions | All public cloud zones | Yes | 1,050,000 tokens |
progress-decision-1.0 | aws-us-east-2-1 only | No | 16,384 tokens |
jev-1.13.0 and gpt-6-luna-decisions are available in every public cloud zone. Use the endpoint encoded in your NUA key; the Python SDK selects it automatically.
Choose a model based on the integration and input size you need:
jev-1.13.0is a decision-native Jev model by TypeSafe.gpt-6-luna-decisionsuses the OpenAI Decisions API, supports image input, and accepts substantially larger inputs.progress-decision-1.0(Progress Decision Model 1.0) is a self-hosted decision model for text and structured state inaws-us-east-2-1.
OpenAI-compatible contract
The request contains:
model: the enabled decision model ID.input: a string, or a list of user messages. Message content can be a string or typedinput_textandinput_imageparts. Image input is currently supported only bygpt-6-luna-decisions.questions: a non-empty ordered list of typed questions.safety_identifier: an optional opaque end-user identifier forwarded only to providers that support it. Do not put personal data in it.
Question types are:
predicate: returns a probability from0to1.choice: selects one of the supplied choices and returns confidence and a probability for every choice. Choice values are preserved as either strings or booleans, so"true"andtrueare different values. Values must be unique.score: scores the evidence against an ordered, non-empty list of levels and returns the level probabilities.
Each question can have an optional name, which is copied to its answer.
curl
This example asks the OpenAI provider to make two related incident-routing decisions:
curl --fail-with-body \
--request POST \
'https://<zone>.dp.progress.cloud/api/v1/predict/decisions' \
--header "X-NUCLIA-NUAKEY: Bearer ${NUA_API_KEY}" \
--header 'X-Show-Consumption: true' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-6-luna-decisions",
"input": "The payment gateway is returning HTTP 503 for every checkout.",
"questions": [
{
"type": "predicate",
"name": "outage",
"instructions": "Is there an active checkout outage?"
},
{
"type": "choice",
"name": "page_on_call",
"instructions": "Should the on-call engineer be paged?",
"choices": [
{"value": false, "description": "Do not page"},
{"value": true, "description": "Page immediately"}
]
}
]
}'
Nuclia Python SDK
Register the NUA key, build the typed request, and call NucliaPredict.decision(...). This example uses the OpenAI-backed gpt-6-luna-decisions model:
import os
from nuclia import sdk
from nuclia_models.predict.decisions import OpenAIDecisionRequest
sdk.NucliaAuth().nua(token=os.environ["NUA_API_KEY"])
request = OpenAIDecisionRequest.model_validate(
{
"model": "gpt-6-luna-decisions",
"input": "The payment gateway is returning HTTP 503 for every checkout.",
"questions": [
{
"type": "predicate",
"name": "outage",
"instructions": "Is there an active checkout outage?",
},
{
"type": "choice",
"name": "page_on_call",
"instructions": "Should the on-call engineer be paged?",
"choices": [
{"value": False, "description": "Do not page"},
{"value": True, "description": "Page immediately"},
],
}
],
}
)
result = sdk.NucliaPredict().decision(
request,
show_consumption=True,
)
outage, action = result.answers
print(outage.probability)
print(action.choice, action.confidence)
Use sdk.AsyncNucliaPredict().decision(...) and await the result in asynchronous applications.
OpenAI Python SDK
You can also call the endpoint with the OpenAI Python SDK. Set its base URL to the NUA Predict API and use your NUA key as the API key:
import asyncio
import os
from openai import AsyncOpenAI
async def main() -> None:
async with AsyncOpenAI(
base_url="https://<zone>.dp.progress.cloud/api/v1/predict",
api_key=os.environ["NUA_API_KEY"],
) as client:
result = await client.decisions.create(
model="gpt-6-luna-decisions",
input="The payment gateway is returning HTTP 503 for every checkout.",
questions=[
{
"type": "predicate",
"name": "outage",
"instructions": "Is there an active checkout outage?",
},
{
"type": "choice",
"name": "page_on_call",
"instructions": "Should the on-call engineer be paged?",
"choices": [
{"value": False, "description": "Do not page"},
{"value": True, "description": "Page immediately"},
],
},
],
)
print(result.answers)
asyncio.run(main())
Response
Answers appear in the same order as the questions. A typical response contains:
{
"answers": [
{
"type": "predicate",
"name": "outage",
"probability": 0.98
},
{
"type": "choice",
"name": "page_on_call",
"choice": true,
"confidence": 0.93,
"probabilities": [
{ "value": false, "probability": 0.07 },
{ "value": true, "probability": 0.93 }
]
}
],
"model": "gpt-6-luna-decisions",
"usage": {
"input_tokens": 32,
"input_tokens_details": {
"cache_write_tokens": 0,
"cached_tokens": 0
},
"output_tokens": 0,
"output_tokens_details": {
"reasoning_tokens": 0
},
"total_tokens": 32
},
"consumption": {
"normalized_tokens": {
"input": 32,
"output": 0,
"image": 0
}
}
}
System One contract
The System One request contains:
model: the enabled decision model ID. Set it explicitly so deployments do not depend on a changing default.state: the evidence as a string, JSON object, or JSON array.questions: a non-empty object whose keys are stable question IDs.safety_identifier: the same optional provider-dependent identifier as in the OpenAI-compatible contract.
Question types are:
noul: a binary predicate. Optionalcriteria.trueandcriteria.falsevalues describe the outcomes.choice: a choice among the keys in the requiredcriteriaobject.score: a score across the ordered entries in the requiredcriteriaarray.
state, instructions, and criteria values can be structured JSON, which lets you pass application state without flattening it into a prompt.
curl with structured state
curl --fail-with-body \
--request POST \
'https://<zone>.dp.progress.cloud/api/v1/predict/decisions/systemone' \
--header "X-NUCLIA-NUAKEY: Bearer ${NUA_API_KEY}" \
--header 'X-Show-Consumption: true' \
--header 'Content-Type: application/json' \
--data '{
"model": "jev-1.13.0",
"state": {
"service": "checkout",
"status_codes": [503, 503, 503],
"affected_regions": ["us-east"]
},
"questions": {
"outage": {
"type": "noul",
"instructions": "Is this evidence consistent with an active outage?",
"criteria": {
"true": "The service is unavailable",
"false": "The service is operating normally"
}
},
"severity": {
"type": "score",
"instructions": "Score the incident severity",
"criteria": ["low", "medium", "high", "critical"]
}
}
}'
Nuclia Python SDK
Call NucliaPredict.decision_system_one(...). This example sends structured application state to Jev and keeps stable IDs for each answer. Pass kbid only when you want the optional /{id} route:
import os
from nuclia import sdk
from nuclia_models.predict.decisions import DecisionRequest
sdk.NucliaAuth().nua(token=os.environ["NUA_API_KEY"])
request = DecisionRequest.model_validate(
{
"model": "jev-1.13.0",
"state": {
"service": "checkout",
"status_codes": [503, 503, 503],
"affected_regions": ["us-east"],
},
"questions": {
"outage": {
"type": "noul",
"instructions": "Is this evidence consistent with an active outage?",
},
"action": {
"type": "choice",
"instructions": "Choose the next action",
"criteria": {
"monitor": "Continue monitoring",
"page": "Page the on-call engineer",
},
},
},
}
)
result = sdk.NucliaPredict().decision_system_one(request, show_consumption=True)
print(result.answers["outage"].noul)
print(result.answers["action"].choice)
Use sdk.AsyncNucliaPredict().decision_system_one(...) and await the result in asynchronous applications.
TypeSafe Python SDK
The TypeSafe Python SDK can call the NUA System One endpoint directly. Point the SDK to the NUA route before creating the client:
import asyncio
import os
from typesafe_sdk import AsyncTypeSafeClient, Choice, Noul, Score
from typesafe_sdk._core import endpoints
endpoints.SYSTEM_ONE_PATH = "/v1/predict/decisions/systemone"
async def main() -> None:
async with AsyncTypeSafeClient(
base_url="https://<zone>.dp.progress.cloud/api",
api_key=os.environ["NUA_API_KEY"],
model="jev-1.13.0",
) as client:
result = await client.system_one(
state={
"service": "checkout",
"status_codes": [503, 503, 503],
"affected_regions": ["us-east"],
},
questions={
"outage": Noul(
instructions="Is this evidence consistent with an active outage?"
),
"action": Choice(
instructions="Choose the next action",
criteria={
"monitor": "Continue monitoring",
"page": "Page the on-call engineer",
},
),
"severity": Score(
instructions="Score the incident severity",
criteria=["low", "medium", "high", "critical"],
),
},
)
print(result.nouls["outage"].noul)
print(result.choices["action"].choice)
print(result.scores["severity"].score)
asyncio.run(main())
System One answers are keyed by question ID:
noul:noulprobability.choice: selected criteria key, confidence, and probabilities keyed by criteria key.score: numeric score, confidence, a levellegend, and probabilities keyed by zero-based level index.
The response also contains model, usage, and optional consumption, as in the OpenAI-compatible response.
Usage and consumption
usage is always part of a successful Decisions response. It reports the provider's input, output, and total token counts; supported providers can also report cache and reasoning details.
To receive normalized Progress Agentic RAG billing consumption, add:
X-Show-Consumption: true
With the Python SDK, set show_consumption=True. The response then includes consumption.normalized_tokens with input, output, and image values. See Token consumption for details.