Skip to main content

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:

ContractEndpointBest for
OpenAI-compatible DecisionsPOST /api/v1/predict/decisionsOrdered predicate, choice, and score questions, typed choice values, and applications adopting the OpenAI Decisions shape
System OnePOST /api/v1/predict/decisions/systemoneStable 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.

ModelZoneImagesMaximum input
jev-1.13.0All public cloud zonesNo64,000 tokens
gpt-6-luna-decisionsAll public cloud zonesYes1,050,000 tokens
progress-decision-1.0aws-us-east-2-1 onlyNo16,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.0 is a decision-native Jev model by TypeSafe.
  • gpt-6-luna-decisions uses 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 in aws-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 typed input_text and input_image parts. Image input is currently supported only by gpt-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 from 0 to 1.
  • 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" and true are 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. Optional criteria.true and criteria.false values describe the outcomes.
  • choice: a choice among the keys in the required criteria object.
  • score: a score across the ordered entries in the required criteria array.

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: noul probability.
  • choice: selected criteria key, confidence, and probabilities keyed by criteria key.
  • score: numeric score, confidence, a level legend, 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.