How to Use Jev: Python, JavaScript and Agent Framework Examples

The fastest way to understand Jev is to replace one classification call you already have. Below are the shapes that matter, all of them reducible to the same request body.

Python, raw HTTP

import os, requests

r = requests.post(
    "https://api.typesafe.ai/v1/systemone",
    headers={"Authorization": f"Bearer {os.environ['TYPESAFE_API_KEY']}"},
    json={
        "model": "jev-latest",
        "state": "My card was charged three times and nobody replied in two days.",
        "questions": {
            "urgent": {"type": "noul",
                       "instructions": "Does this need a reply within the hour?"},
            "team": {"type": "choice",
                     "instructions": "Which team should own this?",
                     "criteria": {"billing": "Payments and refunds",
                                  "technical": "Bugs and outages",
                                  "other": "Anything else"}},
            "severity": {"type": "score", "instructions": "How bad is it?",
                         "criteria": ["Cosmetic", "Annoying", "Blocks work", "Lost money"]},
        },
    },
)
print(r.json()["answers"])

Python, official client

from typesafe import TypeSafeClient

client = TypeSafeClient(model="jev-1.13.0")   # pin once you tune thresholds
answers = client.system_one(state=text, questions=QS).answers

JavaScript

import { TypeSafeClient, choice } from "@typesafe-ai/sdk";

const client = new TypeSafeClient();

export default async (req) => {
  const { answers } = await client.systemOne({
    state: await req.json(),
    questions: {
      team: choice("Route this contact form submission", {
        sales: null, support: null, spam: null,
      }),
    },
  });
  return Response.json({ team: answers.team.choice });
};

Pydantic AI: a typed decision as a tool

Because the answers are already typed, a Jev call drops into an existing agent as a step that returns a value instead of a paragraph:

router = Agent(
    "typesafe:jev-latest",
    output_type=Literal["fast", "capable"],
    instructions=("Pick the next step's model. Use fast for a lookup or a one-file change; "
                  "capable for architecture, security or anything expensive to get wrong."),
)
picked = await router.run(message_history=ctx.messages)

The pattern worth copying from the published guides: Jev chooses, then the code acts. When the decision is "hand this to a human", the tool call is triggered by output == expected in ordinary Python — no parsing, no retry loop.

Four mistakes that show up in every first draft

  1. Sending the whole record. Pre-compute the fields the decision actually needs; tokens are cheap but irrelevant state makes decisions worse.
  2. Asking a compound question. "Is this urgent and about billing?" cannot be answered cleanly. Two questions, one call.
  3. Trusting the label without the probability. Route low-confidence answers to review; that queue is the cheapest quality win available.
  4. Letting a floating alias decide anything that matters. Pin jev-1.13.0, log it next to every threshold.

Measuring the swap

Keep a labelled sample of a few hundred real cases before you migrate, and score both paths on accuracy, calibration (Brier or ECE) and p95 latency. Published comparisons on the same public decision benchmark put the hosted model and its open alternative close enough that your own data decides — see Laya vs Jev and the benchmark table.

Last updated: 2026-09-21 · sources & corrections