If you read the intro to what Jev actually is, you already know it’s a typed decision model rather than a chatbot. This post is about actually getting started with Jev: getting an API key, installing the SDK, and making your first call.
Table of Contents
Get an API Key
The direct TypeSafe API is currently in early access, so sign up on their site and you’ll be issued a key once you’re through. If you don’t want to wait, or you’d rather not manage another provider key directly, Jev is also reachable through gateways you may already use: Vercel’s AI Gateway (via AI SDK 7’s evaluate helper), Cloudflare AI, and OpenRouter. For this walkthrough we’ll assume you have a direct key and export it as an environment variable:
export TYPESAFE_API_KEY="ts_live_..."
Install the SDK
The Python SDK is a single pip install:
pip install typesafe-sdk
The client automatically picks up TYPESAFE_API_KEY from the environment, so you don’t need to pass it explicitly, though you can if you’re managing multiple keys.
Your First evaluate() Call
Every interaction with Jev goes through one method: evaluate(). It takes a state string describing the situation, and a list of questions describing exactly what you want decided. Here’s the simplest possible example – a single yes/no question:
from typesafe_sdk import TypeSafeClient
client = TypeSafeClient()
result = client.evaluate(
state="Comment: 'This tutorial saved me hours, thank you!'",
questions=[
{"type": "noul", "id": "is_spam"},
],
)
print(result)
Run that and you’ll get a response back in well under a second – no streaming, no waiting on token generation, just a direct answer.
Reading the Response
The response is keyed by the id you gave each question. For the example above, it looks roughly like this:
{
"is_spam": {
"answer": false,
"confidence": 0.97
}
}
Two fields matter here. answer is the typed decision itself – a boolean, a chosen option, or a number, depending on the question type. confidence is a probability you can act on programmatically: route low-confidence answers to a human, or a fallback LLM call, instead of trusting them blindly. That’s the piece a normal text-generation API doesn’t give you for free.
A More Realistic Example: Triage
Most real use cases ask more than one question in a single call. Here’s a support-ticket triage example combining a Choice question and a Score question:
result = client.evaluate(
state="Ticket: 'Your app crashed and I lost 3 hours of work. This is unacceptable.'",
questions=[
{"type": "choice", "id": "team", "options": ["billing", "bugs", "feature_requests", "abuse"]},
{"type": "score", "id": "urgency", "min": 1, "max": 5},
{"type": "noul", "id": "needs_human_review"},
],
)
if result["needs_human_review"]["answer"] or result["team"]["confidence"] < 0.6:
escalate_to_human(result)
else:
route_ticket(team=result["team"]["answer"], urgency=result["urgency"]["answer"])
Notice there’s no prompt to tune here – the questions themselves are the interface. If you want a new routing category later, you just add it to the options list.
Common Beginner Mistakes
- Writing state like a chat prompt. You don’t need “Please analyze the following…” framing – Jev isn’t being asked to write anything, just describe the situation plainly.
- Ignoring confidence. A low-confidence answer is Jev’s way of telling you the options didn’t cleanly fit – it’s worth building a fallback path for that from day one.
- Too many options in one Choice question. Keep option lists focused; if you find yourself listing more than 8-10 choices, it’s usually a sign the decision should be split into two questions.
Next in this series, we’ll use exactly this pattern for something higher-stakes: gating destructive commands from an AI coding agent before they ever run.

Leave a Reply
You must be logged in to post a comment.