Skip to content

jev4k

A Kotlin DSL and client for TypeSafe's Jev model.

Jev is a System One model: fast, calibrated judgments instead of generated text. You give it a state (a message, a document, a record) and a set of typed questions, and it returns typed answers with probabilities your code can branch on, sort by, and threshold.

jev4k lets you declare those questions in Kotlin, send them in one request, and read the answers back as typed values, down to enum-valued choices that work with an exhaustive when.

object FirstTriage : JevQuery() {
    val urgent by noul("Does this message convey urgency or time-sensitivity?")
    val team by choice<Team>("Which team should handle this message?")
    val frustration by score("How frustrated does the customer appear?") {
        levels("Calm, just stating facts", "Frustrated but civil", "Very angry, strong language")
    }
}

suspend fun routeTicket(
    jev: JevApi,
    ticket: String,
): String {
    val result = jev.ask(FirstTriage, state = ticket)

    val queue =
        when (result[FirstTriage.team].choice) {
            Team.BILLING -> "billing"
            Team.TECHNICAL -> "engineering"
            Team.SALES -> "sales"
        }
    val priority = if (result[FirstTriage.urgent].isTrue(threshold = 0.7)) "high" else "normal"
    return "$queue ($priority)"
}

How it works

graph TD
  S[State: text, JSON, or @Serializable] --> R
  Q[Questions: Noul, Choice, Score] --> R
  R[jev.ask / jev.query] -->|one HTTP request| J[Jev]
  J -->|typed answers + probabilities| A[JevResult]
  A --> C[Your code: branch, rank, threshold, escalate]
  1. Declare questions with the inline DSL or as a reusable, typed JevQuery.
  2. Ask them about a state in one request. Jev answers every question in parallel, in about 100 ms.
  3. Read typed answers: a probability for a Noul, an option (or enum constant) for a Choice, a position on your levels for a Score, each with the probabilities behind it.
  4. Decide in code. Control flow, arithmetic, thresholds and side effects stay in your program.

Three kinds of question

Question Asks Answer
Noul Is this true? noul: the probability of yes, 0 to 1
Choice Which of these options? choice, a probability per option, confidence
Score Where on these ordered levels? score (can fall between levels), per-level probabilities, confidence

Features

  • Two DSL styles: quick inline queries with string ids, or reusable typed queries whose property names become question ids.
  • Typed enum choices: choice<Team>() answers with a Team, so the compiler checks every branch.
  • Structured criteria: contrastive rubrics, examples, and JSON field specs in instructions and options.
  • Any state: text, JSON, or any @Serializable value.
  • Suspend-first client on Ktor, with a blocking mirror for scripts and main.
  • SDK-parity retries: the official SDKs' retry and timeout rules, including server Retry-After hints.
  • Validation before sending: every problem with a request is reported at once, without a network call.
  • Quick Start


    Set an API key and run your first query in a few lines.

    Get started

  • Concepts


    State, questions, answers, and what calibrated confidence means.

    Learn the model

  • Patterns


    Routing, composite scoring, verification, extraction, ranking, and guardrails.

    Browse patterns

  • Writing Good Questions


    The habits that make Jev's answers accurate and useful.

    Read the guide

  • The Jev Docs


    TypeSafe's own documentation: concepts, primitives, and cookbooks.

    docs.typesafe.ai

  • API Reference


    Every public type and function, generated from the source by Dokka.

    Browse the KDocs

Thanks to TypeSafe

Jev, and the System One idea behind it, come from TypeSafe, who have done a great job with both. Their documentation at docs.typesafe.ai is excellent. jev4k follows Jev's concepts and naming, so what you learn there carries straight over to this library.