Skip to main content

Decision Models

Probabilities, not text

A decision model reads some state and answers your typed questions with calibrated probabilities. Use it for routing, classification and yes/no gates inside an app, where a fast, structured answer matters more than prose.

Two decision models are served through the gateway, both on the /v1/systemone endpoint in the SystemOne format:

ModelMakerContextInputOutput
sage-2Levanto Labs32K$0.07 / 1M$2.00 / 1M
jev-1.13TypeSafe32K$0.042 / 1Mfree

They don't serve /v1/chat/completions or /v1/messages: sending one there returns a 400 that points to /v1/systemone. For the same reason, /v1/models/health shows them as unknown when they've had no calls in the last 15 minutes: idle models are checked with a chat probe, which a decision model can't answer, so that status doesn't mean an outage.

Asking a question​

POST /v1/systemone

Authentication is the same as every other gateway endpoint: a Bankr API key (bk_...) via X-API-Key or Authorization: Bearer.

curl -X POST https://llm.bankr.bot/v1/systemone \
-H "Content-Type: application/json" \
-H "X-API-Key: bk_YOUR_API_KEY" \
-d '{
"model": "sage-2",
"state": "User: please swap 1 ETH to USDC on Base",
"questions": {
"is_trade": {
"type": "noul",
"instructions": "Is the user asking to make a trade?"
},
"chain": {
"type": "choice",
"instructions": "Which chain does the user want to trade on?",
"criteria": { "base": "Base", "ethereum": "Ethereum mainnet", "solana": "Solana" }
}
}
}'

Request​

FieldDescription
modelRequired. sage-2 or jev-1.13.
stateRequired. What the questions are about: a string, or a JSON object.
questionsRequired. An object of at least one question, keyed by an ID you choose.

Apart from the privacy fields and "stream": false, any other field is rejected with 400 unsupported_parameter. Streaming is not supported.

Every question has a type and instructions. The three types:

TypeAskscriteria
noulA yes/no questionNone
choicePick one optionRequired. An object of option ID to description
scoreWhere it sits on a scaleRequired. A list of scale labels, from the lowest to the highest

Response​

{
"id": "dec-k5lcsV1k57JzQ2qjXrDUL",
"model": "sage-2",
"answers": {
"is_trade": { "type": "noul", "noul": 0.991 },
"chain": {
"type": "choice",
"choice": "base",
"confidence": 0.9997,
"probabilities": { "base": 0.9997, "ethereum": 0.0002, "solana": 0.00005 }
}
},
"usage": { "input_tokens": 127, "output_tokens": 0 }
}

Each answer carries its question's type:

  • noul: noul is the probability that the answer is yes.
  • choice: choice is the most likely option, with its confidence and the probabilities of every option.
  • score: score runs from 0 (the first label) to 1 (the last), with probabilities per label (by position) and a legend mapping each position to its label.

Privacy​

Decision models are served without TEE attestation, so a private request ("privacy": "private", "private": true, sage-2:private or the /private path) returns 422 confidential_unavailable.

Zero data retention depends on the model:

  • jev-1.13 takes a ZDR request ("privacy": "zdr", "zdr": true, jev-1.13:zdr or the /zdr path), which only reaches a provider that retains nothing. Accounts with zero data retention turned on can call it too.
  • sage-2 has no zero-retention route, so a ZDR request returns 422 zdr_unavailable, and so does every Sage call from an account with zero data retention turned on.

See Privacy Tiers for how the tiers work on chat models.

Error responses​

StatusCodeMeaning
400missing_required_fieldsmodel or state is missing.
400invalid_valuequestions is missing, empty or not an object.
400unsupported_parameterThe body has a field other than the ones above.
400stream_not_supportedstream was set to anything but false.
400unsupported_modelThe model is unknown or not a decision model.
400invalid_privacyA privacy field has a value it doesn't take.
400privacy_conflictThe request asks for a tier the path doesn't.
422confidential_unavailable / zdr_unavailablePrivate tier, or ZDR with no zero-retention hosts.

A malformed question (for example a choice with no criteria) is rejected by the model's host with a 4xx, whose message usually names the field.

Pricing​

Each call bills its input_tokens and output_tokens at the model's rates from your LLM credit balance, and shows on your usage dashboard. A short request costs a fraction of a cent: the 127-token call above costs about $0.00001 on Sage. See credit management to top up.

Next steps​