Jev
Last updated October 7, 2026
TypeSafeAI's decision model Jev — the three question types, answer shapes, confidence, and known weak spots.
Jev is TypeSafeAI's System One model: it does not generate text. Instead it answers a set of typed questions about the state you give it,
returning one structured answer per question that your code can branch on directly — nothing to parse.
It is served through the TypeSafeAI System One endpoint. The official SDKs
(typesafe-sdk, @typesafe-ai/sdk) work as-is — just point the base URL here.
Model
| Amux ID | typesafe/jev |
| Aliases | jev-latest (what the official SDKs send when no model is given) · jev-preview · jev-1.13.0 |
| Current version | jev-1.13.0 |
| Context | 64K tokens per request; state + the longest question ≤ 32K |
| Input | Text only: a string, a JSON object, or an array. Turn images, audio and video into text or structured fields first |
| Billing | Input tokens only; output is free. See the model page for the price |
| Streaming | Not supported |
https://gateway.amux.ai/v1/systemoneAuthorization
headerAuthorizationstringRequiredBearer <your Amux key> Your Amux API key.
Content-TypestringRequiredDefault "application/json"Always application/json.
Request
application/jsonmodelstringRequiredtypesafe/jev, or one of its aliases: jev-latest (the official SDKs' default), jev-preview, jev-1.13.0. Pin jev-1.13.0 if you have tuned confidence thresholds.
statestring | object | arrayRequiredThe content to evaluate: a string, or a JSON object/array (chat logs, records, application state). Prefer an object with descriptive field names, and refer to the fields from questions in backticks, e.g. ` message `. Text only — no images, audio or video.
questionsmap<string, Question>RequiredThe questions, keyed by an id you choose. Answers come back under the same ids. The ids are not sent to the model and do not affect inference. All questions are evaluated in parallel against the same state, so adding questions barely changes latency.
›questionsmap<string, Question>
‹question id›QuestionA typed question. Its type picks one of the three shapes below; all three share type and instructions, and each adds its own criteria.
›‹question id›Question
noulobjectA yes/no question. The answer is the probability (0–1) that the statement holds.
›noulobject
type"noul"RequiredAlways noul.
instructionsstring | object | arrayRequiredThe yes/no statement to evaluate. A string, or an object/array that puts the question in one field and the data it needs in others (refer to them by name in backticks).
criteriaobjectOptional. What a yes (near 1) and a no (near 0) mean. Put boundary cases here.
›criteriaobject
truestring | object | arrayWhat a yes means.
falsestring | object | arrayWhat a no means.
choiceobjectPicks exactly one option from a set you define. The answer carries the top option, a probability for every option, and a confidence.
›choiceobject
type"choice"RequiredAlways choice.
instructionsstring | object | arrayRequiredWhat the model should decide. String, object or array — see noul.
criteriaobjectRequiredOption name → rubric description. Use null when an option needs no detail. At most 255 options. The option names come back as keys of probabilities.
scoreobjectRates the state on an ordered rubric. The answer is a probability-weighted value that can land between two levels.
›scoreobject
type"score"RequiredAlways score.
instructionsstring | object | arrayRequiredWhat the model should rate. String, object or array — see noul.
criteriaarray<string>RequiredLevel descriptions, lowest first: index 0 is the bottom of the scale. At least 2, at most 10 levels.
Response
200responseOne answer per question, under the same ids.
400responseMalformed body; a question failed upstream validation (the message names the field); or the request is clearly over the context limits.
402responseInsufficient balance.
Three question types
Every question has type and instructions, plus a criteria whose shape depends on the type. You can mix them in one request;
all questions are evaluated in parallel and independently against the same state, so adding questions barely changes latency.
noul: yes / no
Answers with the probability that the statement holds: 0 is no, 1 is yes.
| Field | Type | Required | Notes |
|---|---|---|---|
type | "noul" | yes | |
instructions | string · object · array | yes | The statement to evaluate |
criteria | object | no | { "true": …, "false": … } — what a yes and a no each mean |
"is_urgent": {
"type": "noul",
"instructions": "Does this convey urgency?",
"criteria": { "true": "Explicitly time-sensitive", "false": "No urgency expressed" }
}choice: pick one
Picks exactly one of the options you define, with a probability for every option.
| Field | Type | Required | Notes |
|---|---|---|---|
type | "choice" | yes | |
instructions | string · object · array | yes | The decision to make |
criteria | map<string, string · object · array · null> | yes | Option name → rubric; use null for an option that needs no description. At most 255 |
"department": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "Payments, invoicing, refunds",
"technical": "Bugs, outages, integrations",
"sales": null
}
}score: ordered rating
Rates the state on levels ordered lowest first. The result is probability-weighted and can land between two levels.
| Field | Type | Required | Notes |
|---|---|---|---|
type | "score" | yes | |
instructions | string · object · array | yes | The dimension to rate |
criteria | array<string · object · array> | yes | Level descriptions, index 0 is the lowest. 2–10 levels |
"frustration": {
"type": "score",
"instructions": "How frustrated is the customer?",
"criteria": ["Calm", "Frustrated", "Very angry"]
}Structured instructions and criteria
instructions, choice option descriptions, score levels, and noul criteria all accept JSON.
Put the question in one field and the data it needs in others, and refer to those fields by name in backticks:
"instructions": {
"potential_duplicate": { "name": "John Smith", "location": "Oakland, California" },
"question": "Is the resume for the same person as `potential_duplicate`?"
}Fields in state are referenced the same way: send state as { "message": "…" } and write `message` in the question.
Answers
answers uses the same keys as questions, and every answer carries the same type as its question:
| type | Fields |
|---|---|
noul | noul: 0 (no) to 1 (yes) |
choice | choice: the most likely option; probabilities: option → probability, summing to 1; confidence |
score | score: the weighted value, possibly between levels; legend: level index → description; probabilities: level index → probability; confidence |
The response's model is the versioned ID that actually answered (for example jev-1.13.0), and we do not rewrite it —
aliases move with new releases, and logging it is how you know which release produced a batch of answers.
Confidence
Choice and score answers carry a confidence (0–1) derived from how concentrated the distribution is: all mass on one option is 1,
evenly spread is 0. Noul answers have no such field — the answer is already a probability.
A useful starting point is three bands: high — act automatically; medium — ask for confirmation or flag for review; low — don't act,
route to a human or a reasoning model. Gate destructive actions at a higher threshold than read-only ones. If you have tuned thresholds,
pin jev-1.13.0 and recalibrate on your own schedule when moving to a new version.
Known weak spots
Ask atomic questions and compose them in code. Jev 1.13 is unreliable in these situations:
| Situation | Ask it this way instead |
|---|---|
| Literal reading | State the exact condition; put boundary cases into criteria |
| Arithmetic, counting, numeric comparison | Keep arithmetic in code; ask one noul per item and sum |
| Date and time comparison | Extract the date parts with choices and compare in code |
| Indirection, double negatives | Ask directly; name the state field in backticks |
Large, noisy state | Filter first; send only what the question needs |
Adversarial content in state | Spell it out in criteria and test edge cases |
| Consistency across questions | Probabilities are not constrained across questions (P(yes) + P(not yes) need not be 1); don't reuse thresholds between noul and choice |
| Generation | Produce candidates with a generative model, then let Jev pick among them |
English works best. Other languages, Chinese included, work too, but test on your own data first and watch confidence more closely.
How the body is forwarded
Only model, state and questions reach the upstream. Every other top-level field is removed and listed in amux.droppedParams
and the x-amux-dropped-params header — the upstream rejects unknown top-level fields with an error that does not name them.
Fields inside a question are forwarded as-is.
Errors
Errors come back in OpenAI's error shape ({ "error": { "type", "message", … } }), which the official SDKs recognize.
| Status | type | When |
|---|---|---|
| 400 | invalid_request | A field is missing, or a question failed upstream validation — the message names the field, e.g. questions.q.choice.criteria: Field required |
| 400 | context_length_exceeded | Clearly over the context limits; rejected here |
| 402 | insufficient_credits | Insufficient balance |
| 502 | provider_* | The upstream rate-limited, was overloaded, or failed. Safe to retry |
For every type value and its retry semantics, see Errors and retries.
curl https://gateway.amux.ai/v1/systemone \
-H "Authorization: Bearer $AMUX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe/jev",
"state": {
"message": "Hi, my Stripe integration has been failing for 3 days. Please help ASAP."
},
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle `message`?",
"criteria": {
"billing": "Payment or subscription issues",
"technical": "Bugs or integration problems",
"sales": null
}
},
"frustration": {
"type": "score",
"instructions": "How frustrated does the customer appear?",
"criteria": [
"Calm",
"Frustrated but civil",
"Very angry"
]
},
"is_urgent": {
"type": "noul",
"instructions": "`message` conveys urgency or time-sensitivity"
}
}
}'{
"model": "jev-1.13.0",
"answers": {
"department": {
"type": "choice",
"choice": "technical",
"confidence": 0.95,
"probabilities": {
"billing": 0.03,
"sales": 0,
"technical": 0.97
}
},
"frustration": {
"type": "score",
"score": 1,
"confidence": 1,
"legend": {
"0": "Calm",
"1": "Frustrated but civil",
"2": "Very angry"
},
"probabilities": {
"0": 0,
"1": 1,
"2": 0
}
},
"is_urgent": {
"type": "noul",
"noul": 1
}
},
"usage": {
"input_tokens": 407,
"output_tokens": 73
}
}