Jev — a decision model
MarkdownTypeSafe's Jev decision model answers typed questions about text or JSON: choosing an option, rating on a scale, or answering “yes/no” with probabilities. It is not a chat or text generation model.
Full guide
https://api.ailoot.ai/v1/systemonecurl https://api.ailoot.ai/v1/systemone \
-H "Authorization: Bearer $AILOOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "jev-latest",
"state": "Help! My payouts have been failing for 3 days.",
"questions": {
"is_urgent": {
"type": "noul",
"instructions": "Does this convey urgency?"
}
}
}' import json, os, urllib.request
body = {
"model": "jev-latest",
"state": "Help! My payouts have been failing for 3 days.",
"questions": {
"is_urgent": {"type": "noul", "instructions": "Does this convey urgency?"},
},
}
req = urllib.request.Request(
"https://api.ailoot.ai/v1/systemone",
data=json.dumps(body).encode(),
headers={"Authorization": "Bearer " + os.environ["AILOOT_API_KEY"],
"Content-Type": "application/json"},
)
with urllib.request.urlopen(req, timeout=60) as resp:
result = json.load(resp)
print(result["answers"]["is_urgent"]["noul"]) # 0.95const resp = await fetch("https://api.ailoot.ai/v1/systemone", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AILOOT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "jev-latest",
state: "Help! My payouts have been failing for 3 days.",
questions: {
is_urgent: { type: "noul", instructions: "Does this convey urgency?" },
},
}),
});
const result = await resp.json();
if (!resp.ok) throw new Error(`${resp.status} ${JSON.stringify(result)}`);
console.log(result.answers.is_urgent.noul); // 0.95{
"model": "jev-1.13.0",
"answers": {
"is_urgent": {
"type": "noul",
"noul": 0.95
}
},
"usage": { "input_tokens": 296, "output_tokens": 20 }
}Jev is a System One decision model from TypeSafe. It does not generate text or hold a conversation: you provide a state (state) — text or JSON — and a set of questions, and receive typed values with probabilities in response. Your code can use them directly to branch, sort, and route, without parsing free-form text.
All questions in a request are evaluated in parallel and independently against the same state. According to TypeSafe, adding questions has almost no effect on response time, and the questions do not interfere with one another.
| Item | In brief |
|---|---|
| Model | jev-latest — an alias for the latest stable version of Jev; catalog entry |
| Method | POST /v1/systemone. This is not a chat endpoint: OpenAI, Anthropic, and Gemini formats are not compatible with Jev. The complete response arrives as a single JSON object |
| Accepted input | Text only: a string, a JSON object, or an array of texts. Convert images, audio, and video to text first |
| Context | 64K tokens per request for state and all questions combined; state plus the longest question can contain up to 32K |
| Language | According to TypeSafe, the model is most accurate in English. It accepts other languages with lower accuracy, so test it on your own data |
| Price | Input: $0.084 per 1 million tokens; output is free |
Request
Authentication
- Authorizationheaderrequired
Your Ailoot key in the format
Bearer sk-….
Request body
- modelstringrequired
jev-latest. - statestring | object | arrayrequired
What to evaluate: a text string or JSON containing a customer inquiry, a database record, a conversation, or your application's current state. An object with clear field names is usually easier to work with than a single string.
- questionsobjectrequired
The questions. You choose the keys, and answers are returned under the same keys. The key does not affect the answer; the question itself is specified in
instructions. - questions.*.typestringrequired
noul,choiceorscore— see below. - questions.*.instructionsstring | object | arrayrequired
The question itself. You can pass a long question with supporting data as an object: put the question in one field and the data in others, and refer to fields by name in backticks.
- questions.*.criteriaobject | array
Answer options, defined differently for each type: optional descriptions of “yes” and “no” for noul, a dictionary of options for choice, and an ordered list of levels for score.
Question types
| Type | What it asks | What it returns |
|---|---|---|
noul | Whether a statement is true: yes or no | noul — the probability of “yes,” from 0 to 1 |
choice | Which of the supplied options fits | choice, probabilities, confidence |
score | Where state falls on your scale of levels | score, legend, probabilities, confidence |
You can combine question types in a single request.
noul — yes or no
The field criteria is optional: you can use it to describe what “yes” (true) and “no” (false) mean. The answer noul — a number from 0 (no) to 1 (yes).
"is_urgent": {
"type": "noul",
"instructions": "Does this convey urgency?",
"criteria": {
"true": "Explicitly time-sensitive",
"false": "No urgency expressed"
}
}"is_urgent": {
"type": "noul",
"noul": 0.95
}choice — selecting an option
criteria — an “option → description” dictionary; if no description is needed, use null. Up to 255 options. In the response, choice — the most likely option, probabilities — the probability of each option (summing to 1), confidence — confidence from 0 to 1.
"department": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "Payments, invoicing, refunds",
"technical": "Bugs, outages, integrations",
"sales": "Pricing, upgrades, new customers"
}
}"department": {
"type": "choice",
"choice": "billing",
"probabilities": { "billing": 0.88, "technical": 0.12, "sales": 0.0 },
"confidence": 0.81
}score — rating on a scale
criteria — levels ordered from lowest to highest, with no more than 10 (TypeSafe recommends at least two). In the response, score — a value weighted by the probabilities of the levels (it can fall between levels), legend — the level number and its description, probabilities and confidence. According to TypeSafe, score is suitable for comparison against a threshold, but not for deriving an exact number between levels.
"frustration": {
"type": "score",
"instructions": "How frustrated is the customer?",
"criteria": ["Calm", "Frustrated", "Very angry"]
}"frustration": {
"type": "score",
"score": 1.05,
"legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" },
"probabilities": { "0": 0.0, "1": 0.95, "2": 0.05 },
"confidence": 0.92
}Response
- modelstring
The model version that answered. The jev-latest alias moves to newer versions over time. If you have calibrated
confidencethresholds for a specific version, monitor this field. - answersobject
One answer per question, under the same keys. Every answer has
type, and choice and score also haveconfidence. - usageobject
input_tokensandoutput_tokens. Only input tokens are charged.
Multiple questions in one request
Submit all questions about the same state in one request: they are evaluated in parallel, and state is sent only once. According to TypeSafe, in their example with 13 questions, one combined request cost less by a factor of 12.2 and was 10 times faster than 13 separate requests sent sequentially, with the same answers.
Break a complex judgment into simple questions and combine the answers in code. For example, instead of “evaluate this application,” ask separately about the market, feasibility, and differences from competitors. You can then adjust the weights in code rather than in the question text.
{
"model": "jev-latest",
"state": "Help! My payouts have been failing for 3 days.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "Payments, invoicing, refunds",
"technical": "Bugs, outages, integrations",
"sales": "Pricing, upgrades, new customers"
}
},
"frustration": {
"type": "score",
"instructions": "How frustrated is the customer?",
"criteria": ["Calm", "Frustrated", "Very angry"]
},
"is_urgent": {
"type": "noul",
"instructions": "Does this convey urgency?"
}
}
}When to use it
- Routing. Send an inquiry to the right department or a request to the right handler: simple code, a large model, or a human.
- Sorting and prioritization. Rate urgency, sentiment, and risk on a scale, with thresholds defined in code.
- Moderation and checks. Check whether a message violates the rules, a source supports a quotation, or a document contains an answer to a question before passing the text on.
- Scoring and ranking. Evaluate documents, candidates, or retrieved passages against your own rubric, and decide in code what moves forward.
- Replacing fragile “return JSON” prompts. A call that returns typed values by design, rather than text you need to parse.
When not to use it
- Chat, replies to users, and text or code generation. Jev does not generate text; for that, use text models.
- A model for Claude Code, Cursor, and other agents. You cannot replace an agent's model with jev-latest: the agent needs a model that generates text and calls tools. You can call Jev from code the agent writes for you.
- Arithmetic, counting, and date comparisons. According to TypeSafe, these operations are more reliable in code. Ask the model only for the semantic part—for example, extracting date components using choice.
- Images, audio, and video. The model accepts only text; convert these inputs to text beforehand.
Price
Only input tokens are charged, as reported in the usage.input_tokens field of the response: $0.084 per 1 million. Output tokens are free.
The example request on this page (296 input tokens) costs less than $0.0001.
Before the request, Ailoot places a reserve on your balance and, after the response, charges you once based on actual usage — how it works.
Limits
| Item | Limit |
|---|---|
| Entire request: state and all questions | 64K tokens |
| state together with the longest question | 32K tokens |
| Options in a single choice | up to 255 |
| Levels in a single score | from 2 to 10 |
| Input | text only: a string, a JSON object, or an array of texts |
Model limits are provided by TypeSafe. Your key and balance limits apply as they do for any Ailoot model: Errors and limits.
Errors
Errors use the standard Ailoot API format: a code, a clear message, and a Request ID. The most common errors for this method are:
| Code | When it occurs | What to do |
|---|---|---|
400 invalid_request | The body failed validation: state, model, or questions is missing; type is unknown; choice has more than 255 options; or score has more than 10 levels | Correct the request as described in the error message. It will fail again without a correction. |
400 context_length_exceeded | state and the questions together exceed the model limit | Filter state in your code and keep only what the questions need |
401 invalid_api_key | The key is missing or invalid | Send the key in the Authorization header |
402 insufficient_balance | There is not enough available balance for the reserve | Add funds to your balance |
404 model_not_found, unsupported_endpoint | The ID is incorrect or the model was called through the wrong method, such as /v1/chat/completions | Call jev-latest only through POST /v1/systemone |
429 rate_limit_exceeded | Too many requests | Wait for the number of seconds specified in Retry-After, then retry |
503 model_overloaded, model_unavailable | The model is temporarily overloaded or unavailable | If X-Should-Retry: true, retry after the number of seconds in Retry-After; if false, check the Request ID in your history first |
504 model_timeout | The model did not respond in time | Do not send the request again until you have checked its Request ID in your history |
For the full list of codes, see Errors and limits.