Explainer

Typed decisions: asking a model for a value, not a paragraph

A typed decision is a question where you list the allowed answers before the AI sees anything: pick one of these teams, rate urgency on this scale, or say how likely this is true. The model can only answer from your list, so your software can act on the result straight away.

9 min readLast updated

Swiss-hosted inference. Nothing you send is ever stored.Swiss data residency

In 30 seconds

  • You write the question and the allowed answers; the model picks from your list.
  • Every answer comes with a probability, so you can decide when to trust it and when to ask a person.
  • Nothing is written as free text, so there is no reply to parse and no invented category.
  • Laya answers several typed questions about the same text in one quick pass.
  • It still needs testing on your own data: a valid answer can still be the wrong one.

Code and dense tables are folded away. Open any of them on demand.

What is a typed decision?

A typed decision is a question to an AI model where you declare the answer type and the allowed options before it reads the input: one label from a list, a level on a scale, or the probability that a statement is true. The model returns only a value from that space, with probabilities, so code can act on it.

Most software that "uses AI to decide" is really asking a question with a small, known answer space. Which team should own this ticket? How urgent is it? Is this message a phishing attempt? The answer is not an essay. It is a value from a set you already know: a label, a level on an ordinal scale, or a yes/no probability.

A typed decision makes that explicit. Before the model reads the input, you declare three things:

  1. The state: the thing being judged, such as an email, a ticket, a JSON record or a conversation.
  2. The question: a short natural-language instruction, for example "Which department should handle this request?"
  3. The answer type and its options: the set of labels, the ordered levels, or the true/false pair that a valid answer must come from.

The model's job is then narrow and checkable. It does not write an answer. It distributes probability over answers you already enumerated. Every output is valid by construction, because the only things it can return are the things you listed.

This is the same idea as a type signature in a programming language. A function typed (Ticket) -> Department cannot return a haiku. A typed decision model cannot either.

Why typed decisions beat free-text answers in production

The usual alternative is to prompt a generative model ("Reply with one of: billing, technical, sales, other") and parse what comes back. That works in a demo and becomes a maintenance problem at volume.

ConcernFree-text LLM answerTyped decision
Output validityMust be parsed and validated; can drift ("Billing.", "billing team", "I think billing")Always one of the declared options
ProbabilitiesNot returned by default; verbalised confidence is unreliableA full distribution over the options
ThresholdingHard: there is no number to thresholdNatural: gate on confidence or a class probability
Out-of-set answersPossible (an invented category)Impossible by construction
Cost driverInput plus generated output tokensOne forward pass per call
AuditingLog a string and hope it parses the same way next monthLog a distribution and the options it was over

The deeper benefit is that a typed answer composes with ordinary code. A choice feeds a switch statement. A score feeds a sort order or an SLA timer. A noul probability feeds an if p > 0.8 gate. None of these need a second model to interpret the first one's prose.

Typed decisions do not remove the need to evaluate. A typed model can still pick the wrong option with high probability. What typing removes is a whole class of format failures, so the failures you are left with are judgement failures, which you can measure with accuracy and calibration metrics. See calibrated probabilities for why the distribution matters as much as the argmax.

The anatomy of a typed decision request

A typed decision request has a fixed shape. Laya uses the same shape as TypeSafe's Jev decision API, which introduced the /v1/systemone protocol:

Show technical details· json sample
json
{
  "state": { "subject": "Duplicate charge", "body": "We were billed twice for March." },
  "questions": {
    "department": {
      "type": "choice",
      "instructions": "Which department should handle this request?",
      "criteria": { "billing": "invoices, payments, refunds", "technical": "bugs, outages", "other": "everything else" }
    },
    "urgency": {
      "type": "score",
      "instructions": "How urgent is this request?",
      "criteria": ["not urgent", "soon", "critical deadline or blocking issue"]
    },
    "refund_requested": {
      "type": "noul",
      "instructions": "Does the user explicitly request a refund?"
    }
  }
}
  • state can be a string, an object or a list (for example a conversation). Objects are serialised to JSON before the model reads them, so field names such as subject and body are visible to the model and can be referenced in instructions.
  • questions is a map from your own ids to question definitions. The ids come back unchanged in the response, so you never match answers by position.
  • type is one of three primitives: choice, score or noul. They are covered in depth in choice, score and noul.
  • criteria defines the answer space. For choice it is a map of label to description (or a plain list of labels). For score it is an ordered list of level descriptions, index 0 first. For noul it is optional and can describe what true and false mean.

How Laya implements typed decisions

Laya is an encoder model, not a text generator. For each question it builds one token sequence:

Show technical details· text sample
text
[CLS] <type> question: <instructions> [SEP] [MASK] option0 [MASK] option1 ... [SEP] <state> [SEP]

Every option gets its own [MASK] marker. The encoder (ModernBERT-large for the English checkpoint, mmBERT-base for the multilingual one) reads the whole sequence bidirectionally, a small two-layer decision head refines it, and a scorer reads one logit off each marker. A softmax over those logits is the answer distribution. A learned type embedding tells the model whether it is answering a choice, score or noul. The mechanics are described in option-marker scoring.

Three consequences follow directly from that design:

  1. The answer space is defined at request time. There is no fixed label head, so a new schema needs no retraining. You can change the options on the next call.
  2. All questions in a call run in one batched forward pass. The model card reports 39.5 ms for one question and 158.6 ms for ten on the English checkpoint on a T4 GPU, and 32.8 ms and 72.3 ms on the multilingual checkpoint.
  3. Nothing is generated. The response contains no free text from the model, so there is nothing to parse. See hallucination-free decisions for what that does and does not guarantee.

The output for each question is typed as well:

Question typeMain fieldAlso returned
choicechoice: the argmax labelprobabilities per label, confidence
scorescore: expected level, sum of i × p(i)probabilities per level, legend, confidence
noulnoul: probability the statement is trueconfidence = max(p, 1 − p)

The typed-decisions benchmark and checkpoint

"Typed decisions" is also the name of a specific benchmark: 400 cases and 2,000 decisions across four synthetic workflows (customer service, invoice processing, security incidents and agent-trace observability). The Laya family includes a checkpoint fine-tuned on that benchmark's training split, laya-typed-decisions.

The model card reports, on that benchmark:

Show technical details· 6 rows × 4 columns
ModelAccuracyBrierECE
laya-typed-decisions0.7660.0620.213
laya (English base)0.3620.3160.175
laya-multilingual0.3420.4390.285
Jev 1.13.0 (third-party published)0.7270.1480.144
Teacher self-agreement ceiling0.735
Per-question majority class0.461

Two honest readings. First, the fine-tuned checkpoint is strong on the workflows it was trained on. Second, the base checkpoints are below the majority-class baseline on this benchmark zero-shot. The card says it plainly: Laya is "a fast base to specialise, not a zero-shot decision engine" for this kind of multi-field workflow. If your schema resembles one of the four workflows, the specialised checkpoint is worth trying. If it does not, plan to evaluate the base checkpoints on your own data, and consider fine-tuning. The trade-off is discussed in zero-shot vs fine-tuned.

Designing typed questions that work

A few rules drawn from the model card's limitations and from how the sequence is built:

  • Keep option sets small. Options share a fixed option budget (head_max_len, 192 tokens on the English checkpoint, 256 on multilingual). At 77 options each label gets roughly 3 to 4 tokens, and on Banking77 Laya scores 0.425 against Jev's published 0.870. For large label spaces, split into a coarse question and a fine question.
  • Describe options, do not just name them. "billing": "invoices, payments, refunds" gives the scorer something to match against. Descriptions are truncated at 48 tokens per option.
  • Include an escape option. An other choice lets the model put mass somewhere honest when nothing fits.
  • Check noul on your data. The card documents that noul can follow its false: / true: labels rather than the state. If answers look stuck, ask the same thing as a two-option choice with neutral keys.
  • Treat score as the weakest primitive. The card reports SST-5 at 0.372. Use few, clearly separated levels.
  • Calibrate before you threshold. The checkpoints ship over-confident. See temperature scaling.

Try it: a typed decision request to Laya Studio

Laya Studio hosts the open Laya checkpoints behind the /v1/systemone protocol. Get a key at /signup and send:

Show technical details· bash sample
bash
curl -s https://api.laya.studio/v1/systemone \
  -H "Authorization: Bearer $LAYA_STUDIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "state": {
      "subject": "Duplicate charge on invoice #4411",
      "body": "We were billed twice for March. Please refund the duplicate today or we will cancel."
    },
    "questions": {
      "department": {
        "type": "choice",
        "instructions": "Which department should handle this request?",
        "criteria": {
          "billing": "invoices, payments, refunds",
          "technical": "bugs, outages, system errors",
          "sales": "pricing, new contracts",
          "other": "everything else"
        }
      },
      "urgency": {
        "type": "score",
        "instructions": "How urgent is this request?",
        "criteria": ["not urgent", "soon", "critical deadline or blocking issue"]
      },
      "refund_requested": {
        "type": "noul",
        "instructions": "Does the user explicitly request a refund?"
      }
    }
  }'

The response has this shape (the numbers are illustrative, not a benchmark; routing.detection is trimmed):

Show technical details· json sample
json
{
  "model": "laya-rl-agent",
  "answers": {
    "department": {
      "type": "choice",
      "choice": "billing",
      "probabilities": { "billing": 0.9121, "technical": 0.0287, "sales": 0.0214, "other": 0.0378 },
      "confidence": 0.7173,
      "action": { "act_probability": 0.9987 }
    },
    "urgency": {
      "type": "score",
      "score": 1.4681,
      "legend": { "0": "not urgent", "1": "soon", "2": "critical deadline or blocking issue" },
      "probabilities": { "0": 0.0812, "1": 0.3695, "2": 0.5493 },
      "confidence": 0.18,
      "action": { "act_probability": 0.9991 }
    },
    "refund_requested": {
      "type": "noul",
      "noul": 0.9312,
      "confidence": 0.9312,
      "action": { "act_probability": 0.9994 }
    }
  },
  "usage": { "input_tokens": 212, "output_tokens": 0 },
  "routing": { "model": "english", "repo": "convaiinnovations/laya", "reason": "English Latin text" }
}

This call is billed its input tokens (1 credit = 1 input token); each of the three questions reads the state once. See /pricing for the 5 free runs and plans, and /docs for the full reference.

Frequently asked questions

Is a typed decision the same as classification?
It generalises classification. A choice question is multi-class classification with labels supplied at request time. score adds ordinal scales and noul adds calibrated binary probabilities, all in the same request and the same forward pass.
Can I change the options without retraining?
Yes. Laya scores each option at its own marker token, so the label set is part of the input, not the weights. Accuracy still depends on how well the base model understands your options, so evaluate new schemas before relying on them.
Why is output_tokens always 0?
Laya never generates tokens. It reads the input once and scores the options you supplied. The usage block keeps the field for wire compatibility with Jev clients.
When should I use the typed-decisions checkpoint?
When your questions resemble its four training workflows: customer service, invoice processing, security incidents or agent-trace observability. Pass model "typed-decisions" explicitly. It is never picked by automatic language routing, because it is specialised and should not be a silent default.
How many credits does a typed decision cost on Laya Studio?
It is billed in input tokens: 1 credit = 1 input token. Each question reads the state once, so a five-question request costs about five times the state's tokens, whichever checkpoint answers it. See /pricing for the 5 free runs.
What are the three types of typed questions?
choice picks one label from options you define, score places the input on an ordered scale, and noul gives the probability that a yes/no statement is true. One request can mix all three about the same text.
Do typed decisions stop AI hallucinations?
They remove format failures: the model cannot invent a label, a field or a sentence, because it only scores the options you listed. They do not stop wrong choices. A typed model can pick the wrong option with high probability, so measure accuracy and calibration on your data.

Sources

Last updated . Laya Studio is an independent hosted service for the open-source Laya model (Apache-2.0, © Convai Innovations) and is not affiliated with Convai Innovations or TypeSafe.