Skip to main content

Branch on probabilities

Use a probability threshold when the next part of an answer depends on how strongly Struct favors a decision. For example, route a reported duplicate charge for automatic handling only when the probability assigned to true reaches your threshold; otherwise request review.

The runtime tests the measured candidate distribution and applies the corresponding schema branch. You do not ask the model to generate a confidence number or send a second request to choose the branch. The answer names a route; your application decides what action to take.

Route above a threshold​

This schema asks whether a charge was duplicated. P(...) denotes probability, so P(duplicate = true) means the probability Struct assigns to true for the duplicate field. It returns route: "automatic" when that probability is at least 0.95, and route: "review" otherwise. No state or policy is required.

Save the schema beside your client:

probability-routing.schema.json
{
"type": "object",
"properties": {
"duplicate": {
"type": "boolean",
"description": "True only when the input explicitly reports being charged more than once for the same purchase; otherwise false.",
"x-runtime": {
"probabilities": true
}
},
"route": {
"enum": [
"automatic",
"review"
]
}
},
"required": [
"duplicate",
"route"
],
"additionalProperties": false,
"if": {
"x-runtime": {
"probability": {
"path": "/duplicate",
"minimum": 0.95,
"value": true
}
}
},
"then": {
"properties": {
"route": {
"const": "automatic"
}
}
},
"else": {
"properties": {
"route": {
"const": "review"
}
}
}
}
Before you run this example

Call https://api.blatent.ai from your server. Set your API key in the same terminal where you run the example:

export BLATENT_API_KEY='YOUR_SERVICE_KEY'

Python requires Python 3.10+ and HTTPX:

python -m pip install "httpx>=0.28,<1"

TypeScript requires Node.js 24+ and uses its built-in fetch. The cURL examples require curl and jq.

Save the displayed files and the selected client in one directory. Run the client there with python example.py, node example.ts or bash example.sh. Downloads use the example's name in place of example.

import json
import os
from pathlib import Path
import httpx

request = {
"input": "The customer was charged twice for the same purchase. The duplicate charge is confirmed.",
"schema": json.loads(Path("probability-routing.schema.json").read_text(encoding="utf-8")),
}
with httpx.Client(
base_url="https://api.blatent.ai",
headers={"Authorization": f"Bearer {os.environ['BLATENT_API_KEY']}"},
timeout=195,
) as client:
response = client.post("/v1/resolve", json=request)
response.raise_for_status()
print(json.dumps(response.json()["output"]))

Illustrative output: {"duplicate":true,"route":"automatic"}. The full response also includes the distribution at probabilities["/duplicate"]. Python and TypeScript print output; cURL prints the full response.

Two annotations work together:

AnnotationWhere it belongsWhat it does
"probabilities": trueInside x-runtime on the decision field's schemaCollect the distribution over that field's candidates
"probability": {...}Inside the if schema's x-runtimeCompare a probability with your threshold

The plural probabilities enables measurement. The singular probability refers to that measurement. then and else are ordinary JSON Schema branches: both add constraints to the surrounding schema. Declare the route and its allowed values in the surrounding object first.

Select the probability to test​

PartMeaning
path: "/duplicate"The output field whose distribution is measured; not a path into the schema
value: trueThe particular candidate whose probability to test
minimum: 0.95Require a probability of at least 95%

For a categorical field, the same rule can name a candidate such as value: "billing". Preserve its JSON type: Boolean true and the string "true" are different candidates.

If you omit value, the rule tests the probability of whichever answer Struct selected. This is useful for deciding whether to accept a classification or ask for review, regardless of which category won. It is different from requiring a particular answer:

RuleWhen the selected answer is false with probability 99%
Test value: true against 95%Does not pass: P(true) is 1%
Omit value and test against 95%Passes: the selected false has probability 99%

For approval-like rules, name the approving candidate explicitly. If your rule requires both a selected value and a probability threshold, put the ordinary properties and required tests alongside x-runtime inside if; both conditions must hold.

The direct if.x-runtime.probability.path addresses the output from its root. For example, /assessment/duplicate refers to a field inside assessment. The decision field and its parent objects must be required in the supported object form.

Inclusive and strict thresholds​

Thresholds are numbers between 0 and 1. Use the comparison that matches your rule:

Inside if.x-runtime.probabilityMeaningSwitch comparison
minimumAt least the thresholdgte
exclusiveMinimumStrictly above itgt
maximumAt most the thresholdlte
exclusiveMaximumStrictly below itlt

You can supply lower and upper bounds together. An invalid threshold or a reference to an unmeasured field is rejected; it is not treated as a low-probability answer.

Choose among several tiers​

A switch can select a probability through on.probability instead of selecting an output value through on.path. This example tests the same named candidate at two thresholds:

Probability assigned to duplicate = trueRoute
At least 95%automatic
At least 50%, but below 95%review
Below 50%decline
probability-switch.schema.json
{
"type": "object",
"properties": {
"duplicate": {
"type": "boolean",
"description": "True only when the input explicitly reports being charged more than once for the same purchase; otherwise false.",
"x-runtime": {
"probabilities": true
}
},
"route": {
"enum": [
"automatic",
"review",
"decline"
]
}
},
"required": [
"duplicate",
"route"
],
"additionalProperties": false,
"x-runtime": {
"switch": {
"on": {
"probability": {
"path": "/duplicate",
"value": true
}
},
"cases": [
{
"when": {
"gte": 0.95
},
"then": {
"properties": {
"route": {
"const": "automatic"
}
}
}
},
{
"when": {
"gte": 0.5
},
"then": {
"properties": {
"route": {
"const": "review"
}
}
}
}
],
"default": {
"properties": {
"route": {
"const": "decline"
}
}
}
}
}
}
Before you run this example

Call https://api.blatent.ai from your server. Set your API key in the same terminal where you run the example:

export BLATENT_API_KEY='YOUR_SERVICE_KEY'

Python requires Python 3.10+ and HTTPX:

python -m pip install "httpx>=0.28,<1"

TypeScript requires Node.js 24+ and uses its built-in fetch. The cURL examples require curl and jq.

Save the displayed files and the selected client in one directory. Run the client there with python example.py, node example.ts or bash example.sh. Downloads use the example's name in place of example.

import json
import os
from pathlib import Path
import httpx

request = {
"input": "The customer was charged twice for the same purchase. The duplicate charge is confirmed.",
"schema": json.loads(Path("probability-switch.schema.json").read_text(encoding="utf-8")),
}
with httpx.Client(
base_url="https://api.blatent.ai",
headers={"Authorization": f"Bearer {os.environ['BLATENT_API_KEY']}"},
timeout=195,
) as client:
response = client.post("/v1/resolve", json=request)
response.raise_for_status()
print(json.dumps(response.json()["output"]))

Cases are checked in order. Put the highest threshold first because the first match wins; the explicit default handles all remaining probabilities. As with value switches, branches constrain the answer and do not execute the named action.

For switch.on.probability, path is relative to the output object containing the switch. A switch inside assessment therefore uses /duplicate for its own field, rather than /assessment/duplicate.

Apply a threshold to each supplied item​

Use a switch inside a for-each loop to assess each item independently. This example answers two product checks and marks each answer for automatic handling or review. Here value is deliberately omitted: a confident false is just as useful as a confident true.

probability-checks.schema.json
{
"$schema": "urn:blatent:json-schema:template-draft-v1",
"type": "array",
"maxItems": 4,
"x-runtime": {
"forEach": {
"ref": "state/checks",
"as": "check"
}
},
"items": {
"type": "object",
"properties": {
"route": {
"enum": [
"automatic",
"review"
]
},
"id": {
"x-runtime": {
"bind": {
"const": {
"ref": "check/id"
}
}
}
},
"answer": {
"type": "boolean",
"x-runtime": {
"probabilities": true,
"bind": {
"description": {
"ref": "check/description"
}
}
}
}
},
"required": [
"id",
"answer",
"route"
],
"additionalProperties": false,
"x-runtime": {
"switch": {
"on": {
"probability": {
"path": "/answer"
}
},
"cases": [
{
"when": {
"gte": 0.95
},
"then": {
"properties": {
"route": {
"const": "automatic"
}
}
}
}
],
"default": {
"properties": {
"route": {
"const": "review"
}
}
}
}
}
}
}
probability-checks.state.json
{
"checks": [
{
"id": "waterproof",
"description": "True if the product is waterproof; false otherwise."
},
{
"id": "hooded",
"description": "True if the product has a hood; false otherwise."
}
]
}
Before you run this example

Call https://api.blatent.ai from your server. Set your API key in the same terminal where you run the example:

export BLATENT_API_KEY='YOUR_SERVICE_KEY'

Python requires Python 3.10+ and HTTPX:

python -m pip install "httpx>=0.28,<1"

TypeScript requires Node.js 24+ and uses its built-in fetch. The cURL examples require curl and jq.

Save the displayed files and the selected client in one directory. Run the client there with python example.py, node example.ts or bash example.sh. Downloads use the example's name in place of example.

import json
import os
from pathlib import Path
import httpx

request = {
"input": "A lightweight waterproof jacket with no hood.",
"schema": json.loads(Path("probability-checks.schema.json").read_text(encoding="utf-8")),
"state": json.loads(Path("probability-checks.state.json").read_text(encoding="utf-8")),
}
with httpx.Client(
base_url="https://api.blatent.ai",
headers={"Authorization": f"Bearer {os.environ['BLATENT_API_KEY']}"},
timeout=195,
) as client:
response = client.post("/v1/resolve", json=request)
response.raise_for_status()
print(json.dumps(response.json()["output"]))

The template dialect expands the supplied checks before generation. Each result keeps its bound id, generates an answer, and applies its own 95% threshold to choose route. The local switch uses /answer for every item. Returned distributions use full output paths such as /0/answer and /1/answer; each route uses its corresponding item's distribution.

The list supplies the checks and their descriptions. It does not supply or invent the probabilities. Changing the list preserves the same template and reference rules.

Choose and evaluate your threshold​

These are normalized preferences among the allowed candidates, not calibrated probabilities that an answer is correct. A 95% threshold is an example, not a recommended value for every task. Evaluate accuracy, review rate and failures on representative inputs, including confident mistakes.

Collecting a complete distribution can add inference work compared with choosing only an answer. Reuse a measured field for related routing rules, and measure latency with your actual candidates and branches. A threshold does not replace permission checks or trusted application facts.

Use candidate probabilities when you only need to inspect the distribution, output conditions for rules based on generated values, and state conditions for rules based on supplied facts. These downloadable examples use required Boolean decisions and finite routes. Other combinations still need to fit the service's supported schema forms.