Jev for developers: typed decisions inside real software

A developer guide to TypeSafe AI's Jev: typed judgments, Python integration, retrieval filters, routing, prompt-caching patterns, and decision policies.

Last checked:

Sections

Most useful AI features in software are smaller than a chatbot. Which queue should this issue enter? Does this retrieved passage actually answer the question? Which handler can process this request? Is there enough information to continue?

These decisions sit between ordinary functions. They need a predictable interface, a fallback, and a way to measure whether the judgment was right.

Jev is TypeSafe AI's model for that kind of work. TypeSafe calls it a System One model: you supply context and typed questions, and receive decisions with numerical signals your application can inspect. The interface centers on selecting, rating, and evaluating statements instead of writing prose. TypeSafe introduction.

This article builds on the introduction in Prosper Otemuyiwa's practical Jev guide. Here, the focus is the code around the model: useful boundaries, realistic use cases, and what should happen when an answer is uncertain or wrong. The examples are integration designs, not production performance claims.

Where Jev fits in an application

Think about an issue tracker. A regular expression can detect an issue number. A database query can establish who owns a repository. A model can help interpret a messy description and suggest which team should investigate.

That last step is a candidate for Jev. The surrounding code still owns identity, permissions, persistence, and execution.

01 / The application flow A small judgment. A clear next step. Context goes in. Your code decides what happens next.
01 Prepare Application code Relevant state and questions
02 Jev Model judgment
Example judgment
choice
runtime
confidence
0.72
Typed answers and probabilities
03 Decide Application code
Apply policy
RouteorReview
Checks, thresholds, and fallback
FIG. 01 Jev supplies a judgment. Your application owns permissions, validation, and execution.

The request contains state, the material to evaluate, and questions, the judgments to make. Questions in one request are evaluated independently against that same state. One question cannot depend on another question's returned answer inside that call. A dependent decision needs a later step. System One concepts.

That boundary is useful. You can ask about issue category and reproduction details together, then combine their results in a deterministic function. Independent evaluation does not mean the answers are statistically independent, so multiplying their probabilities would need separate justification.

Typed output also has a limit: a valid category can still be the wrong category. Treat the API contract and the quality of the judgment as two separate things to test.

The three primitives: Choice, Score, and Noul

Choice selects from a fixed vocabulary. Give it named options with descriptions. A response includes the selected option, probabilities across the options, and confidence. Use it for mutually exclusive destinations such as documentation, build tooling, runtime investigation, or general triage. Include an explicit fallback category when the input might fit none of your normal routes. Choice reference.

Score evaluates an ordered rubric. Its levels are descriptions, starting at position zero. The returned score is a probability-weighted position and can be fractional. With three levels, it ranges from 0 to 2. It also returns the distribution and confidence. A score is not an objectively measured quantity: a documentation-quality score of 1.6 does not mean a document is 80% correct. Score reference.

Noul estimates the probability that a yes/no statement is true. It returns a value between zero and one, without a separate confidence field. Ask a narrow question such as whether a report includes reproduction steps. A value of 0.8 means an estimated probability of yes, not that the steps are 80% complete. Noul reference.

The practical choice is simple: an unordered category calls for Choice, a graded rubric calls for Score, and a single proposition calls for Noul. Avoid combining unrelated concepts into one question. “Urgent, reproducible, and security-sensitive” describes three different judgments.

02 / The decision vocabulary Three shapes for three kinds of question. Illustrative values, not measured model results.
ChoiceWhich one?Select a category.
Where should this issue go?
docsbuildruntime
Selected category: runtime
ScoreWhere on a scale?Use an ordered rubric.
How specific is this report? Position on the rubric, not percent correct.
NoulIs it true?Evaluate a yes/no question.
Are reproduction steps provided?
0.85Estimated probability
of “yes”
Not a measure of how complete the steps are.
FIG. 02 Choice and Score also return distributions and confidence. Noul returns the probability of yes.

A Python example: classify an incoming developer issue

Install the package with python -m pip install typesafe-sdk and provide TYPESAFE_API_KEY through your server's environment or secret manager. Keep the key out of browser code. The official Python SDK provides synchronous and asynchronous clients.

This example uses the documented synchronous API and a pinned model version. It asks for a destination, the presence of reproduction steps, and the specificity of the report. The fixture is synthetic. Running the first block requires a TypeSafe account and makes a billable API request; no live model output is presented here.

from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

issue = {
    "title": "CSV export stops after upgrading the dashboard",
    "body": (
        "In dashboard 4.2 on Firefox, open Reports, "
        "select Last month, then click Export CSV. "
        "Expected a download; instead the button stays disabled. "
        "The same account can export in Chrome."
    ),
}

with TypeSafeClient(model="jev-1.13.0") as client:
    response = client.system_one(
        state={"issue": issue},
        questions={
            "route": Choice(
                instructions="Which area should first investigate this issue?",
                criteria={
                    "docs": "Incorrect or missing written instructions.",
                    "build": "Installation, compilation, or packaging failure.",
                    "runtime": "Unexpected behavior in a running application.",
                    "other": "Ambiguous, unrelated, or no listed area fits.",
                },
            ),
            "reproduction": Noul(
                instructions=(
                    "Does the report give an explicit sequence of actions "
                    "that a developer could attempt to reproduce the issue?"
                ),
            ),
            "specificity": Score(
                instructions="How specific is the reported observation?",
                criteria=[
                    "Only a general complaint; no identifiable behavior.",
                    "Identifiable behavior, without expected versus actual detail.",
                    "A concrete expected result and a concrete actual result.",
                ],
            ),
        },
    )

print(response.model)
print(response.choices["route"].choice)
print(response.choices["route"].probabilities)
print(response.nouls["reproduction"].noul)
print(response.scores["specificity"].score)

The category descriptions explain the actual distinction to make. The report stays in state, separate from the application-owned instructions. The Score measures specificity only; it should not silently become a severity score or determine incident priority.

For an asynchronous service, use the SDK's async client and bound concurrency in your application. Configure transport timeouts and retry behavior explicitly for the service's latency budget. The client reference documents those controls. A transport timeout is not a substitute for an end-to-end workflow deadline.

Put the action policy in ordinary code

The API call produces evidence for a decision. A separate function decides which queue to propose:

QUEUES = {
    "docs": "documentation-review",
    "build": "build-investigation",
    "runtime": "runtime-investigation",
}

def proposed_queue(response, *, route_floor, reproduction_floor):
    route = response.choices["route"]
    if route.choice not in QUEUES:
        return "general-triage"
    if route.confidence < route_floor:
        return "general-triage"

    reproduction = response.nouls["reproduction"].noul
    if route.choice == "runtime" and reproduction < reproduction_floor:
        return "reproduction-review"

    return QUEUES[route.choice]

# Illustrative thresholds, not validated defaults.
queue = proposed_queue(
    response, route_floor=0.8, reproduction_floor=0.85
)
print(queue)

This function returns a suggestion. It does not assign an issue, message a customer, or execute a command. Unknown categories and low confidence stay in general triage. A runtime report without a strong reproduction signal goes to a reviewer, who can decide whether more information is actually needed. An urgent incident should still follow your existing incident process.

The two thresholds mean different things. One gates the Choice confidence statistic; the other gates a Noul probability. Their similar numerical range does not make them interchangeable.

Test the policy with constructed responses before testing the model: every known route, the fallback route, values on either side of each threshold, and missing or failed API responses at the caller. On an API failure, retain the existing queue and record a retryable failure. Do not convert a timeout into a fabricated model answer.

Use case 1: better evidence selection for retrieval

A retrieval system may return passages that mention the right subject without answering the user's actual question. Jev can provide a second judgment after retrieval: does this particular passage contain information needed for this particular question?

Pass the question and a candidate passage as state. Use Noul for direct answer relevance, or a Score rubric that distinguishes a passing mention, useful background, and direct support. Keep document IDs attached in application code. TypeSafe has a retrieved-passage classification cookbook for this pattern.

An implementation could retrieve a bounded candidate set, filter it with Jev, and give the retained passages to the answer generator. Keep a fallback for an empty result instead of forcing an answer from weak evidence.

Measure retrieval recall as well as filtering precision. A filter that removes every difficult passage may look clean while making the final assistant less useful. Compare answer quality with and without the filter on questions that require multiple passages.

After generation, another step can compare individual claims with their cited passages. TypeSafe's citation-checking cookbook covers evaluating support. Citation support is narrower than factual truth: a claim can faithfully repeat a source that is outdated or wrong. Preserve source dates and authoritative-source rules outside the model.

Use case 2: CI failure triage that engineers can inspect

Build logs mix machine-readable facts with noisy descriptions. Start with deterministic parsing: exit codes, failing test names, package versions, and relevant error excerpts. Use Jev to suggest a failure family such as dependency resolution, test assertion, configuration, or unknown.

The useful output is a triage artifact attached to the failed run: proposed category, supporting log excerpt, model version, and the route chosen by policy. Select the excerpt through your log parser; do not imply Jev returned a written explanation when it returned a category.

Group repeated failures by a stable signature your code calculates. This prevents dozens of identical failures from creating dozens of separate investigations. A model's category can help organize the groups without becoming their identity.

Keep the classification advisory at first. “Infrastructure failure” should not automatically disable a test, merge a pull request, or repeatedly rerun expensive jobs. Track how often engineers change the category, then decide whether a narrow action such as notifying an internal queue is justified.

Use case 3: routing between handlers and models

An internal assistant might support documentation lookup, issue search, and a longer technical investigation. A Choice can propose the appropriate handler. A Noul can separately assess whether the request names a specific repository. Code then checks the user's access and resolves that repository before anything runs.

TypeSafe documents intent routing. In your application, map labels to a fixed registry of handlers. A returned label should never become an arbitrary function name, shell command, or unchecked URL.

The same approach can route between a quick retrieval answer and a more expensive reasoning workflow. Evaluate whether routing saves total time and cost after accounting for the extra call and wrong routes. Some applications are better served by going straight to the main model.

Dependent questions need stages. First resolve the request category; then supply that result and the relevant evidence to the next decision. Independent checks can share a request, but speculative work should be bounded and free of side effects. The fan-out pattern explains the shared-state approach.

Use case 4: document and operational exception queues

A distributor receives delivery notes, stock discrepancy emails, and return requests. Existing software already knows order IDs, quantities, and customer accounts. Jev's role can be interpreting the accompanying text: is the sender describing damaged goods, missing items, the wrong product, or an unclear problem?

Use a document parser or OCR service before Jev when needed, then resolve identifiers against trusted records. Keep quantity comparisons and monetary calculations in code. A discrepancy category can select the review queue and the evidence the reviewer needs.

This division is valuable when descriptions vary but the business process is stable. The warehouse team gets a relevant case instead of a generic inbox item. The application still decides whether a credit is allowed and whether the submitting user can access the order.

For the surrounding workflow design, see the business automation guide. Jev belongs at the interpretation step, alongside the CRM, database, and workflow engine that already own the records.

Connecting Jev to prompt caching

Routing and evidence selection also affect the request sent to the next model. That creates a useful connection to prompt caching, where a provider reuses computation for a matching input prefix while still generating a new answer.

Jev can help shape that downstream request in two ways:

These are proposed composition patterns, not claims that Jev itself provides a prompt cache or cache discount. A Jev call and the downstream model call have separate processing and costs. A stable prefix only creates an opportunity for reuse; the selected provider's eligibility rules, cache availability, and expiry determine what actually happens.

Stable profiles can improve reuse compared with instructions customized for every request. They do not inherently beat one suitable universal prefix: splitting that prefix divides traffic. Put eligible shared content before profile-specific instructions, and check that each cache boundary is long enough, stays identical, and receives repeat traffic before expiry. Different tasks receiving different labels is normal; spreading equivalent work across unnecessary profiles fragments reuse.

Compare a direct-model baseline, stable-prefix assembly alone, and the same assembly with Jev routing or filtering. Keep the classifier's own question definitions stable too, without assuming Jev offers a cache discount. Include its latency, retries, wrong routes, and downstream cache reads and writes. Track answer quality and cost per successful task. An existing deterministic rule may select the template without another model call.

The prompt caching in production guide goes deeper into prefix layout, provider differences, usage accounting, break-even calculations, and cold-versus-warm testing. Keep Jev's role small: judge the task or evidence, then let code build and evaluate the request.

Confidence needs a local evaluation, not a magic cutoff

TypeSafe defines Choice and Score confidence as a statistic derived from the shape of the returned probability distribution. A concentrated distribution has higher confidence. It is not simply the selected option's probability, and a confidence of 0.9 is not a guarantee of 90% accuracy on your inputs. Confidence documentation.

Build an evaluation set from the actual decision boundary. Include ambiguous reports, missing context, overlapping categories, unfamiliar vocabulary, and cases that should reach the fallback. Have a knowledgeable reviewer label expected outcomes. Keep a separate held-out set for checking changes after you tune question wording or thresholds.

Measure at least four things:

Report quality by category too. A strong overall average can hide poor performance on a rare but important route. Review a sample of high-confidence decisions, not just uncertain ones, or confident mistakes will remain invisible.

Run the first integration in shadow mode: store the proposed decision while the current process continues. Compare the two, investigate disagreements, and only then enable a narrow reversible action. The AI evaluation and observability article explains how traces and evaluation sets support that feedback loop.

Model limits and production details worth getting right

As checked on September 22, 2026, the documented version is jev-1.13.0. Jev accepts text, including structured text values; images, audio, and video need preprocessing. The documented context limits are 64k tokens for the complete request and 32k for state plus the longest individual question. The jev-latest alias can move, so pin a version for evaluated behavior and log the resolved model returned by the API. Model reference.

TypeSafe's Jev 1.13 jaggedness page documents weaknesses with arithmetic, counting, date comparisons, irrelevant context, and adversarial instructions inside state. Separately asked complementary questions can also disagree. These are reasons to design small judgments and explicit fallbacks. An instruction to ignore malicious content is not a security boundary.

For production, I would add these controls around the integration:

The model page lists input pricing at $0.042 per million tokens, with output tokens free. At that rate, one million requests averaging 2,000 input tokens would cost about $84 in model inference. That is illustrative arithmetic, not a complete system quote: retrieval, other models, retries, storage, and engineering add cost. Recheck pricing before budgeting. Current pricing.

A useful first project

Choose a decision with an existing queue, a known set of outcomes, and someone who can judge the result. Issue routing and document exception triage are good candidates because disagreements are visible and the proposed action can stay reversible.

Start with the current deterministic process as a baseline. Add one Jev judgment. Compare the quality, latency, and review load. Keep it only if the complete workflow improves.

That is also the broader idea behind breaking problems into smaller model tasks: make each judgment small enough to inspect, and let ordinary software connect the steps.

If you have a developer workflow or business process that could use this kind of integration, discuss your idea with Peak Evergreen. I can help map the decision, build the integration, and establish an evaluation process before expanding its role.

Also worth exploring: Kev and its playground

Jared Palmer's Kev is a separate project offering small Jev-like decision models built on Qwen3.5 that you can run and train yourself. It supports the same Choice, Noul, and Score request pattern through a TypeSafe-compatible server. That makes it an option to explore when you want control over the model and serving environment.

Kev already includes a playground for inspecting judgments, comparing option order, and trying questions together or separately. There is also a hosted demo on Hugging Face. Start there to explore the model interactively.

Jevidence adds the application-code side: point its existing issue-routing example at a running Kev server and inspect the suggestion produced by the same policy. After following Kev's server setup, run these commands from Jevidence:

make setup-live
make kev

API compatibility does not establish equivalent accuracy or confidence. Kev documents its own confidence calculation, so evaluate thresholds separately on your inputs. Record the checkpoint and server settings as well: Kev's returned model label can be an alias, not an immutable version. The Jevidence Kev guide explains the connection and what to compare.

Try the companion project: Jevidence

Jevidence on GitHub turns this article's issue-routing example into a small Python sandbox. Start with make demo to inspect a synthetic judgment, make evaluate to compare the policy against constructed cases, and make test to check its behavior. No API key is needed for the offline examples.

The project includes Choice, Noul, and Score questions, separate routing rules, failure handling, tests, Docker builds, and setup instructions. Live calls require an explicit opt-in; TypeSafe's hosted backend also needs your API key. Everything stays advisory: the sandbox prints a proposed queue and never assigns an issue. The bundled fixtures test the code, not Jev's accuracy.

Watch the 50-second walkthrough

A silent, captioned walkthrough using real CLI output from synthetic fixtures. Change a threshold, inspect the proposed queue, and run the policy checks. No live Jev calls or actions are performed. Download the video.
Read the demo transcript
  1. 0–5 seconds: Jevidence separates typed judgment, code-owned policy, and a proposed next step. The offline demo needs no API key.
  2. 5–16 seconds: python3 -m jevidence demo returns a synthetic runtime choice with confidence 0.72. The route threshold is 0.8, so the policy proposes general-triage.
  3. 16–27 seconds: Add --route-floor 0.7. The same evidence passes that threshold and the reproduction check (0.95 >= 0.85), proposing runtime-investigation. These are illustrative thresholds. Nothing is applied.
  4. 27–35 seconds: python3 -m jevidence evaluate reports eight cases matching their expected decisions at the default thresholds. This tests policy behavior, not model accuracy or calibration.
  5. 35–42 seconds: The unit test command reports 15 passing tests and five skipped optional SDK transport tests in this dependency-free run, including checks for boundaries and failure handling.
  6. 42–50 seconds: Clone Jevidence, run the offline demo, and explore this companion guide.

All notes · Contact