Decision Models API: Typed Answers With Probabilities
POST /api/alpha/decide takes state plus typed boolean, choice, and score questions and returns verified answers with probabilities. Use trev-1.0, Jev, or any chat model through the attested TrustedRouter gateway.
Ask your software a question. Get a typed answer with a probability.
Most calls to a language model inside an application are not conversations. They are decisions: is this a refund request, which queue does it go to, how urgent is it, did the agent finish, should it retry. Asking a chat model for prose and then parsing it is slow, expensive, and fragile.
POST /api/alpha/decide takes a piece of state and a set of typed questions, and returns one typed answer per question, each with probabilities you can threshold on. All questions are answered in a single call.
Every answer is verified against your request before it is returned. You never receive an option you did not declare, a probability outside 0 to 1, or a distribution that does not add up.
curl https://api.trustedrouter.com/api/alpha/decide \
-H "Authorization: Bearer $TRUSTEDROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "trustedrouter/trev-1.0",
"state": "I was charged twice for order A-1 and need this fixed today.",
"questions": {
"refund": {
"type": "boolean",
"instructions": "Is the customer asking for money back?"
},
"route": {
"type": "choice",
"instructions": "Route this support ticket.",
"criteria": {
"billing": "payment or charge problems",
"shipping": "delivery problems",
"technical": "application bugs"
}
},
"urgency": {
"type": "score",
"instructions": "How urgent is this ticket?",
"criteria": ["low", "medium", "high"]
}
}
}'
One answer per question, keyed by the names you chose.
A boolean returns the probability that the answer is yes. A choice returns the selected option and a probability for every option you declared. A score returns a probability for each level and the expected level as a single number, so 1.8 on a three-level scale sits between medium and high.
Automate the confident cases and send the uncertain ones to a person: if answers.refund.probability > 0.9.
trustedrouter.routing tells you which model and provider actually served the decision, the same way a chat completion does. trev-1.0 is a private configuration, so it names the gateway itself and omits the host it chose, while the counts still show how many hosts it could have used and how many it tried. A model whose configuration is not private names the vendor that ran it, with the endpoint it used. A field the gateway cannot establish is absent rather than guessed.
{
"model": "trustedrouter/trev-1.0",
"answers": {
"refund": { "type": "boolean", "probability": 0.97 },
"route": { "type": "choice", "choice": "billing",
"probabilities": { "billing": 0.96,
"shipping": 0.02,
"technical": 0.02 } },
"urgency": { "type": "score", "score": 1.8,
"probabilities": { "0": 0.0, "1": 0.2, "2": 0.8 } }
},
"usage": { "inputTokens": 519, "outputTokens": 229 },
"trustedrouter": {
"routing": {
"selected_model": "trustedrouter/trev-1.0",
"selected_provider": "trustedrouter",
"fallback_candidate_count": 4,
"upstream_attempt_count": 1,
"fallback_attempt_count": 0
}
}
}
Question types
Yes or no, with a probability.
instructions is required. criteria is optional: an object with "true" and/or "false" describing what each side means.
Returns probability, the chance the answer is yes.
Pick one of your options.
criteria is required: an object mapping each option name to a description. Between 2 and 255 options.
Returns choice and probabilities for every option. The choice is always the most probable option.
Rate along an ordered scale.
criteria is required: an array of 2 to 10 level labels, lowest first.
Returns probabilities keyed "0" to "n-1", and score, their expected value. The gateway computes it from the probabilities it returns, so the two always agree.
Models
Nine names, one APIEvery model below takes the same request and returns the same response, so switching is changing one string. A decision usually sits in the middle of a request, so speed comes first: four of these answer in about a third of a second, and a fifth in about half. Start with trustedrouter/trev-1.0: it is among the fastest, it reasons briefly before it answers, and it fails over across four hosts.
| Model | Pick it for | Median model latency | Eval accuracy | About one decision costs |
|---|---|---|---|---|
| typesafe-ai/jev | A purpose-built decision model from TypeSafe AI, called at TypeSafe's own API with automatic failover to Vercel AI Gateway. | about 250 ms | 29 / 29 | $0.00002 |
| trustedrouter/trev-1.0 | The default. An open-weight 120B reasoning model on the fastest hardware we could measure, with automatic failover across four hosts. | about 300 ms | 29 / 29 | $0.00034 |
| trustedrouter/mev-1.0 | Speed at half the price. Mercury 2, a diffusion model, answering without deliberating. It over-rates the urgency of one eval ticket; pass reasoning_effort: "low" for 29 / 29 at about 600 ms. | about 290 ms | 28 / 29 | $0.00017 |
| trustedrouter/lev-1.0 | The steadiest tail. Llama 3.3 70B does not deliberate, so its slowest answer in the eval took 565 ms. Fails over across three hosts. | about 390 ms | 29 / 29 | $0.00036 |
| trustedrouter/zev-1.0 | A larger fast model. GLM 5.2 Fast, with failover to a second host. About four times the price of the others here. | about 0.5 s (0.35 to 0.7 s) | 29 / 29 | $0.0014 |
| trustedrouter/gev-1.0 | A Google model. Small, from the Gemini family, with the format enforced by the host. | about 0.8 s | 29 / 29 | $0.00023 |
| trustedrouter/dev-1.0 | Harder judgments on a budget. A DeepSeek flash model: strong judgment, cheap input. | about 1 s (0.7 to 2.4 s) | 29 / 29 | $0.00013 |
| trustedrouter/oev-1.0 | A cheap all-rounder. An open-weight 20B model that reasons briefly. | about 1.6 s | 29 / 29 | $0.00004 |
| trustedrouter/gemmev-1.0 | The lowest price. A small open Gemma model. | about 2 s | 29 / 29 | $0.00002 |
What a name is. A trustedrouter/ name is one tuned configuration: a model, the hosts it was measured on, its reasoning setting and its output format. It runs only on its own hosts, so the speed and price above are what you get, and it answers the decide route only. Improvements ship as a new version (trev-1.1) rather than by changing a name you have pinned.
Prefer a plain model id? The same tuning applies when you name one of these chat models directly, and any other chat model in the catalog, such as anthropic/claude-opus-5, works too, untuned. Larger models do better on harder judgments.
| Tuned chat model | Runs on |
|---|---|
| inception/mercury-2 | Inception |
| meta-llama/llama-3.3-70b-instruct | SambaNova, then Parasail, then Together |
| z-ai/glm-5.2-fast | Fireworks, then Baseten |
| google/gemini-3.1-flash-lite | Google AI Studio |
| deepseek/deepseek-v4.1-flash | DeepInfra |
| openai/gpt-oss-20b | DeepInfra |
| google/gemma-4-e4b-it | DeepInfra |
How to read this. The eval is small and deliberately easy: eight labeled support tickets, four questions each, 29 checks, run in September 2026. It shows that every model here answers clear cases correctly in the right form; it does not rank them on hard ones, and across repeated runs one borderline ticket occasionally costs a model a single check. Latency is the typical median time for the model host to answer, measured from one client over repeated runs; hosts vary from run to run, and your request also pays for authorization and settlement through the gateway. Cost is for that four-question request, about 410 to 480 input tokens, at list price. Live per-token prices are always in GET /v1/models.
Turn reasoning on. The output does not change.
By default a decision model answers without deliberating, which is what makes it fast. For a judgment that needs thought, pass reasoning (true, or {"effort": "low" | "medium" | "high"}) or reasoning_effort, and the model thinks first. You still get exactly the same typed answers, verified the same way.
provider accepts the same routing preferences as chat, so you can move a tuned model to a cheaper or regional host. max_tokens raises the budget if a long deliberation is being cut short.
These three options apply to chat-model-backed decisions. typesafe-ai/jev has no reasoning to turn on and rejects them with a clear 400 rather than ignoring them. A trustedrouter/ name always runs on its own hosts.
{
"model": "deepseek/deepseek-v4.1-flash",
"reasoning": { "effort": "high" },
"provider": { "only": ["deepinfra"] },
"state": { "diff": "...", "tests": "12 passed, 1 failed" },
"questions": {
"safe_to_merge": {
"type": "boolean",
"instructions": "Is this change safe to merge as is?",
"criteria": {
"true": "no failing tests, no behavior change outside the diff's stated purpose",
"false": "any failing test or unexplained behavior change"
}
}
}
}
What "verified" means
No special model support needed.
The gateway shows the model the exact JSON shape to fill in, and adds a strict JSON schema where the model's host can enforce one. That is why models with no structured-output support, such as Gemma 4 E4B, still work.
Never the answer.
Code fences, surrounding prose, percentages, and an option written by name are normalized. A missing question, a word where a number belongs, an option you did not declare, probabilities far from summing to one, or two answers in one reply are not repaired: the gateway never chooses for the model.
The same check for every model.
Exactly one answer per question, of the right type. Every probability between 0 and 1. Every declared option present, none invented, mass summing to one. The choice is the most probable option; the score is the distribution's mean. Hosted models are checked exactly as chat models are.
If a chat model's answer fails the second pass, the gateway asks once more. If that also fails you receive a 502, never a guess. Both attempts consumed tokens at the model host and both are billed.
The same contract as Vercel's evaluate endpoint and OpenRouter's Decisions API.
The route is POST /api/alpha/decide: alpha because the contract may still change, decide because that is what it does. It also answers, identically, to the paths other gateways use for the same model, state, questions request, so a client written for one of them needs only its host, key and model id changed:
POST /api/decide— the same name, for when it leaves alphaPOST /v1/decide— where this route was first publishedPOST /v1/evaluate— Vercel AI Gateway and the AI SDKPOST /api/alpha/decisions— OpenRouter's Decisions APIPOST /api/decisions— the same, for when it leaves alpha
Coming from OpenRouter or TypeSafe? They call the yes/no question noul. Send "type": "noul" and the answer comes back the way they return it, {"type": "noul", "noul": 0.97}; send "type": "boolean" and you get {"type": "boolean", "probability": 0.97}. It is the same question either way, and you can mix them in one request. Their typesafe/jev-1.13 is typesafe-ai/jev here.
state may be a string, an object, or an array, so you can pass a record or a message history without serializing it yourself.
import httpx, os
r = httpx.post(
"https://api.trustedrouter.com/api/alpha/decide",
headers={"Authorization": f"Bearer {os.environ['TRUSTEDROUTER_API_KEY']}"},
json={
"model": "trustedrouter/trev-1.0",
"state": ticket_text,
"questions": {
"route": {
"type": "choice",
"instructions": "Route this support ticket.",
"criteria": {
"billing": "payment or charge problems",
"shipping": "delivery problems",
"technical": "application bugs",
},
},
},
},
timeout=30,
)
route = r.json()["answers"]["route"]
if route["probabilities"][route["choice"]] > 0.9:
assign(route["choice"])
else:
send_to_human()
Billing, privacy, limits
Tokens, like everything else.
typesafe-ai/jev bills input tokens only; its output is free. Chat-model-backed decisions bill the input and output tokens of the underlying call at the rate of the host that served it. A trustedrouter/ name lists the rate of its most expensive host; a request served by a cheaper fallback host costs less.
Your state never reaches our control plane.
As with chat, state and questions terminate inside the attested gateway and go only to the model host. Authorization and billing see token counts, not content. typesafe-ai/jev is called at TypeSafe's own API. Only if TypeSafe is down or rate limiting does the request fail over to Vercel AI Gateway, and only then does it cross two third parties.
Sized for real applications.
Up to 64 questions per request, 255 options per choice and 10 levels per score: the same limits on every model, so a request written for one runs on any other. Question and option names up to 128 characters, with no control characters. No streaming: a decision is one small JSON object. typesafe-ai/jev accepts about 32,000 tokens of state.
Errors
| Status | Meaning |
|---|---|
| 400 | The request is malformed. error.param names the field, for example questions.route.criteria. Also returned when a decision model is named on a chat endpoint, or when the hosted model itself rejects the request, for example as too long. |
| 401 / 402 | Invalid API key, or not enough credit. |
| 502 | The model host failed, or the model's answer failed verification twice. No unverified answer is ever returned. When a model had already run, the response carries x-should-retry: false: retrying would pay for it again. |
| 503 | Every host in a model's chain is unavailable. Retry shortly. |