AI DevelopmentAI Agents

Typed Decision Models for Agents: Jev vs Laya

September 22, 2026
11 min read
Abstract AI triage workflow with routing lines over a desk
Share:

Most production agents do not need another paragraph. They need a judgment: which team owns this ticket, is this tool call safe, which model should handle this request. Calling a frontier LLM for each of those micro-decisions is slow, expensive, and forces you to parse prose back into a branch.

In this deep dive I show you the System One alternative: typed decision models that return a choice, a score or a calibrated yes/no your code can branch on — and I compare the managed route (Jev) with the self-hosted route (Laya), with code I verified against the official sources.

1. The Problem: LLM Calls Where a Judge Would Do

Look at a typical support agent. Before it drafts any reply it must answer narrow questions: who owns the case, does the policy cover it, how urgent is it, is this message a prompt injection. Each answer has a bounded space you can enumerate before seeing the ticket. Yet most stacks send each question to a chat model and pray the JSON parses.

What Breaks in Production

Three costs compound: latency (seconds per decision instead of milliseconds), money (reasoning tokens billed per micro-judgment), and reliability (free-text answers that invent labels outside your set). A wrong-but-valid branch is debuggable; a hallucinated tool name buried three layers deep in a dependency chain is an incident.

The pattern that fixes it: keep exact work in code, keep generation in the LLM, and put a fast judgment gate between them. The gate reads unstructured state and returns typed values with probabilities. Thresholds, permissions and side effects stay in ordinary software where you can test them.

2. Minimum Concepts: Choice, Score, Noul, Calibration

Both Jev and Laya expose the same three question types. Learn these four ideas and every sample below reads like plain English.

🗳️

Choice

categorical · up to 255 options (Jev)

Pick one option from a fixed set. You get the winning label plus a probability per option. If the list may be incomplete, always include an other option — otherwise the model must pick the least-wrong answer.

📏

Score

ordinal · 2–10 ordered levels

A position on a rubric you define, e.g. routine / time-sensitive / urgent / critical. The returned number is probability-weighted across levels, so inspect the distribution when its shape matters.

⚖️

Noul

yes/no · calibrated probability

A yes/no probability P(true) from 0.0 to 1.0. A noul of 0.5 means equal probability on both sides — uncertainty, not medium intensity. For intensity, use a Score.

🎯

Calibration

ECE · Brier score · temperature

Calibration asks whether 80% predictions come true ~80% of the time, measured over many cases (ECE), with Brier rewarding confident-and-right answers. Laya ships calibration temperatures you refit per domain; Jev trains for it with RLCD.

Jev vs Laya at Design Level

Jev (TypeSafe AI, launched September 2026) is a managed API: parallel sampler, undisclosed architecture, RLCD post-training, 64k-token combined request limit, $0.042 per million input tokens with output free, 70–500ms end to end. Laya (Convai Innovations, Apache 2.0, pip install laya) is self-hosted: a 421M ModernBERT-large encoder (512 tokens) plus a 322M multilingual checkpoint (1024 tokens), a Router that picks the checkpoint per request, ~33ms per question on a T4. Same interface, opposite trade-off: provider dependence vs infrastructure you own. Vendor workflow numbers put Jev at 67.8% agreement for $0.0004 per case against GPT-5.6 Terra at 67.9% for $0.0304 — but that reference is TypeSafe’s own, so treat it as a vendor demo, not a leaderboard.

3. Tutorial, Part 1: Jev SDK in Python

Install the official SDK, set TYPESAFE_API_KEY, and call system_one with a state plus typed questions. This shape is copied from the official Python SDK docs — Choice criteria is a map of option to description (None for a bare label), Score criteria is an ordered list, and answers come back split into nouls, choices and scores.

One call, three judgments, batched in parallel

# pip install typesafe-sdk  # TYPESAFE_API_KEY in env
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

with TypeSafeClient() as client:
    response = client.system_one(
        state={"document": "I was charged twice. Please fix this ASAP."},
        questions={
            "billing": Noul(instructions="Is this ticket about billing?"),
            "tone": Choice(
                instructions="What is the customer tone?",
                criteria={"calm": None, "frustrated": None, "angry": None},
            ),
            "urgency": Score(
                instructions="How urgent is this ticket?",
                criteria=["can wait", "this week", "today"],
            ),
        },
    )

print(response.nouls["billing"].noul)    # P(yes), 0..1
print(response.choices["tone"].choice)   # winning label
print(response.scores["urgency"].score)  # weighted position, 0..2

Questions in one request share the prepared state and are evaluated in parallel — a tenth question costs tokens but almost no extra time. The model never authorizes anything: your code reads the probabilities and applies the policy, with an explicit uncertain band routed to humans.

Policy gate: act, review, or reroute

p_billing = response.nouls["billing"].noul

if p_billing > 0.90:
    queue_refund_checks(state)      # code verifies amounts, identity, limits
elif p_billing > 0.55:
    route_to_human(state, response) # uncertain band goes to review
else:
    route_to_specialist(state)

Rule of Thumb

One semantic judgment per question; composition and side effects in code. If question B needs the answer to question A, put that answer into a later request — never hide workflow dependencies inside a prompt.

4. Tutorial, Part 2: Laya Router + the Flywheel

Laya runs locally and speaks the same three primitives through dict schemas. Start with the built-in presets for instant triage, then use the Router when traffic mixes languages — it inspects the input script and picks the right checkpoint per request with under 2% overhead.

Preset triage in three lines

# pip install laya
import laya

agent = laya.load("convaiinnovations/laya")  # 421M, English, 512 ctx

triage = agent.predict(
    {"message": "My payment failed twice"},
    laya.triage_questions(),  # intent, urgency, frustration, churn
)

Why the Router Exists

One checkpoint cannot be optimal for every language. Router(preload=True) keeps the English (421M/512), multilingual (322M/1024) and typed-decisions (421M/1024) checkpoints resident and selects per request — no 7–10s cold swap when traffic alternates languages. Caveat from Convai’s own card: base checkpoints score near chance zero-shot on typed-decisions (0.362 vs 0.318 random); the strong numbers belong to the checkpoint fine-tuned on that benchmark’s training split.

Same task through Router.predict

from laya import Router

router = Router(preload=True)

decision = router.predict(
    {"message": "I was charged twice. Please refund the duplicate today."},
    {
        "owner": {
            "type": "choice",
            "instructions": "Which team owns the primary issue?",
            "criteria": {
                "billing": "charges, invoices, refunds, subscriptions",
                "technical": "product failures or errors",
                "account": "login, permissions, or account security",
                "other": "none of the listed teams fits",
            },
        },
        "refund_requested": {
            "type": "noul",
            "instructions": "Does the customer explicitly request a refund?",
        },
    },
)

The flywheel pattern (documented in the Jev-Flywheel study) keeps the engine frozen and adapts around it: refit a small decision head over the answers when reviewers disagree, and run steering rounds where an analyst proposes a new question a human approves. On the same 140 labels and 600 held-out items, that layer lifted Jev from 0.768 to 0.870 and Laya from 0.722 to 0.802, calibrating both (ECE 0.030 and 0.015). Full fine-tuning of Laya’s open weights on the same budget reached 0.896 — higher accuracy, but 42% of unrelated answers drifted, so every other score needs revalidating.

5. Common Mistakes in Production

These five failure modes come straight from the versioned limitation docs of both models. Budget for all of them before your first live decision.

🔢

Asking the judge to count

numbers · dates · exact math

Jev documents weak numerical precision, counting and date comparison — and a 400M encoder is no calculator either. Parse timestamps, compare amounts and check authorization deterministically; let the model judge language, not arithmetic.

📦

Closed choice, open world

missing other option

A Choice without an other or none_of_the_above forces a confident wrong answer when the true class is absent. Keep choice lists under ~20 options on Laya: every option shares a fixed token budget and long lists blur together.

🌡️

Trusting raw probabilities

calibration is a deployment step

Recheck probabilities after changing the model, schema, language or domain. Fit temperature on held-out data, set thresholds at the operating point that controls the workflow, and compare precision/recall there — not just accuracy.

✂️

Ignoring the window

512/1024 vs 64k

Laya truncates overlong input silently and answers on a prefix — count tokens first and refuse. Jev’s 64k request limit is headroom, not a promise: long noisy state still degrades decisions. Retrieve focused evidence either way.

🚨

No fallback around the gate

timeouts · drift · review queues

A hosted API needs timeouts, retries and a fallback branch; a local checkpoint needs serving capacity, cold-start planning and monitoring. Both need reversible actions, human queues, and logs of state version, distributions and overrides.

What to Evaluate Before Choosing

Run one frozen question set against the same labelled cases for every candidate — rules baseline, structured-output LLM, Jev, and the right Laya checkpoint — then compare per-class precision/recall, calibration at your threshold, latency percentiles, cost, and review volume. Start in shadow mode, ship reversible actions first, and pin the model version or checkpoint plus any calibration fit.

Conclusion

The useful idea is bigger than either product: many agent steps need a bounded judgment, not another paragraph. Jev packages that as a managed decision API with a 64k window you rent; Laya offers inspectable Apache-2.0 weights with 512/1024-token windows you own, fine-tune and calibrate yourself.

Give each layer the job it handles best: code does exact work and owns actions, a tested decision model turns text into bounded answers, LLMs generate and reason, humans resolve consequential uncertainty. Start this week by replacing one LLM classification call with a typed decision and a threshold — that single gate usually pays for the whole pattern.

Sources for This Post

Official

  • TypeSafe launch post
  • TypeSafe Python SDK docs
  • Laya GitHub repo

Independent analysis

  • Chromiak: Jev and Laya
  • Anthus: Jev vs Laya + flywheel
  • Laya model card (HF)

Key numbers

  • Jev 67.8% / $0.0004 per case
  • Flywheel: 0.870 vs 0.802
  • Laya: 33ms, 7.2ms batched
Diego Rodriguez

Diego Rodriguez

Senior Full-Stack & AI Engineer

Diego has 10+ years of experience building production-grade AI-powered applications, from LLM orchestration and RAG pipelines to ML-driven risk detection and algorithmic trading systems.

Learn more about Diego