Skip to main content
Jev AI logoJev AI

Jev Choice: The Classification Question Type

Last verified against the TypeSafe docs on 22 September 2026 · model jev-1.13.0

What a Choice question looks like

A Choice question has `type` set to `"choice"`, an `instructions` string holding the question, and `criteria`: a map where each key is an option name and each value describes that option. Both the names and the descriptions are sent to the model, so write descriptions that separate the options from one another.

JSON
{
  {
  "state": : "My running shoes arrived in the wrong size. Can I swap them for a size 10?",
  ,
  "questions": {
    : {
    "department": {
      : {
      "type": : "choice",
      ,
      "instructions": : "Which team should handle this?",
      ,
      "criteria": {
        : {
        "returns": : "Exchanges, wrong or damaged items",
        ,
        "shipping": : "Delivery status, delays, lost packages",
        ,
        "billing": : "Charges, invoices, payment problems"
      }
    }
  }
}
      }
    }
  }
}

Note the shape of `criteria`. For a Choice it is a map, not a list — the option keys are what comes back in `choice`, so pick keys your code can switch on.

What comes back

JSON
{
  {
  "model": : "jev-1.13.0",
  ,
  "answers": {
    : {
    "department": {
      : {
      "type": : "choice",
      ,
      "choice": : "returns",
      ,
      "confidence": : 1.0,
      ,
      "probabilities": {
        : {
        "shipping": : 0.0,
        ,
        "returns": : 1.0,
        ,
        "billing": : 0.0
      }
    }
  },
  
      }
    }
  },
  "usage": {
    : {
    "input_tokens": : 328,
    ,
    "output_tokens": : 34
  }
}
  }
}

This ticket is an easy one: all of the probability sits on `returns` and confidence is 1.0. A ticket that mentioned both a wrong size and a missing refund would split probability between `returns` and `billing`, and the confidence would drop.

Reading confidence

`confidence` is a number from 0 to 1 computed from how `probabilities` is spread. A single peak on one option means high confidence. A flat shape, with probability spread across several options, means low confidence.

The TypeSafe docs show what that looks like on a harder ticket: "Shoes arrived two weeks late and in the wrong size. Also I see two charges of $120 on my card. What are you going to do about this?"

Question`choice``confidence`Distribution
`department`returns0.42returns 0.61, billing 0.35, shipping 0.04
`return_reason`wrong_size1.0wrong_size 1.0
`requested_resolution`refund0.20refund 0.40, replacement 0.34, exchange 0.24, information 0.02
`tone`frustrated0.76frustrated 0.84, angry 0.16, calm 0.0

TypeSafe docs, Choice

The ticket genuinely belongs to two teams, and the 0.42 confidence on `department` reflects that. The resolution question is weaker still at 0.20: the double charge suggests money back, the wrong size suggests a swap, and the customer never says which they want. That is a case for asking rather than guessing.

A low confidence value is a routing decision, not a verdict on the answer. Note too that confidence 1.0 describes the model's distribution, not a guarantee that the answer is correct.

Acting on the distribution, not just the winner

Because `probabilities` covers every option, your code can do more than read the winner:

Python
department = answers[department = answers["department"]

]

if department.confidence <  department.confidence < 0.3:
    send_to_manual_triage(ticket)
    :
    send_to_manual_triage(ticket)
    return

assign(ticket, team=department.choice)



assign(ticket, team=department.choice)

# A second team with a real share of the probability gets a copy

for team, probability  team, probability in department.probabilities.items():
     department.probabilities.items():
    if team != department.choice  team != department.choice and probability >  probability > 0.25:
        notify(ticket, team=team):
        notify(ticket, team=team)

For the ticket above this assigns it to returns, and copies billing in because its 0.35 share clears the 0.25 bar.

Writing the option set

  • Give the full list. A Choice question accepts up to 255 options, and each option costs only a few tokens, so send the whole list of teams, categories or products rather than a shortlist.
  • Add an escape hatch. When the list might not cover every input, include an `other` or `none of the above` option so the model can say that none of the others fit. A Choice always names a winner, so without one, an input that fits nothing still gets assigned somewhere.
  • Descriptions can be null. When the option names speak for themselves, `null` is a valid description. The TypeSafe docs use `{"calm": null, "frustrated": null, "angry": null}` for a tone question.
  • Use objects when two options keep getting confused. Instead of one line per option, give each a structured description with a field for what it covers, a field for what belongs to the neighbouring option instead, and a few examples:
JSON
"criteria": {
  : {
  "return_policy": {
    : {
    "what": : "Whether and how an item can be returned",
    ,
    "not_for": : "Progress of a return already sent",
    ,
    "examples": [
      : [
      "Can I return shoes I've worn once?",
      ,
      "How long do I have to return an order?"
    ]
  },
  
    ]
  },
  "return_status": {
    : {
    "what": : "Progress of a return already sent",
    ,
    "not_for": : "Whether and how an item can be returned",
    ,
    "examples": [
      : [
      "Has my return arrived yet?",
      ,
      "When will my refund be paid?"
    ]
  }
}
    ]
  }
}

The field names `what`, `not_for` and `examples` are not part of the API and none of them are reserved. You pick them, the same way you pick option names, and the model sees the names along with the values. On the message "I sent the shoes back a week ago. When do I get my money?", this question returns `return_status` at confidence 1.0.

Deep taxonomies chain. For a large hierarchy, ask a Choice per level and let each answer decide which options the next question offers, rather than flattening everything into one question.

Choice, Noul or Score

NoulChoiceScore
AsksIs this true?Which of these options?Which level?
`criteria` shapeOptional object with `true` and `false` descriptionsMap of option name to descriptionOrdered array of level descriptions
Returns`noul``choice`, `probabilities`, `confidence``score`, `legend`, `probabilities`, `confidence`
Value range0 to 1One of your option keys0 to the top level number
Has `confidence`NoYesYes
Size limit—Up to 255 optionsAt least 2 levels, up to 10
Your code doesAn `if`Branches per optionCompares to a threshold
flowchart TD
    A[What shape is the answer?] --> B{Yes or no?}
    B -- Yes --> C[Noul]
    B -- No --> D{Do the answers<br/>have an order?}
    D -- No --> E[Choice]
    D -- Yes --> F{Can you describe<br/>each level?}
    F -- Yes --> G[Score]
    F -- No --> E

use a Noul when there are only two outcomes and you want the probability itself. use a Score when the options have an order and you can describe each level. Use a Choice when the options are distinct and unordered, and especially when each one maps to its own code path.

One thing a Choice will not do is tell you that nothing applies, because its probabilities always sum to 1 across the options you gave. If "none of these" is a real outcome, make it an option.

FAQ

How many options can a Jev Choice have?

Up to 255. The docs recommend giving the model the full list rather than a shortlist, since options cost only a few tokens each.

Is `criteria` a list or a map for a Choice?

A map. Each key is an option name and each value describes it. Score is the type that takes an ordered array.

What does the confidence value mean?

How peaked the probability distribution is. All the probability on one option gives 1.0; spread across several options gives a lower number. It describes the distribution, not the correctness of the answer.

Can a Choice answer be "none of these"?

Only if you make it an option. The probabilities always sum to 1 across the options you supplied, so a Choice always names a winner.

Choice or several Nouls?

If exactly one option is true, a Choice gives you the winner and the full distribution in one answer. If the conditions can overlap or be true at the same time, ask separate Nouls.