System 1 and System 2 thinking, a practical support-ticket example, and where Jev could fit into AI agents.

At Algorisys Technologies most of our prouducts have LLM integration including our CRM called Propeak.app, our skills assessment platform at skillzengine.com and more.
We have a usecase for Jev. This article is for my team to remind them not to jump to the frontier LLM models for all task but to find out better alternatives. As we integrate Jev and other similar models we will record our learnings as well.
Suppose a customer sends this message:
“The payment went through, but our candidates cannot start their assessments. Interviews begin in 30 minutes.”
Before someone writes a reply, our application has a few decisions to make.
Is the customer reporting a blockage? Does the message indicate urgency? Which team should investigate?
We could send the message to a general-purpose LLM and ask it to analyse the situation. But at this stage, our application does not need a detailed explanation. It needs a few values that the rest of the software can act on.
This is where Jev becomes interesting.
Jev, from TypeSafe AI, is designed to evaluate supplied context and return structured decisions and probabilities, rather than generate an open-ended response. TypeSafe calls it a System One model.
To understand that name, let us first step away from software.
System 1 and System 2 thinking
Daniel Kahneman’s book, Thinking, Fast and Slow, gives us a useful starting point.
System 1 describes fast, intuitive thinking. System 2 describes slower, more deliberate thinking, where we consciously work through a problem. The book also explores the mistakes and biases that can accompany our intuitive judgments. Fast does not automatically mean correct.
Think of recognising a familiar face versus mentally calculating 27 × 43.
The first may happen almost immediately. The second usually requires some effort 🙂
Now, bring this intuition into an application.
Choosing which support queue should receive a message is a relatively narrow judgment. Investigating a complex production incident, comparing possible causes, and developing a recovery plan is a much broader task.
The System 1/System 2 analogy helps us notice this difference.
However, I would not turn it into a rigid classification where Jev equals System 1 and every LLM equals System 2. TypeSafe uses the name to emphasise fast, focused judgments. It is a product-design analogy, not evidence that the model reproduces human cognition.
The more useful engineering question is:
What kind of answer does this part of the application actually need?
Generating an answer versus evaluating a decision
An autoregressive language model generates a sequence by predicting the next token using the preceding context. That sequence might become a paragraph, source code, a plan, or a structured response.
Jev takes a different approach. According to TypeSafe, it evaluates the supplied questions in parallel instead of generating their answers token by token. The developer defines the permitted answer spaces in advance.
This gives us two different interfaces.
A generative request might be:
“Analyse this customer complaint and explain how we should handle it.”
A decision-oriented request might be:
“Which of these teams should investigate this complaint?”
Neither interface is universally better. They serve different purposes.
Also, structured output is not exclusive to Jev. Modern LLM APIs support schema-constrained output and structured tool calls. For example, Anthropic documents JSON output and strict tool-use capabilities. So the comparison should not be “Jev returns structured data, while LLMs can only return prose.”
The distinction worth evaluating is the combination of execution approach, decision quality, probabilities, latency, and cost for a particular workload.
For me, the appeal is straightforward: I can design a normal application and use a model only at the points where the software needs help interpreting meaning.
The interface: state, questions, answers
Jev’s interface starts with something TypeSafe calls state.
State is simply the material the model should evaluate. It could be a message, a document passage, or a JSON object containing relevant application information. You submit that state alongside one or more questions.
For our support application, the state might contain the customer’s message, the product involved, and selected account information retrieved by our backend.
That last part matters.
The customer saying “the payment went through” is not the same thing as our payment system confirming a settled transaction.
I would keep those facts separate:
Customer message:
"The payment went through."
Verified application record:
Payment status retrieved from the payment service.
The model can help interpret the message. It should not become the source of truth for a transaction our application can look up directly.
This is an important design habit: distinguish what someone reports from what the system has verified.
Three kinds of questions
Jev provides three question types: Choice, Noul, and Score. Each gives us a different way to define the answer we need.
Choice: select from a defined set
Use Choice when the answer should be one of several options.
For example:
Which team should investigate the main issue?
technical
billing
general
A Choice answer includes the selected option, a probability distribution across the options, and a confidence value. The option descriptions are part of the question, so they should explain what belongs in each category.
For our example, I would define technical support as handling application failures and assessment-access problems. Billing would handle disputed charges, failed payments, and refund requests.
The word “payment” appearing in the message should not, by itself, decide the queue.
We are classifying the problem that needs attention, not matching a keyword.
Noul: estimate the probability of a yes/no answer
Noul is TypeSafe’s name for a question whose answer is expressed as the estimated probability of “yes”.
For example:
“Does the message report that the customer is unable to complete a necessary task?”
A value close to 1 expresses a strong “yes”. A value close to 0 expresses a strong “no”. A value around 0.5 gives similar probability to both possibilities. Noul does not include the separate confidence field returned by Choice and Score.
Notice the wording: does the message report a blockage?
That is a more defensible question than asking the model to establish whether the entire service is down.
The first evaluates the supplied evidence. The second requires operational information we may not have provided.
Score: evaluate against ordered descriptions
Use Score when the answer lies along a spectrum with levels you can describe.
For a learning platform, I might define a rubric such as:
0: The explanation does not address the concept.
1: The explanation addresses the concept but misses
an important part.2: The explanation addresses the concept and includes
a relevant example.
Score returns a value along the supplied levels, together with the underlying probabilities and confidence. Its numerical range comes from the ordered rubric, not an arbitrary universal scale.
I would rather define these levels than ask:
“How good is this explanation?”
“Good” leaves too much of the evaluation unspecified. A rubric forces me to explain what I expect.
That work belongs to the person designing the application.
Let us build the support workflow
Before making any API call, I would define the responsibilities.
The application receives and stores the ticket. Jev supplies interpretation signals. Application code decides how to use those signals. A reviewer handles cases we are not ready to automate.
The proposed flow looks like this:
Customer message
↓
Backend retrieves relevant, verified context
↓
Jev evaluates the configured questions
↓
Application applies routing and escalation rules
↓
Suggested action or human review
↓
Record the outcome and any correction
This follows TypeSafe’s documented approach: keep the workflow and side effects in code, and give the model narrow questions rather than ownership of the whole process.
For the first version, I would make the result suggestion-only.
The operator sees the proposed team and the signals behind it. They can accept or correct the suggestion. No refund is issued, no account permission changes, and no ticket is silently closed.
That gives us a useful starting point without pretending we have already established production reliability.
A small JavaScript example
The official JavaScript SDK supports Node.js 20 and newer and reads TYPESAFE_API_KEY from the environment. Install it with the following command, then set the environment variable using your usual local or server secret configuration.
npm install @typesafe-ai/sdk
Save this example as triage.mjs. It follows the documented SDK interface and prints suggestions only; it is not a recorded benchmark or a demonstrated result.
import {
TypeSafeClient,
choice,
noul,
} from "@typesafe-ai/sdk";
async function main() {
const client = new TypeSafeClient(); const result = await client.systemOne({
model: "jev-1.13.0", state: {
message:
"The payment went through, but our candidates " +
"cannot start their assessments. " +
"Interviews begin in 30 minutes.",
}, questions: {
reported_blockage: noul(
"Does `message` report that candidates " +
"cannot start their assessments?"
), time_sensitive: noul(
"Does `message` describe a near-term deadline " +
"that makes prompt support important?"
), team: choice(
"Which team should investigate the main issue " +
"described in `message`?",
{
technical:
"Application failures or problems " +
"accessing or starting assessments.", billing:
"Disputed charges, failed payments, " +
"or refund requests.", general:
"Other issues, or insufficient detail " +
"to select a specialist team.",
}
),
},
}); const { team, reported_blockage, time_sensitive } =
result.answers; console.log({
model: result.model,
suggestedTeam: team.choice,
teamProbabilities: team.probabilities,
teamConfidence: team.confidence,
reportedBlockageProbability: reported_blockage.noul,
timeSensitivityProbability: time_sensitive.noul,
});
}main().catch(() => {
console.error(
"No routing suggestion was produced. " +
"Manual review is required."
);
process.exitCode = 1;
});
Run it with:
node triage.mjs
The example deliberately stops before taking action.
Once we have evaluated the outputs, we can add application rules. For instance, an uncertain team classification could remain in manual triage, while a strong time-sensitivity signal could make the ticket more visible to the operator.
Those are separate decisions. Uncertainty about the responsible team should not automatically hide a potentially urgent problem.
Ask several narrow questions, then combine the answers
A useful part of Jev’s interface is that several questions about the same state can be evaluated together. TypeSafe documents this as a way to avoid unnecessary sequential calls. A question can also be asked speculatively, with its result ignored when it is irrelevant.
Suppose our application needs a bug-severity assessment only when the message describes a bug.
We could first ask whether it is a bug, then make another call for severity. Alternatively, we could ask both questions together and let code decide whether the severity answer should be used.
There is an important limit to this idea.
When a later decision requires information we have not retrieved yet, we still need another stage. Parallel evaluation does not make missing information available.
I would also avoid assuming that separately evaluated questions produce statistically independent evidence. Combining several related signals does not automatically give us a valid joint probability.
For our support example, I would start with explicit rules that reviewers can inspect, rather than invent a complicated “overall certainty” formula.
Confidence is useful, but it needs careful interpretation
There are three ideas here that are easy to mix up.
Probability describes the model’s estimate for an outcome.
Jev’s confidence field summarises the shape of the probability distribution for a Choice or Score answer.
Calibration concerns how predicted probabilities compare with observed outcomes across many examples. Jev’s confidence field is not simply another name for measured accuracy.
Suppose a routing model assigns these probabilities:
Technical: 0.51
Billing: 0.47
General: 0.02
Technical is the highest-probability option. But the distribution is nearly split between two teams.
That should lead me to a different application decision than a distribution heavily concentrated on one team.
Now consider calibration.
In a well-calibrated set of predictions, outcomes assigned roughly 80% probability should occur roughly 80% of the time. This is a property assessed across groups of predictions, not a guarantee about an individual case.
TypeSafe describes Jev’s training approach as Reinforcement Learning for Calibrated Decisions, or RLCD, with the aim of making its probabilities useful for this kind of decision-making.
I would still verify that behaviour on our own workload.
A threshold that works for our English support tickets may not work equally well for a different product, a different language mix, or a different rubric.
The threshold is part of the application’s design. It is not a magic number we copy from a documentation example.
Type-safe does not mean correct
Suppose the permitted answers are:
technical
billing
general
Returning billing is structurally valid.
It can still be the wrong routing decision.
This distinction matters because Jev constrains its outputs to the supplied answer space, but its documentation also describes limitations and incorrect judgments. Type safety does not establish semantic correctness.
For the application, I would separate three checks:
Is the output valid?
Does it match the interface we expect?
Is the judgment reliable enough?
What does our evaluation show for this kind of input?
Is the proposed action permitted?
Do our rules, permissions, and approval requirements allow it?
Passing the first check does not automatically pass the other two.
I would also treat timeouts, unavailable services, and rate limits as ordinary integration failures. In the proposed support workflow, failure to obtain a suggestion should leave the ticket available for manual handling, not cause it to disappear.
Where AI agents could benefit
This is the part I find especially interesting.
An agent may need a generative model to produce a plan or write code. But the surrounding workflow also contains narrower decisions: selecting a handler, classifying a request, or flagging an action for review.
LangChain documents Jev integrations for model routing and tool-action checks, positioning it as a complement to the model driving the agent rather than a replacement for that model.
Consider a request entering an assistant.
My proposed routing options might be:
Deterministic handler
Small generative model
More capable reasoning model
Human review
An exact account-status lookup might belong in a deterministic handler. A request to explain a feature might need a generative model with product context. An ambiguous request involving a sensitive account change might need clarification or review.
TypeSafe documents this broader intent-routing pattern, including routing to code, specialist models, and humans.
However, I would not add a Jev call before every operation just because it is available.
If code already knows that an action is a database lookup, another classification step has no obvious purpose.
The useful question is: does this model call remove more uncertainty or work than it adds?
A model judgment is not a permission check
Suppose an agent proposes changing account permissions.
A model might help classify what the user requested. But I would still require the application to verify the actor, the target account, the allowed operation, and any necessary approval.
This separation is particularly important because TypeSafe explicitly documents that adversarial content in the input can influence Jev’s answers.
An instruction embedded in a support ticket must not become permission to execute an action.
I would use model-based checks as additional signals, not as the sole boundary protecting tools and data.
Speed and cost: promising numbers, but measure the whole workflow
TypeSafe reports response times of approximately 70–500 milliseconds and roughly 190× speedups in selected workflow evaluations. Its launch post qualifies those results: the largest improvements are expected to be toward the high end of real-world gains, and its published tests were generally run from the US West Coast. These are vendor-reported results, not benchmarks I have independently run.
For an application deployed in India, I would measure latency from the actual deployment region.
I would also measure the complete workflow, including context retrieval, the API request, retries, application processing, and any human review.
A fast classification call is useful. It does not tell us how quickly the customer’s problem gets resolved.
As of September 25, 2026, TypeSafe lists Jev at $0.042 per million input tokens, with no output-token charge.
For an illustrative calculation, assume 100,000 requests, each containing 1,000 total input tokens, including the state and questions.
That gives us:
100,000 requests × 1,000 tokens
= 100 million input tokens
100 × $0.042
= $4.20
That is the calculated Jev input cost at the published rate, not the cost of running the entire application.
For a pilot, I would compare token cost, incorrect decisions, review effort, and completion time together. A cheaper call is not a saving if it creates enough additional work elsewhere.
Where I would experiment beyond support tickets
The following are applications I would evaluate, not claims that these workflows are already reliable.
Editorial checks for technical learning content
For a programming lesson, I could supply the learning objective, prerequisites, and explanation.
Then I could ask whether the explanation introduces an undefined term, whether an example addresses the stated objective, or whether an essential prerequisite appears to be missing.
The result would be an editorial flag, not an automatic declaration that the lesson is correct.
Code examples would still need to run. An editor would still review the explanation.
Assessing individual parts of an answer
In an assessment application, I would prefer narrow rubric judgments over a broad score such as “candidate quality”.
For a JavaScript closure question, I might separately evaluate whether the answer discusses lexical scope, access to outer variables, and an appropriate use case.
I would keep these as reviewer-assistance signals, with the original answer visible.
The currently documented Jev model accepts text, not raw audio or video. A recorded-answer workflow would therefore need a separate transcription step before this kind of evaluation.
Choosing useful material for another model
A retrieval workflow could first obtain candidate passages, then evaluate which ones appear relevant to a question.
Here I would compare Jev with our existing retrieval and ranking approach. The goal would be better downstream answers or less unnecessary context, not merely adding another AI component.
In each case, I would begin with one clear decision and an explicit way to judge whether it helped.
What I would keep out of Jev
I would not delegate calculations, exact date comparisons, or counts that ordinary code can compute.
TypeSafe documents limitations in numerical precision, counting, date comparisons, complex indirection, and inputs containing substantial irrelevant material.
For our application, that means:
An invoice total belongs in code. A permission check belongs in code. A verified payment status comes from the payment system.
The model might interpret why a customer is asking for help. It should not calculate the balance or decide whether an authenticated user has a database permission.
I would also test the language mix we actually receive. TypeSafe says English is its strongest language and recommends evaluating other-language workloads on representative content.
And before sending customer data to an external API, I would minimise the fields included and review the applicable data-handling arrangements. A classification task should not receive unrelated personal information simply because it is present in the database.
How I would move from a demo to a useful feature
I would start by defining what counts as a correct decision.
For support routing, that includes how we handle messages involving multiple teams, incomplete reports, resolved incidents, and unclear deadlines. Without those definitions, even human reviewers may disagree.
Then I would assemble a labelled evaluation set containing both ordinary and difficult cases. I would reserve some examples for final testing rather than repeatedly tuning the questions against every available example.
Next, I would run the integration in shadow mode: it produces suggestions, but does not control the workflow.
During that stage, I would measure whether urgent cases are missed, whether routing suggestions are accepted, where the model is confidently wrong, and how much reviewer effort the suggestions actually save.
Only after that would I consider automating a narrow, reversible action.
For example, suggesting or assigning a support queue is a more contained starting point than issuing a refund or changing account access.
Finally, I would version the questions and record the model used. TypeSafe’s documentation notes that model aliases can move to new releases and recommends pinning a version when thresholds have been tuned against it.
That gives us a way to investigate a change in behaviour rather than guessing what changed.
My takeaway
The part of Jev that interests me is not the System One label by itself.
It is the opportunity to make the model’s role smaller and more explicit.
Before adding AI to a workflow, I would ask whether the application needs to generate something new, interpret something ambiguous, or calculate something exact.
Those are different jobs.
For generation and complex reasoning, I would evaluate a generative model. For suitable narrow judgments, I would evaluate Jev alongside other approaches. For exact operations, I would write code.
Then I would measure the result at the application level.
Also Laya is a local alternative to Jev (haven’t tried it yet) https://huggingface.co/convaiinnovations/laya
PS: AI agents could find a lot of use for this. There is scope to reduce unnecessary token generation and make smaller decisions faster. But the first optimisation is still to identify which decisions need a model at all.
Sometimes, writing that down removes the model call altogether 🙂
