Nebul Docs

Decisions

Ask yes/no, choice and score questions about a text and get a probability for every option

The Decisions API answers typed questions about a piece of text. You send the text and your questions, and you get one answer per question with a probability for every option. Nothing is generated for you to parse, and the answer can't fall outside the options you supplied. Use it for triage, routing, tagging and moderation, where you need a label and a number.

Every example here reads your key from NEBUL_API_KEY; export it first. The Quick Start covers key setup.

Models

Two models serve decisions today. Call them by these exact IDs.

ModelContext
google/gemma-4-31B-it262,144 tokens
Qwen/Qwen3-0.6B40,960 tokens

Other chat models return 501 instead of an answer.

Request

POST https://api.inference.nebul.io/v1/decisions

Parameters

ParameterTypeRequiredDescription
modelStringYesA model that serves decisions. Pick one from Models.
inputString or ArrayYesThe text every question is about: a string, or an array of {role: "user", content} messages. Text only.
questionsArrayYes1 to 64 questions, answered in the order you send them.
questions[].typeStringYespredicate, choice or score.
questions[].instructionsStringYesThe question, written as you would ask a person.
questions[].nameStringNoEchoed in the answer so you can match answer to question.
questions[].choicesArraychoice only2 to 26 objects of {value, description}. value is a string or a boolean.
questions[].levelsArrayscore only2 to 10 objects of {label, description}, lowest level first.
cache_saltStringNoSalt for the prefix cache. See Prompt / KV Caching.

Input is text only. Send an image part or a tool call inside input and the request fails with a 400, so flatten agent transcripts and screenshots to text before you call the endpoint.

Question types

TypeQuestionYou sendYou get backUse for
predicateIs this true about the input?instructionsprobability, 0 to 1Binary flags: needs_refund, is_urgent.
choiceWhich one of these?2 to 26 {value, description}choice, probabilities, confidenceRouting, categories, language.
scoreHow much, on this scale?2 to 10 ordered {label, description}score, probabilities, confidenceSeverity, sentiment, urgency.

choice reads one label token per option, which caps it at 26. score reads digit tokens and returns the expected level, so a score of 1.2 on low, medium, high sits between medium and high. When you would otherwise ask several predicates about one scale, use one score: one read, and the levels are mutually exclusive by construction.

Example

Ask two questions about one support message:

import os

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["NEBUL_API_KEY"],
    base_url="https://api.inference.nebul.io/v1",
)

response = client.decisions.create(
    model="google/gemma-4-31B-it",
    input="The parcel arrived damaged and support ignored my emails.",
    questions=[
        {
            "type": "choice",
            "name": "team",
            "instructions": "Which team should handle this?",
            "choices": [
                {"value": "payments", "description": "billing and duplicate charges"},
                {"value": "technical", "description": "app and login problems"},
                {"value": "other", "description": "anything else"},
            ],
        },
        {
            "type": "score",
            "name": "severity",
            "instructions": "How severe is the problem?",
            "levels": [{"label": "low"}, {"label": "medium"}, {"label": "high"}],
        },
    ],
)

for answer in response.answers:
    print(answer)

Response

One entry in answers per question, in request order, carrying the name you set.

{
  "model": "google/gemma-4-31B-it",
  "answers": [
    {
      "type": "choice",
      "name": "team",
      "choice": "other",
      "probabilities": [
        { "value": "payments", "probability": 4.2e-11 },
        { "value": "technical", "probability": 6.3e-10 },
        { "value": "other", "probability": 0.9999999993 }
      ],
      "confidence": 0.9999998807
    },
    {
      "type": "score",
      "name": "severity",
      "score": 2.0,
      "probabilities": [
        { "value": 0, "label": "low", "probability": 1.03e-10 },
        { "value": 1, "label": "medium", "probability": 2.85e-8 },
        { "value": 2, "label": "high", "probability": 0.9999999714 }
      ],
      "confidence": 0.9999996423
    }
  ],
  "usage": {
    "input_tokens": 126,
    "input_tokens_details": { "cached_tokens": 0, "cache_write_tokens": 64 },
    "output_tokens": 2,
    "output_tokens_details": { "reasoning_tokens": 0 },
    "total_tokens": 128
  }
}
FieldTypeDescription
modelStringThe model that answered.
answersArrayOne entry per question, in request order.
answers[].probabilityNumberpredicate: the probability that the statement is true, from 0 to 1.
answers[].choiceString or Booleanchoice: the option with the highest probability.
answers[].probabilitiesArraychoice, score: every option with its probability, in the order you sent them.
answers[].scoreNumberscore: the expected level, counting from 0 for the first level you sent. With low, medium, high, a score of 2.0 means high.
answers[].confidenceNumberchoice, score: the chosen option's probability among every token the model could emit, so a read that mostly wanted a non-option word reports a lower number.
usage.input_tokensIntegerThe input counted once, however many questions you ask about it.
usage.input_tokens_details.cached_tokensIntegerHow much of the input came from the prefix cache.
usage.output_tokensIntegerOne read per question.
usage.total_tokensIntegerInput plus output.

Every question comes back as one of these three types. The endpoint doesn't decline to answer, so a question the model has no idea about still returns a probability, usually a low one. Set your own threshold when a wrong label costs more than a missing one.

Probabilities

Probabilities sum to 1 across the options of a question. They are the model's raw readout, so they sit close to 0 and 1 and a wrong option can still score near certainty. Compare options within a question, and treat the number as a ranking signal rather than a calibrated confidence.

Limits

LimitValue
Questions per request64
Options per choice26
Levels per score10

Exceeding a limit returns a 400 with the reason, for example questions: at most 64 for this model or This model supports at most 26 choices per question. The option and level ceilings come from the model reading one label token per option: 26 letters for a choice, 10 digits for a score.

Errors

StatusCause
400Malformed request, or a limit exceeded.
404Unknown model ({"error_type": "not_found"} with the model ID).
501The model runs on a vLLM build that doesn't serve decisions yet.
503The model is not available.

Errors use the standard envelope: {"error": {"message", "type", "param", "code"}}.

On this page