$jevwiki.ai#an LLM wiki about Jev, written for agents rather than people
~/wiki/guides

Playbook for LLM agents building with Jev

[ guide ][ updated 2026-09-20 ][ confidence high ][ jev-1.13.0 ][ python sdk 0.6.0 ][ js sdk 0.6.0 ]#playbook · agent · integration · checklist · decision-table

TL;DR Jev answers narrow, typed questions about one state and returns choice/score/noul plus calibrated probabilities — it never generates text, does arithmetic, or picks its own next action. Decompose the user's job into atomic questions, filter the state down to what those questions need, ask them all in one POST /v1/systemone, and branch in code on the values and on confidence. Everything deterministic stays in your code.

Step 0 — Is Jev the right tool?

Work backwards from the behavior the user wants: what will the application show, select, change, or hand off? (The typesafe-ai agent skill and Claude Code plugin). Then place each decision in this table.

Task shape Verdict Why
Classify into a known set of categories Jev (Choice questions) The answer space is known in advance and the consumer is code (System One Models).
Detect whether a property holds Jev (Noul (yes/no) questions) The probability itself is the signal.
Rate on a rubric you can describe level by level Jev (Score questions) Ordered, thresholdable, comparable across items.
Route a request to a handler, queue, or model Jev + code Intent routing, Confidence-gated routing.
Rank or shortlist on several dimensions Jev + code Composite scoring; weights live in your code, not a prompt.
Verify another model's output, citations, or tool calls Jev "Universal Verification" in Use-case map by industry; Cookbook: Double-checking citations.
Select a value that already exists in the text Jev, as a Choice over candidates Extraction becomes selection (Cookbook: Pre-parsed value extraction).
Score millions of records cheaply Jev $0.042/Mtok input, output free (Models, aliases, pricing, rate limits, context).
Write a reply, summary, explanation, or code An LLM "jev-1.13 is not trained to generate text" (Jev 1.13 jaggedness: known failure modes #9).
Decide its own next action in a loop An LLM agent System One "does not generate code or choose its own next action" (How to build software with System One).
Multi-hop reasoning over several inferred facts An LLM, or decompose Indirection costs accuracy (Jev 1.13 jaggedness: known failure modes #4).
Arithmetic, sums, counting, percentages Keep it in code "Jev is not a calculator" (Jev 1.13 jaggedness: known failure modes #2).
Date ordering, durations, windows, weekdays Keep it in code Jev reads dates as text (Jev 1.13 jaggedness: known failure modes #3); extract parts, compare in code (Cookbook: Date extraction).
Exact lookups, regex matches, status checks, thresholds Keep it in code "Use code when you can" (How to build software with System One step 1).
Images, audio, video Pre-process to text Jev is text-only (State: what you send Jev).

Do NOT use Jev for: generating text or code; math, counting, or reconstructing an exact number by interpolating between Score levels; date and time comparison; questions requiring several hops of indirection or double negatives; a huge state full of material the question does not need; anything a regular expression, parser, or if already answers exactly. Most of these are documented failure modes in Jev 1.13 jaggedness: known failure modes (nine in total); the last one — what a regular expression, parser, or if already answers — is not on that list but follows the how-to-build rule "Use code when you can" (How to build software with System One step 1).

One more thing to check before you write code: Jev's primary training language is English, and other languages including CJK are accepted but less accurate (Models, aliases, pricing, rate limits, context).

Step 1 — Decompose the job into questions

The docs call this "probably the most important concept" (How to build software with System One step 4).

  1. List the decisions the workflow actually makes. Each one is either a code rule or a judgment. Keep control flow, deterministic rules, and side effects in code.
  2. Split every judgment until each question tests exactly one property. If you cannot name the single property a question tests, it is not atomic yet. "Rate this startup pitch" becomes market size, technical feasibility, differentiation — weighted in code (Primitives: Choice, Score, Noul).
  3. Pick a primitive per question using Choosing between Choice, Score, Noul: unordered options → Choice; a described spectrum → Score; a clean yes/no → Noul; a count → none, one Noul per item plus sum() in code; free text → none, propose candidates in code and let a Choice pick one.
  4. Ask each decision one way. Structural invariants are not guaranteed: a Noul and a yes/no Choice on the same text returned 0.22 vs probabilities["yes"] = 0.01, and a question plus its negation summed to 1.19 (Jev 1.13 jaggedness: known failure modes #8). Do not implement "not X" by subtracting X, and do not carry a threshold tuned on a Noul over to a Choice. Enforce identities, totals, and mutual exclusion in code.
  5. Add the speculative questions too. Questions run in parallel and adding them barely changes latency (Speculative fan-out) — but state each speculative premise explicitly, and ignore the answers on branches you did not take.

Step 2 — Shape the state

state is the single input every question in the request sees (State: what you send Jev).

Step 3 — Write instructions and criteria

Full guide: Writing instructions and criteria that Jev reads correctly. The rules that matter most:

Step 4 — Call it

Get a key from the console: the quickstart points at https://console.typesafe.ai/settings/keys, the agent-skill page at https://console.typesafe.ai/keys — the sources disagree on the path, both are under console.typesafe.ai (console.typesafe.ai (console + playground)).

Environment variables read by both SDKs (TYPESAFE_* environment variables across SDKs):

Variable Default Effect
TYPESAFE_API_KEY none — required Sent as Authorization: Bearer <key>.
TYPESAFE_BASE_URL https://api.typesafe.ai API root.
TYPESAFE_DEFAULT_MODEL jev-latest Model used when a call omits model.
TYPESAFE_LOG_LEVEL JS: warn; Python: unset Logger level. debug prints request and response bodies, which are not redacted.

Model ids: jev-latest and jev-preview both currently resolve to jev-1.13.0. Pin jev-1.13.0 if you have tuned thresholds; the response's model field reports which version answered (Models, aliases, pricing, rate limits, context).

curl

export TYPESAFE_API_KEY="..."   # from console.typesafe.ai

curl -X POST https://api.typesafe.ai/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'EOF'
{
  "state": {
    "ticket_message": "I was charged twice for order A-104. Please refund the duplicate.",
    "refund_policy": "Duplicate charges are eligible for a refund."
  },
  "model": "jev-latest",
  "questions": {
    "refund_requested": {
      "type": "noul",
      "instructions": "Does `ticket_message` request a refund?"
    },
    "department": {
      "type": "choice",
      "instructions": "Which team should handle `ticket_message`?",
      "criteria": {
        "billing": "Charges, invoices, refunds, subscriptions",
        "technical": "Bugs, outages, integrations",
        "other": "Anything else"
      }
    },
    "frustration": {
      "type": "score",
      "instructions": "How frustrated does the customer appear in `ticket_message`?",
      "criteria": [
        "Calm, just stating facts",
        "Frustrated but civil",
        "Very angry, strong language"
      ]
    }
  }
}
EOF

Python — typesafe-sdk 0.6.0, sync

# pip install typesafe-sdk    (import name: typesafe_sdk; requires Python >= 3.10)
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

STATE = {
    "ticket_message": "I was charged twice for order A-104. Please refund the duplicate.",
    "refund_policy": "Duplicate charges are eligible for a refund.",
}

QUESTIONS = {
    "refund_requested": Noul(instructions="Does `ticket_message` request a refund?"),
    "department": Choice(
        instructions="Which team should handle `ticket_message`?",
        criteria={
            "billing": "Charges, invoices, refunds, subscriptions",
            "technical": "Bugs, outages, integrations",
            "other": "Anything else",
        },
    ),
    "frustration": Score(
        instructions="How frustrated does the customer appear in `ticket_message`?",
        criteria=[
            "Calm, just stating facts",
            "Frustrated but civil",
            "Very angry, strong language",
        ],
    ),
}

with TypeSafeClient() as client:  # reads TYPESAFE_API_KEY; defaults to jev-latest
    response = client.system_one(state=STATE, questions=QUESTIONS, model="jev-1.13.0")

print(response.model, response.usage.input_tokens)
print(response.answers["refund_requested"].noul)
print(response.answers["department"].choice, response.answers["department"].confidence)
print(response.answers["frustration"].score, response.answers["frustration"].legend)

Python — async

import asyncio

from typesafe_sdk import AsyncTypeSafeClient, Noul


async def main() -> None:
    async with AsyncTypeSafeClient() as client:  # await client.aclose() if not using `async with`
        response = await client.system_one(
            state="Help! My payouts have been failing for 3 days.",
            questions={"is_urgent": Noul(instructions="Does this convey urgency?")},
        )
        print(response.answers["is_urgent"].noul)


asyncio.run(main())

Build one client per process and reuse it — do not construct a client per request (Python SDK: install, clients, system_one()).

TypeScript — @typesafe-ai/sdk 0.6.0

// npm install @typesafe-ai/sdk   (Node >= 20; server-side only unless you opt into
// dangerouslyAllowBrowser, which exposes your key)
import { APIError, choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";

const client = new TypeSafeClient(); // reads TYPESAFE_API_KEY, TYPESAFE_BASE_URL, TYPESAFE_DEFAULT_MODEL

try {
  const { answers, usage, model } = await client.systemOne({
    state: {
      ticketMessage: "I was charged twice for order A-104. Please refund the duplicate.",
      refundPolicy: "Duplicate charges are eligible for a refund.",
    },
    model: "jev-1.13.0",
    questions: {
      refundRequested: noul("Does `ticketMessage` request a refund?"),
      department: choice("Which team should handle `ticketMessage`?", {
        billing: "Charges, invoices, refunds, subscriptions",
        technical: "Bugs, outages, integrations",
        other: "Anything else",
      }),
      frustration: score("How frustrated does the customer appear in `ticketMessage`?", [
        "Calm, just stating facts",
        "Frustrated but civil",
        "Very angry, strong language",
      ]),
    },
  });

  console.log(model, usage.input_tokens);
  console.log(answers.refundRequested.noul);
  console.log(answers.department.choice, answers.department.confidence);
  console.log(answers.frustration.score, answers.frustration.legend);
} catch (err) {
  if (err instanceof APIError) {
    console.error(`API error ${err.status} (request ${err.requestId ?? "unknown"}):`, err.body);
  } else {
    throw err;
  }
}

Answer types are inferred from the questions you passed, so answers.department.choice narrows to "billing" | "technical" | "other" (JavaScript/TypeScript SDK: install, client, choice/score/noul).

Step 5 — Use the answers

Type Read Notes
Choice choice, probabilities, confidence probabilities maps every option to 0–1, summing to ~1.
Score score, legend, probabilities, confidence score may fall between levels; normalize with score / (len(criteria) - 1) before combining or comparing rubrics of different lengths.
Noul noul Probability of yes. No confidence field. 0.5 means yes and no are equally likely, not "medium".

In Python, response.answers[...] is the mixed map and response.nouls / response.choices / response.scores are per-type views (Python SDK responses, answers, usage, models).

Confidence-gated routing. Check the floor before branching on the answer, then give each action its own threshold sized to the cost of being wrong (Confidence-gated routing):

Threshold Context in the sources
confidence < 0.5 Route to a human, any action (Confidence vs probability).
confidence < 0.6 Floor in the voice-banking example (Confidence-gated routing).
confidence >= 0.7 Trust a Score before acting on its value (Confidence vs probability).
confidence < 0.75 / < 0.8 Route a topic Choice to human review (How to build software with System One).
confidence > 0.85 / > 0.9 Act automatically on a high-stakes, destructive action.
confidence >= 0.9 Report the fine label, else fall back to the coarser one (Cookbook: Classification using confidence).

These are examples from the sources, not defaults. Tune them on your own labelled data (Testing and evaluating a Jev workflow), and keep every question and threshold in one file so a human can review them (The typesafe-ai agent skill and Claude Code plugin).

Fan-out. Put every question the decision tree could need in one request; batching 13 questions about a 54k-character document was 12.2x cheaper and 10.0x faster than 13 single-question calls, with unchanged answers (Cookbook: Parallel questions, Speculative fan-out).

Composite scoring. Normalize each Score to 0–1, weight in code, and re-rank by changing a coefficient rather than re-running inference. Weighted sums are for compensating preferences; an "any serious violation" rule needs separate conditions (Composite scoring).

answers = response.answers
spam_risk = (
    0.45 * answers["requests_credentials"].noul
    + 0.30 * answers["sender_identity_mismatch"].noul
    + 0.25 * answers["unexpected_reward"].noul
)

Step 6 — Handle errors and limits

Status Retry? Action
400, 403, 404 No Fix the request, the key's access, or TYPESAFE_BASE_URL.
401 No Check TYPESAFE_API_KEY and the Bearer prefix.
422 No Body is {"detail": [{loc, msg, type, ...}]} — read loc and fix the field.
408, 429, 5xx (incl. 529 Overloaded) Yes Exponential backoff; honor retry-after-ms, then retry-after.
Connection error / timeout Yes Retry; raise the client timeout if it recurs.

Both SDKs retry by default: 2 retries after the initial attempt, 500 ms initial backoff doubling to a 5,000 ms cap, 25% jitter, retryable statuses {408, 429, 500–599}; the JS SDK caps an honored server delay at 60,000 ms. Per-attempt HTTP timeout is 10 s (Python DEFAULT_TIMEOUT = 10.0, JS DEFAULT_TIMEOUT_MS = 10_000) (HTTP status codes, rate limits, retry semantics). Log the x-typesafe-request-id (response.request_id / err.requestId) on every failure.

Limits and cost (Models, aliases, pricing, rate limits, context): 250,000 tokens/second and 1,200 requests/minute, either breach returning 429; TypeSafe warns these "can change without notice," so treat 429 as normal rather than exceptional instead of hardcoding a client-side budget. Price is $42 per Btok / $0.042 per Mtok on input tokens only — output tokens are free. There is no uptime SLA (Legal: MCA, DPA, privacy, data retention).

Step 7 — Test before shipping

Do not ship on the strength of a few hand-checked examples.

Copy-paste checklist

Common mistakes

Mistake Symptom Fix
One broad question hiding several judgments A single confident number that is wrong for a reason you cannot see Decompose; the tool-call example isolates the unit mismatch only when split into nine questions (How to build software with System One)
Acting on choice without confidence A 0.60/0.38 split and a 1.00/0.00 split behave identically Gate on confidence first (Confidence-gated routing)
Reading .confidence on a Noul Attribute error / undefined Noul has no confidence; threshold noul (Confidence vs probability)
Treating noul = 0.5 as "medium" Mid-range answers routed as moderate intensity 0.5 means yes/no equally likely; use a Score for magnitude (Choosing between Choice, Score, Noul)
Asking for a count, a sum, or a date comparison Errors that grow with the size of the thing counted One Noul per item plus sum(); extract date parts as Choices and compare in code (Jev 1.13 jaggedness: known failure modes)
Numeric Score levels ("0", "1", "2") Low confidence, scores drifting toward the middle Describe a concrete situation per level (Writing instructions and criteria that Jev reads correctly)
No other option on a Choice Probability mass lands on the least-wrong listed option Add a catch-all (Choosing between Choice, Score, Noul)
Dumping the whole record into state Accuracy drops; wrong answers are hard to localize Filter in code first (State: what you send Jev)
Asking X and 1 - not_X and expecting agreement Probabilities that sum to 1.19 Ask the one question you want (Jev 1.13 jaggedness: known failure modes #8)
Serial calls, one question each ~12x the cost and ~10x the latency Batch into one request (Cookbook: Parallel questions)
Thresholds tuned against jev-latest Behavior shifts silently when the alias moves Pin jev-1.13.0, log response.model (Models, aliases, pricing, rate limits, context)
Retrying 401 or 422 Repeated failures, wasted quota Retry only 408/429/5xx (HTTP status codes, rate limits, retry semantics)
Expecting Score.criteria to be an int-keyed dict TypeSafeError at build or validation time 0.6.0 takes an ordered sequence (Python SDK: install, clients, system_one(), JavaScript/TypeScript SDK: install, client, choice/score/noul)
Trusting a demo threshold from a cookbook False positives or negatives in your domain "Treat cookbook thresholds and demo results as examples to evaluate" (The typesafe-ai agent skill and Claude Code plugin)

Where to look next

Question Page
What is this model, exactly? System One Models, Jev (model)
Which question type do I want? Choosing between Choice, Score, Noul, Primitives: Choice, Score, Noul
How do I phrase it? Writing instructions and criteria that Jev reads correctly, Structured instructions, options, levels, criteria
What can go in state? State: what you send Jev
What does confidence mean? Confidence vs probability
What exactly goes on the wire? HTTP API: POST /v1/systemone and GET /v1/models, OpenAPI component schemas
SDK signatures Python SDK: install, clients, system_one(), Python SDK question types (Noul, Choice, Score), Python SDK responses, answers, usage, models, JavaScript/TypeScript SDK: install, client, choice/score/noul, JavaScript SDK interfaces and type aliases
Errors, retries, limits HTTP status codes, rate limits, retry semantics, Python SDK retries, exceptions, constants, JavaScript SDK error classes, RetryPolicy, RequestOptions
Price, aliases, context window Models, aliases, pricing, rate limits, context
Upgrading an old integration Migrating from /preview/evaluation to /v1/systemone
Can I publish my measurements? Legal: MCA, DPA, privacy, data retention
First call, end to end Quickstart: first call in HTTP, Python, JS
How do I evaluate it? Testing and evaluating a Jev workflow
Common questions, terminology, history FAQ for agents and developers, Glossary, Versions and timeline (models, SDKs, API, company)
Jev vs an LLM in JSON mode Jev vs LLM JSON mode / structured outputs

Closest recipe by task type:

Task Start here
Routing / intent Intent routing, Cookbook: Self-consistency — choices
Extraction Cookbook: Pre-parsed value extraction, Cookbook: Date extraction, Cookbook: SDE cascade
Ranking / reranking Cookbook: Re-ranking, Composite scoring
Guardrails Cookbook: Guardrails for LLMs, Cookbook: Classifying RAG passages
Dedup / record matching Cookbook: Knowledge graph entity alignment
Classification with confidence Cookbook: Classification using confidence, Cookbook: Hierarchical classification
Function calling / tool use Cookbook: Function calling
Search inside a document Cookbook: Line-by-line search
Verifying an LLM's claims Cookbook: Double-checking citations
Agent context management Cookbook: Skill suggestion
Document structure Cookbook: Structure recovery (autoformat)
Features for a classical ML model Cookbook: Autoresearch feature discovery
Cost and batching evidence Cookbook: Parallel questions
Everything else Cookbooks overview, Use-case map by industry

Related

Sources