Built with Tutify.io

    AIStudyLabs

    JEV AI: Structured Decisions for Software, Not Chat

    JEV AI: Structured Decisions for Software, Not Chat

    What is JEV AI?

    JEV is a model from TypeSafe AI, released in early access. TypeSafe calls it its first System One model. The name borrows from Daniel Kahneman's split between fast, intuitive thinking (System One) and slow, deliberate thinking (System Two). In this framing, LLMs are the slow, deliberate reasoners, and JEV is the fast layer that handles repetitive decisions.

    TypeSafe describes JEV as "a frontier-intelligence function call: unstructured state in, typed probabilistic decisions out." You send it some state (text or a JSON object) and a list of questions. It returns answers in the shape you specified, each with a confidence value.

    JEV is not built to write essays, hold a conversation, or explain its reasoning. It is built to answer questions such as:

    JEV is not the same as JEPA, a separate research architecture from Meta. JEPA AI explained covers that design.

    Core concepts

    System One vs. System Two

    | | System One (JEV) | System Two (LLM) | | --------------- | ------------------------------- | ----------------------------------- | | Purpose | Fast, repeatable decisions | Open-ended reasoning and generation | | Output | Predefined, typed values | Free-form text | | Typical latency | 70 ms to 500 ms (vendor figure) | Seconds | | Explanations | None returned | Can explain its reasoning |

    Comparison of System One (JEV) and System Two (LLM) decisions

    Typed, defined outputs

    With an LLM, you ask for JSON and hope it parses. With JEV, you define the answer space up front. A choice question can only return one of the options you list. A score question can only return a level on your scale. Because the answer space is fixed, there are no formatting errors to handle, and an unexpected output cannot reach your database.

    Question types

    JEV supports three question types:

    Each question has a stable key, such as department or needs_human. The key is how you find that answer in the response.

    Calibrated confidence

    JEV returns a confidence value with each answer. The vendor says the model is trained with Reinforcement Learning for Calibrated Decisions (RLCD), which aims for probabilities that match how often the answer is right. If the model is well calibrated, an answer with 0.95 confidence should be right about 95% of the time. You can use that number to decide what runs automatically and what goes to a person.

    Calibration is a claim to test on your own data. The testing section below shows how.

    Parallel, single-pass decisions

    LLMs generate output one token at a time. TypeSafe says JEV produces all of its answers in one pass, using a parallel sampler. That design underpins its speed claims.

    Advantages

    Claimed by the vendor or launch material:

    Observed by third parties in the sources:

    When to use JEV, and when not to

    Good fit:

    Poor fit:

    A common pattern is a cascade. JEV answers first. If its confidence is below a threshold (for example, 0.8), the request goes to a larger LLM. You choose the threshold based on how costly a wrong answer is.

    Cascade flow: JEV answers first, and answers below 0.8 confidence go to an LLM

    Real-time use cases

    1. Support ticket routing. Route each incoming message to billing, technical or sales as it arrives, before a person reads it.
    2. Live moderation. Score each chat message for policy violations and hold the uncertain ones for review.
    3. Fraud and abuse signals. Ask yes/no questions such as "does this look like a phishing attempt?" on each login or message.
    4. Intent detection in apps. Decide what a user wants from a search box or voice transcript, then pick the next screen.
    5. Prompt guardrails. Check each user input for jailbreak attempts before it reaches an LLM. The TypeSafe article names this use case.
    6. Quality gates for LLM output. Score a generated answer for factual support or policy compliance before it is shown to a user.
    7. Game and agent decisions. TypeSafe's launch material includes demos of a bot that plays Doom and a Wikiracing game, showing decisions made in tight loops.

    How JEV differs from an LLM

    | Aspect | LLM | JEV | | --------------- | -------------------------------------- | ------------------------------------------------------ | | Output | Open-ended text | Predefined decisions with probabilities | | Typical latency | Seconds | Hundreds of milliseconds (vendor figure) | | Billing | Input and output tokens | Input tokens (per the sources) | | Explanations | Yes | No rationale returned | | Calibration | Not designed for it | Trained for calibrated probabilities (RLCD) | | Strengths | Writing, reasoning, code, conversation | Classification, routing, scoring, yes/no checks | | Failure mode | Confident-sounding wrong text | Wrong option with a confidence value you can threshold |

    The two are complements, not substitutes. A common architecture puts JEV in front as a fast decision layer and calls an LLM only for cases that need language generation or deeper reasoning.

    Installing the JEV API

    Requirements: Python 3.10 or later.

    1. Get API access. Direct API access is in early access. Request a key from the TypeSafe console. Third-party guides report a waitlist, so access may take time. Some gateways also serve JEV without one, but they use different keys and base URLs, so check their docs before using them.

    2. Create a virtual environment and install the SDK.

    python3 -m venv .venv
    source .venv/bin/activate
    pip install typesafe-sdk
    

    Or with uv:

    uv init --bare
    uv add typesafe-sdk
    

    A fresh install of typesafe-sdk version 0.7.5 on Python 3.13 imports cleanly.

    3. Store your key in an environment variable. The SDK reads TYPESAFE_API_KEY automatically. Do not put the key in your code or commit it to version control.

    export TYPESAFE_API_KEY="your-api-key"
    

    On Windows, use WSL or the equivalent set or setx command.

    4. Confirm the install. If the key is missing, the SDK raises a clear error before it sends anything:

    from typesafe_sdk import TypeSafeClient
    
    with TypeSafeClient(model="jev-latest") as client:
        print("Client ready")
    

    Without TYPESAFE_API_KEY set, this raises TypeSafeError: No API key was provided.

    5. Make a first decision with the SDK. The SDK handles authentication and response parsing:

    from typesafe_sdk import Noul, TypeSafeClient
    
    ticket = "Our API integration started returning 500 errors on every request about 20 minutes ago."
    
    with TypeSafeClient(model="jev-latest") as client:
        response = client.system_one(
            state=ticket,
            questions={
                "is_urgent": Noul(instructions="The message conveys urgency or time-sensitivity"),
            },
        )
    
    print(response.nouls["is_urgent"].noul)  # a probability from 0 to 1
    

    The SDK exposes results by question ID: response.choices[...] for Choice questions, response.scores[...] for Score, and response.nouls[...] for Noul.

    The SDK is the recommended route. The sections below use requests to show the raw HTTP request, which helps when debugging or working in a language without an SDK.

    Making a raw decision request

    import os
    
    import requests
    
    JEV_URL = "https://api.typesafe.ai/v1/systemone"
    
    
    def decide(state, questions, model="jev-latest", timeout=10):
        """Send one decision request and return the parsed JSON response."""
        headers = {
            "Authorization": f"Bearer {os.environ['TYPESAFE_API_KEY']}",
            "Content-Type": "application/json",
        }
        payload = {"model": model, "state": state, "questions": questions}
        response = requests.post(JEV_URL, headers=headers, json=payload, timeout=timeout)
        response.raise_for_status()
        return response.json()
    

    The timeout matters. A real-time system should fail fast and fall back, not hang.

    Defining questions

    TICKET_QUESTIONS = {
        "department": {
            "type": "choice",
            "instructions": "Which team should handle this request?",
            "criteria": {
                "billing": "Payments, invoices, refunds, or payouts",
                "technical": "Bugs, outages, or integration failures",
                "sales": "Pricing, upgrades, or new accounts",
            },
        },
        "needs_human": {
            "type": "noul",
            "instructions": "Does this request require human review?",
        },
    }
    
    result = decide(
        state={"message": "My payout has failed three times.", "days_waiting": 3},
        questions=TICKET_QUESTIONS,
    )
    

    Keep the criteria specific. Each option's description tells the model when to pick it, so clear descriptions usually beat clever prompts.

    Reading the answers

    The Hugging Face guide describes an answers object keyed by question name. A choice answer carries the chosen option, per-option probabilities and a confidence. A noul answer carries a single probability.

    answers = result["answers"]
    
    department = answers["department"]["choice"]
    department_confidence = answers["department"]["confidence"]
    human_probability = answers["needs_human"]["noul"]
    

    Routing on confidence

    Automate only when the model is sure. Send the rest to a person. For how human oversight is organized, see Human in the loop vs human on the loop.

    CONFIDENCE_THRESHOLD = 0.8
    
    
    def route_ticket(answers):
        if answers["department"]["confidence"] < CONFIDENCE_THRESHOLD:
            return "human_review"
        if answers["needs_human"]["noul"] >= CONFIDENCE_THRESHOLD:
            return "human_review"
        return answers["department"]["choice"]
    
    
    fake_answers = {
        "department": {"choice": "billing", "confidence": 0.94},
        "needs_human": {"noul": 0.12},
    }
    print(route_ticket(fake_answers))
    

    Output:

    billing
    

    Choose the threshold from data, not intuition. Run JEV on historical tickets with known labels, then pick the threshold that gives an acceptable error rate for the cases you automate.

    A cascade: JEV first, LLM when unsure

    def classify_with_fallback(ticket_text, llm_classify):
        """Try JEV first. Escalate to a slower LLM when confidence is low."""
        data = decide(
            {"message": ticket_text},
            {"department": TICKET_QUESTIONS["department"]},
        )
        department = data["answers"]["department"]
        if department["confidence"] >= CONFIDENCE_THRESHOLD:
            return department["choice"], "jev"
        return llm_classify(ticket_text), "llm"
    

    llm_classify is any function that calls your LLM. The cascade keeps most traffic on the fast path and spends LLM tokens only where JEV is unsure.

    Splitting one hard question into several easy ones

    The TypeSafe and third-party tests suggest that breaking a question into narrower sub-questions and combining the answers can raise accuracy. Here is a simple combination rule:

    PHISHING_CHECKS = {
        "asks_for_credentials": {
            "type": "noul",
            "instructions": "Does the message ask the reader to enter a password or login details?",
        },
        "urgent_deadline": {
            "type": "noul",
            "instructions": "Does the message claim an urgent deadline or threat?",
        },
        "unknown_sender": {
            "type": "noul",
            "instructions": "Does the message come from a sender the content does not identify clearly?",
        },
        "suspicious_link": {
            "type": "noul",
            "instructions": "Does the message contain a link that does not match the claimed sender?",
        },
        "payment_request": {
            "type": "noul",
            "instructions": "Does the message ask for money, gift cards or a payment change?",
        },
    }
    
    
    def phishing_score(message):
        data = decide({"message": message}, PHISHING_CHECKS)
        probs = [data["answers"][key]["noul"] for key in PHISHING_CHECKS]
        # Average the yes-probabilities. Each check is one simple, testable question.
        return sum(probs) / len(probs)
    

    Averaging is only one option. Test other combination rules, such as the maximum or a weighted sum, on labeled examples, and keep whichever works best on your data.

    Testing without an API key

    You can test routing logic offline with a canned response shaped like the real one. This keeps unit tests fast and free:

    def test_low_confidence_goes_to_human():
        fake_answers = {
            "department": {"choice": "sales", "confidence": 0.51},
            "needs_human": {"noul": 0.20},
        }
        assert route_ticket(fake_answers) == "human_review"
    
    
    def test_confident_billing_is_automated():
        fake_answers = {
            "department": {"choice": "billing", "confidence": 0.94},
            "needs_human": {"noul": 0.12},
        }
        assert route_ticket(fake_answers) == "billing"
    

    Run these with pytest. Add a small set of recorded real responses so the parser keeps matching the live API.

    Limitations and risks

    Summary

    JEV AI is a decision model, not a chatbot. It takes state and a set of questions, and returns typed answers with calibrated confidence in a few hundred milliseconds. Use it for classification, routing, scoring and yes/no checks in high-volume or real-time paths. Keep LLMs for generation and explanation. Put a confidence threshold between the two, and measure both accuracy and calibration on your own data before relying on either.

    Sources