Introduction.
Jev answers typed questions with calibrated probabilities. JevChain composes those answers into programs you can read, type-check and replay.
What Jev is#
Jev is TypeSafe's classification model. It doesn't write prose. You send it some state (text, or JSON) and a set of typed questions, and it answers every question at once with a calibrated probability distribution, usually in tens to low hundreds of milliseconds.
POST https://api.typesafe.ai/v1/systemone
{
"model": "jev-latest",
"state": "i was charged twice, please help",
"questions": {
"team": { "type": "choice", "criteria": { "billing": null, "bug": null, "vibes": null } },
"urgent": { "type": "noul", "instructions": "Is the user blocked right now?" }
}
}{
"team": { "type": "choice", "choice": "billing",
"probabilities": { "billing": 0.94, "bug": 0.05, "vibes": 0.01 },
"confidence": 0.81 },
"urgent": { "type": "noul", "noul": 0.22 }
}- One endpoint:
POST https://api.typesafe.ai/v1/systemone, bearer-token auth. - Three question types:
choice(pick a label),score(rate on an ordered rubric) andnoul(yes or no, as p(yes)). See Questions. - Cheap: jev-1.13 lists at $0.042 per million input tokens. Output tokens are free, because the output is a handful of numbers.
What JevChain adds#
One Jev call answers questions. Real decisions are several of them in a row, with your code in between. JevChain is the small, typed layer that composes those calls into a graph and writes down everything that happened.
- Typed composition.
route,gate,parallel,cascade,step,chain. Choice labels come back as literal unions, a route with a missing branch doesn't compile, andchain(a, b)only compiles whena's output fitsb's input. - Traces. Every run leaves plain JSON: each call's state, questions and full distributions, every decision with the branches it didn't take, tokens, cost, latency, retries. Stream it live, diff two runs, draw it.
- Batching. Asks against the same state issued in the same tick are merged into one HTTP request. Jev reads the state once and answers everything, so fanning out is nearly free.
- No dependencies. TypeScript and
fetch. Retries, timeouts, concurrency limits and cancellation are built in.
Thirty-second quickstart#
- 1install itpnpm add jevchain
- 2give it a keyexport TYPESAFE_API_KEY=...
createJev()readsTYPESAFE_API_KEYby default. In a browser, don't ship the key; point the client at a proxy instead (see Proxy & BYOK). - 3write a chain, run ittriage.ts
import { createJev, route, choice, emit } from "jevchain"; const triage = route("triage", { ask: choice("What is this message about?", { billing: "money, invoices, refunds", bug: "something is broken", vibes: "no actionable content, just vibes", }), branches: { billing: emit("→ billing"), bug: emit("→ on-call"), vibes: emit("reply with a gif"), }, }); const jev = createJev(); // reads TYPESAFE_API_KEY const result = await jev.run(triage, "i was charged twice, please help"); if (result.status === "ok") console.log(result.output); // "→ billing" console.log(result.trace.spans[0]?.decision?.summary); // Went to "billing" with 94%, a landslide over "bug" at 5% (confidence 0.81).
The mental model#
So a chain reads like a flowchart where every diamond is a question with a number attached. Because the structure is plain data, the same definition drives the runtime, the trace, the JSON format and the diagrams on this site. Here's a complete one: a support desk for haunted appliances, with a nested safety gate and a low-confidence escape hatch.
route picks the team; its confidence decides whether to trust that pick at all. The paranormal branch nests a gate and a second route. Pink-marked nodes are the ones that call Jev.My toaster whispers my name at 3am and the bread comes out cold.
Where next#
- Questions: the three types and what their answers look like.
- route and gate: the two decisions you'll use most.
- Traces: what a run leaves behind, and how to read it.
- The gallery: five silly chains, each teaching one serious pattern.