# Jev Wiki > Unofficial, agent-maintained knowledge base about Jev, TypeSafe AI's System One model, and everything an LLM agent needs to build software with it. Plain Markdown with YAML frontmatter; wikilinks [[dir/slug]] resolve to https://jevwiki.ai/raw/wiki/dir/slug.md. Covers: Jev (TypeSafe AI's System One model): concepts, the HTTP API (/v1/systemone, /v1/models), OpenAPI schemas, models/pricing/rate limits, Python SDK (typesafe-sdk) and JavaScript SDK (@typesafe-ai/sdk) references, architectural patterns, all 18 official cookbooks, guides, the agent skill, the system-one-adapter, company/team/blog/press, legal terms. Not covered: Anything after the current-as-of date below, TypeSafe's private roadmap, benchmark claims beyond what TypeSafe and cited press publish, other vendors' structured-output products in depth. Use the live docs at https://docs.typesafe.ai/llms.txt for anything newer. Current as of: 2026-09-17 (docs snapshot), jev-1.13.0, typesafe-sdk 0.6.0, @typesafe-ai/sdk 0.6.0 ## Route by task (read these, skip the rest) Every entry below shows an estimated token size so you can budget before fetching. Do NOT load llms-full.txt for a single task; it is the whole corpus. - **Build something with Jev:** [guides/agent-integration-playbook](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) (~7.0k tok) → [reference/http-api](https://jevwiki.ai/raw/wiki/reference/http-api.md) (~5.0k tok) → [concepts/jaggedness-jev-1-13](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) (~3.3k tok) — then one SDK page (reference/python-sdk or reference/javascript-sdk) and the closest cookbook - **Assess a project: "could Jev help here?":** [ideas/consult](https://jevwiki.ai/raw/wiki/ideas/consult.md) (~2.0k tok) → [ideas/patterns](https://jevwiki.ai/raw/wiki/ideas/patterns.md) (~2.4k tok) — then ONE domain page the index points to (ideas/patterns-agents, ideas/patterns-interface, ideas/patterns-data or ideas/patterns-business); open ideas/field-reports or ideas/community-repos only when a pattern points you there - **Look up an exact contract, limit or price:** [reference/http-api](https://jevwiki.ai/raw/wiki/reference/http-api.md) (~5.0k tok) → [reference/models-and-pricing](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) (~2.7k tok) → [reference/rate-limits-and-errors](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) (~3.6k tok) - **Write good instructions and criteria:** [guides/writing-instructions-and-criteria](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) (~4.6k tok) → [guides/choosing-a-primitive](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) (~3.4k tok) Tiers: pages under ideas/ are community-sourced (source_tier: community, confidence capped at medium). When they conflict with reference/ or concepts/ pages, the reference pages win. Start with the agent playbook: https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md — then the reference pages. Every page is served raw at /raw/wiki/.md and as HTML at /wiki/.md. Full corpus in one fetch: https://jevwiki.ai/llms-full.txt. Machine registry: https://jevwiki.ai/index.json. - [Playbook for LLM agents building with Jev — START HERE](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) - [README: how to use this wiki](https://jevwiki.ai/raw/README.md) - [Schema and maintenance rules](https://jevwiki.ai/raw/CLAUDE.md) - [Jev Wiki — Master Index](https://jevwiki.ai/raw/wiki/index.md): Catalog of every page in the wiki, one line each, grouped by section. Generated by scripts/build.mjs. - [Activity log](https://jevwiki.ai/raw/wiki/log.md): Append-only log of ingestion, lint, and refresh activity. ## Concepts - [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) (~3.4k tok): instructions, Choice option descriptions, Score levels and Noul true/false all accept JSON: string, object, array or null (EntryType). - [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md) (~4.6k tok): Choice picks one option from a fixed set: send type/instructions/criteria, get back choice, probabilities over every option, and confidence. - [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) (~2.3k tok): confidence is a 0-1 statistic derived from an answer's probabilities distribution; Choice and Score carry it, Noul does not. - [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) (~6.3k tok): Build a normal software workflow and insert System One only where AI is needed: narrow typed questions, composed in code. - [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) (~3.3k tok): Nine documented failure modes of jev-1.13 — literal reading, math, dates, indirection, big states, adversarial text, contradictions, invariants, generation — with the mitigation for each. - [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md) (~1.7k tok): Why TypeSafe post-trains with RLCD for calibrated decisions instead of RLHF/RLVR for generated text. - [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) (~2.3k tok): Noul asks one yes/no question and returns a single number, the probability that the answer is yes; criteria are optional true/false clarifications. - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) (~3.0k tok): The three Jev question types (Choice, Score, Noul), the typed answers they return, how to pick one, and how to batch many questions in one request. - [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) (~5.1k tok): Score rates a state against an ordered array of described levels and returns a probability-weighted position, the legend, per-level probabilities, and confidence. - [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) (~1.7k tok): State is the content Jev evaluates: a string, JSON object, or array of text, shared by every question in one request. - [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md) (~2.8k tok): System One models make fast, typed, calibrated decisions software can consume directly; Jev is TypeSafe's first one. - [Use-case map by industry](https://jevwiki.ai/raw/wiki/concepts/use-case-map.md) (~3.2k tok): Scannable map of where Jev fits: five capability categories, eighteen industry/function areas, and ten decision shapes. - [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md) (~4.0k tok): TypeSafe's four workflow evals: same harness for every model, reference labels from GPT-6 Astra + Claude Fable 5.1, source of 193.6x/444.6x. ## Reference - [The typesafe-ai agent skill and Claude Code plugin](https://jevwiki.ai/raw/wiki/reference/agent-skill.md) (~5.2k tok): Install, update, and invoke the typesafe-ai agent skill (Claude Code plugin typesafe 0.5.7, MIT), plus a faithful digest of the guidance SKILL.md gives agents. - [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md) (~2.8k tok): Exactly four TYPESAFE_* environment variables are read by the SDKs: API_KEY, BASE_URL, DEFAULT_MODEL, LOG_LEVEL — both SDKs read all four. - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) (~5.0k tok): Complete wire contract for POST https://api.typesafe.ai/v1/systemone and GET /v1/models: auth, request body, question and answer shapes, usage, errors. - [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) (~6.9k tok): @typesafe-ai/sdk 0.6.0: install, TypeSafeClient config and defaults, systemOne(), choice/score/noul builders, APIPromise, models.list(), logging. - [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md) (~1.8k tok): @typesafe-ai/sdk releases: 0.5.7 initial public release, 0.6.0 (2026-09-15) makes Score.criteria an ordered sequence — the one breaking change. - [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) (~5.2k tok): Error hierarchy of @typesafe-ai/sdk 0.6.0, status-to-class mapping, RetryPolicy defaults (2 retries, 500ms/5s backoff, 0.25 jitter) and RequestOptions. - [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) (~6.0k tok): Every interface, type alias and exported variable in @typesafe-ai/sdk 0.6.0, with per-property type/required/default tables and generics examples. - [Legal: MCA, DPA, privacy, data retention](https://jevwiki.ai/raw/wiki/reference/legal-and-data.md) (~5.1k tok): Developer-facing summary of TypeSafe's MCA, DPA, and Privacy Policy: no training on Input, telemetry carve-out, retention, sub-processors, acceptable use, no uptime SLA. - [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md) (~3.7k tok): Every delta between the preview evaluation endpoint and the stable v1 API, with before/after examples, plus the typesafe-client to typesafe-sdk rename table. - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) (~2.7k tok): Jev 1.13 model ID, aliases, $42/Btok pricing with free output tokens, 250k tok/s and 1,200 rpm limits, 64k/32k context rule, and text-only input. - [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md) (~4.8k tok): Every component schema in TypeSafe's OpenAPI 3.1.0 document (info version 0.2.0): properties, types, requiredness, constraints, and examples. - [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) (~5.7k tok): typesafe-sdk 0.6.0: install, TypeSafeClient/AsyncTypeSafeClient constructor params, system_one() kwargs, models resource, env vars, logging, and the full export list. - [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md) (~1.8k tok): typesafe-sdk release history: 0.0.1a0 placeholder, 0.5.7 initial public release (2026-09-14), 0.6.0 (2026-09-15) with the Score.criteria breaking change. - [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md) (~3.1k tok): Every field of Noul, Choice and Score in typesafe-sdk 0.6.0, their TypedDict equivalents, JSONContent typing, client-side validation, and the 0.6.0 Score.criteria breaking change. - [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md) (~3.4k tok): SystemOneResponse fields and the .nouls/.choices/.scores views, every answer attribute, Usage, request_id and raw_http_response, plus ListModelsResponse and ModelMetadata. - [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md) (~4.7k tok): RetryPolicy fields and defaults, which statuses and exceptions are retried, backoff and Retry-After handling, the full exception hierarchy with attributes, timeouts, and public constants. - [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) (~3.6k tok): One table mapping every HTTP status to its meaning, Python exception, JS error class, retryability, and the recommended client action. - [system-one-adapter: LLM-backed drop-in for TypeSafeClient](https://jevwiki.ai/raw/wiki/reference/system-one-adapter.md) (~5.0k tok): system-one-adapter answers typesafe_sdk questions with an OpenAI or Anthropic LLM instead of Jev, so you can compare cost, speed, and intelligence on the same code. ## Patterns - [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) (~2.1k tok): Break a ranking judgment into independent Score dimensions, normalize each to 0–1, and combine them with weights your code owns and can retune. - [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) (~2.2k tok): Treat confidence as a second decision axis: one floor below which nothing is automated, then a per-action threshold sized to the consequences of being wrong. - [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) (~2.2k tok): Put every question your decision tree could need into one call, including speculative ones, and let code discard the irrelevant answers. - [Intent routing](https://jevwiki.ai/raw/wiki/patterns/intent-routing.md) (~2.6k tok): Classify the request with one cheap Jev call, then invoke the cheapest adequate handler: deterministic code, a specialist LLM, or a human. - [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) (~1.8k tok): Catalog of TypeSafe's four architectural patterns — fan-out, confidence routing, composite scoring, intent routing — and when to reach for each. ## Cookbooks - [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md) (~4.5k tok): Rebuild Markdown from de-formatted plain text in two requests: Nouls stitch hard-wrapped lines, then Choices classify each block; code renders every character from the input. - [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md) (~4.7k tok): An LLM proposes Jev questions, Jev answers them per row to build numeric columns, CatBoost trains and reports back: 38 questions after five rounds reach 1.77 held-out RMSE on wine scores. - [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md) (~2.8k tok): One Choice question decides whether a quote's surrounding section supports, contradicts, or says nothing about an LLM's claim; a string match catches fabricated quotes first. - [Cookbook: Classification using confidence](https://jevwiki.ai/raw/wiki/cookbooks/classification-using-confidence.md) (~2.9k tok): Classify SEC filings into 75 SIC industry groups with one Choice; when confidence < 0.9, report the broader division instead — 40% correct becomes 70%, at no extra call. - [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md) (~3.6k tok): Four Noul questions per retrieved query-passage pair, routed by ordered thresholds, decide what reaches the generator as evidence, as conflict, or not at all. - [Cookbook: Self-consistency — choices](https://jevwiki.ai/raw/wiki/cookbooks/consistency-choice.md) (~4.3k tok): Runs an 8-Choice moderation rubric 15 times across Jev and six LLM conditions; a 0.60 top-probability floor lifts Jev's decision agreement from 90.8% to 99.2% at 74.2% automation. - [Cookbook: Self-consistency — nouls](https://jevwiki.ai/raw/wiki/cookbooks/consistency-noul.md) (~3.7k tok): Runs a 14-Noul claims rubric 15 times against Jev and six LLM conditions; Jev's mean probability std dev is 0.0102 at 111ms per call, and an uncertain band routes 0.30-0.70 to a human. - [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md) (~3.9k tok): Seven Choice questions read a date's parts off a document in one call; code does all the calendar math and gates on the weakest part's confidence. - [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md) (~3.0k tok): One three-level Score decides merge / curate / leave-unlinked for 450 candidate entity pairs, with three Nouls riding along to tell the curator which field disagrees. - [Cookbook: Function calling](https://jevwiki.ai/raw/wiki/cookbooks/function-calling.md) (~2.9k tok): Map typed Python functions to Jev Choice/Noul questions so a natural-language command becomes a validated call with a per-argument confidence. - [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) (~2.9k tok): Walk a deep taxonomy to a leaf by asking one Choice per sibling set, and keep K paths alive with a geometric-mean beam search instead of a greedy walk. - [Cookbook: Guardrails for LLMs](https://jevwiki.ai/raw/wiki/cookbooks/llm-guardrails.md) (~3.1k tok): Screen every LLM input and output with one Jev request: four hazard Nouls plus a severity Score, then route pass / review / block / support on thresholds you own. - [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md) (~3.4k tok): Catalog of all 18 TypeSafe cookbooks — goal, primitives and domain each — plus how a cookbook is structured and why the published pip line does not work. - [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md) (~3.1k tok): Batching 13 questions about one 54k-character document into a single Jev call was 12.2x cheaper and 10.0x faster than 13 single-question calls, with identical answers. - [Cookbook: Pre-parsed value extraction](https://jevwiki.ai/raw/wiki/cookbooks/pre-parsed-value-extraction.md) (~2.7k tok): A recall-tuned regex finds candidate spans, a Jev Choice over those exact spans picks the one the question asks for, and code copies it verbatim and normalizes it. - [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md) (~2.6k tok): BM25 builds a 30-candidate shortlist per CLERC query, then one Noul per query-candidate pair re-sorts it: top-1 rises 5% to 18%, top-10 38% to 62% for $0.0645. - [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md) (~4.0k tok): Extract with a cheap model, verify every field with a battery of Jev Nouls framed so true means wrong, and escalate to a reasoning model only when a flag fires. - [Cookbook: Line-by-line search](https://jevwiki.ai/raw/wiki/cookbooks/semantic-find.md) (~2.4k tok): Tag a document's lines with ids, rank them with one Choice over those ids, and pair it with a Noul that says whether the document answers the query at all. - [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md) (~3.8k tok): Two Jev requests per agent turn — rank 182 skills then re-read the top three — cut wrong skill loads from 16.8% to 7.3% and needless loads from 9.8% to 4.0%. ## Guides - [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) (~7.0k tok): Seven-step playbook for an agent told 'use Jev for X': decide, decompose, shape state, write questions, call, consume, handle errors, test. - [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) (~3.4k tok): Decision table mapping question shape to Choice, Score or Noul, the anti-patterns for each, and how to decompose a complex judgment into several primitives. - [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) (~3.6k tok): Get a key at console.typesafe.ai, export TYPESAFE_API_KEY, and make your first POST /v1/systemone call in curl, Python, or TypeScript. - [Smart home assistant demo walkthrough](https://jevwiki.ai/raw/wiki/guides/smart-home-demo.md) (~2.3k tok): TypeSafe's smart home demo: one speculative fan-out per utterance routes device commands, while an LLM handles compound splitting and conversational fallback. - [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) (~4.3k tok): Measure accuracy, calibration, repeatability, latency and cost on your own labelled set; pick thresholds from confidence buckets; regression-test jaggedness. - [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) (~4.6k tok): How to phrase instructions and criteria for each question type, with before/after rewrites for literal reading, negation, numbers and dates, plus an edge-case testing loop. ## Ideas (community) - [Community repos: what people built and how they use Jev](https://jevwiki.ai/raw/wiki/ideas/community-repos.md) (~2.6k tok): Index of 58 third-party Jev repos, one line each, split across two domain pages, plus reusable designs and a vetting checklist. - [Consult guide: could Jev help this project?](https://jevwiki.ai/raw/wiki/ideas/consult.md) (~2.0k tok): Procedure for an agent asked 'here is my project, could Jev help?': what to read (10-15k tokens), how to find and filter decisions, and the shortlist format to return. - [Field reports: independent evaluations, critiques, open replicas](https://jevwiki.ai/raw/wiki/ideas/field-reports.md) (~3.4k tok): What independent testers measured in Jev's first week: repeatable bounded decisions, weak standalone browser control, and probe-measured order and option-set sensitivity. - [Measurements, access routes and open replicas](https://jevwiki.ai/raw/wiki/ideas/measurements.md) (~3.0k tok): Numbers measured with Jev — cost, latency, calibration, token accounting, vendor harness figures — plus access routes and replica trust notes. Every figure is one run; re-measure yours. - [Ideas section overview](https://jevwiki.ai/raw/wiki/ideas/overview.md) (~0.8k tok): One-screen map of the community-tier ideas section: which index or domain page to open for which question, and how far to trust them. - [Decision patterns from the community (with fit verdicts)](https://jevwiki.ai/raw/wiki/ideas/patterns.md) (~2.4k tok): Index of all 37 community decision patterns (ID, primitive, fit verdict, page), routing by project type to one of four domain pages, retrofit order, and anti-patterns. - [Patterns: agent internals, context and coding agents](https://jevwiki.ai/raw/wiki/ideas/patterns-agents.md) (~4.4k tok): P01-P11 plus P35-P37: community decision patterns for agent loops, model and security routing, context, memory, coding agents and self-compiling workflows, each with a fit verdict. - [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md) (~4.5k tok): Eleven community decision patterns for GTM, content, support and ops — lead scoring, next-best action, churn, draft QA, SEO, triage, approvals — each with a fit verdict. - [Patterns: judging, search, documents, real-time and markets](https://jevwiki.ai/raw/wiki/ideas/patterns-data.md) (~3.0k tok): P15-P18 and P24-P27: community decision patterns for judging, moderation, search and ranking, corpus labelling, documents, transcripts, devices and markets, with fit verdicts. - [Patterns: browser, computer use, voice and product UI](https://jevwiki.ai/raw/wiki/ideas/patterns-interface.md) (~1.3k tok): Community patterns where Jev picks the next on-screen action or labels items inside a product UI: browser agents, site-exposed tools, desktop/mobile/voice control, in-UI classifiers (P12-P14, P34). - [Repos: coding agents, orchestration, memory, browser and computer use, integrations](https://jevwiki.ai/raw/wiki/ideas/repos-agents.md) (~4.4k tok): 32 community repos that put Jev inside a coding agent, an orchestrator, a browser or computer-use loop, or an MCP/CLI integration surface. - [Repos: data, documents, judging, real-time, markets, business apps, replicas](https://jevwiki.ai/raw/wiki/ideas/repos-apps.md) (~3.8k tok): 23 community repos that point Jev at rows, documents, media, live simulations, markets, business questions — plus the open replicas of the interface. ## Entities - [Blog: Lies, Damned Lies, and Benchmarks](https://jevwiki.ai/raw/wiki/entities/blog-antibenchmaxxing.md) (~1.7k tok): 2026-09-11 post against benchmaxxing, ending in TypeSafe's commitment to publish no standard benchmark table and to retire dated eval snapshots. - [Blog: The Bitterest Lesson](https://jevwiki.ai/raw/wiki/entities/blog-bitterest-lesson.md) (~1.4k tok): 2026-09-10 post arguing the ML priority order is doing the right task > data > compute > algorithms, using InstructGPT vs GPT-3 as the proof. - [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md) (~2.6k tok): Digest of TypeSafe's launch post: System One vs LLM comparison table, price/speed claims, the evidence section, and the caveats the post states itself. - [Blog: AI: too good to be true, too bad to be useful (2026-06-19)](https://jevwiki.ai/raw/wiki/entities/blog-too-good-to-be-true.md) (~0.7k tok): Stub: the body of this 2026-06-19 TypeSafe post was not captured (JS-rendered); only title, date, category, and the homepage teaser are known. - [typesafe-ai GitHub organisation and repos](https://jevwiki.ai/raw/wiki/entities/github-repos.md) (~2.3k tok): The github.com/typesafe-ai org: two SDKs, the agent skill marketplace, the System One adapter, plus infra repos and two forks. - [Jev (model)](https://jevwiki.ai/raw/wiki/entities/jev.md) (~1.6k tok): Jev is TypeSafe's first System One model: text in, typed decisions with calibrated probabilities out, $0.042/MTok input, 64k context, 70-500 ms. - [Manifesto: Composable AI — Build Prod, Not God](https://jevwiki.ai/raw/wiki/entities/manifesto.md) (~1.7k tok): TypeSafe's manifesto argues the bottleneck is composability, not intelligence, and lays out a three-step plan to make AI a dependable software primitive. - [Press and third-party coverage](https://jevwiki.ai/raw/wiki/entities/press-and-coverage.md) (~3.5k tok): Outlet-by-outlet digest of Jev's launch coverage (2026-09-15/16), separating TypeSafe's claims from each outlet's own assertions and caveats. - [Founders and team](https://jevwiki.ai/raw/wiki/entities/team.md) (~1.6k tok): TypeSafe AI's three founders (Diogo Almeida CEO, Sasha Sheng COO, Erik Gafni CTO), the team's stated culture and values, and the SDK maintainers. - [TypeSafe AI (company)](https://jevwiki.ai/raw/wiki/entities/typesafe-ai.md) (~2.5k tok): TypeSafe AI, Inc. is a San Francisco frontier AI lab that left stealth on 2026-09-15 with $40M led by DCVC and Jev, its first System One model. - [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) (~1.1k tok): console.typesafe.ai is TypeSafe's Web Interface: log in with Google or an email code, try Jev in the Playground, and mint API keys. ## Syntheses - [FAQ for agents and developers](https://jevwiki.ai/raw/wiki/syntheses/faq.md) (~4.9k tok): Forty answers about Jev — what it is, the API, the SDKs, design, confidence, limits and pricing, company and legal — each linked to the page carrying the detail. - [Glossary](https://jevwiki.ai/raw/wiki/syntheses/glossary.md) (~4.7k tok): Sixty-nine Jev, TypeSafe, API, SDK and evaluation terms defined in one or two sentences, alphabetical, each linked to the page with the full contract. - [Jev vs LLM JSON mode / structured outputs](https://jevwiki.ai/raw/wiki/syntheses/jev-vs-llm-structured-outputs.md) (~4.3k tok): What Jev gives you that an LLM in JSON mode does not (and vice versa), a row-by-row comparison, when to pick each, how to combine them, and how to benchmark the pair honestly. - [Versions and timeline (models, SDKs, API, company)](https://jevwiki.ai/raw/wiki/syntheses/version-timeline.md) (~4.0k tok): Every datable fact in the wiki on one axis: company, model versions, API, both SDKs, the plugin and adapter, legal documents, repo commits, and where the dates disagree. ## Upstream sources - [TypeSafe docs llms.txt](https://docs.typesafe.ai/llms.txt) - [TypeSafe docs llms-full.txt](https://docs.typesafe.ai/llms-full.txt) - [OpenAPI spec](https://api.typesafe.ai/openapi.json) - [typesafe-ai on GitHub](https://github.com/typesafe-ai) --- # FULL CORPUS Each page below begins with a line `` followed by its frontmatter and body. Wikilinks have been resolved to absolute URLs. --- title: "Jev Wiki — Master Index" type: index tags: [index] created: 2026-09-17 updated: 2026-09-21 confidence: high sources: [] summary: "Catalog of every page in the wiki, one line each, grouped by section. Generated by scripts/build.mjs." --- # Jev Wiki — Master Index > **TL;DR** 88 content pages (plus this index and the log) about Jev, TypeSafe AI's System One model. Snapshot of upstream sources: 2026-09-17. Model: jev-1.13.0; typesafe-sdk 0.6.0; @typesafe-ai/sdk 0.6.0. New here? Read [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) first, then [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) or the SDK reference, then [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md). This file is generated from page frontmatter by `node scripts/build.mjs`; edit the pages, not this list. Maintenance log: [Activity log](https://jevwiki.ai/raw/wiki/log.md). ## Guides (6) | Page | Summary | ~Tokens | Updated | Conf. | |---|---|---|---|---| | [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) | Seven-step playbook for an agent told 'use Jev for X': decide, decompose, shape state, write questions, call, consume, handle errors, test. | 7.0k | 2026-09-20 | high | | [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) | Decision table mapping question shape to Choice, Score or Noul, the anti-patterns for each, and how to decompose a complex judgment into several primitives. | 3.4k | 2026-09-17 | high | | [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) | Get a key at console.typesafe.ai, export TYPESAFE_API_KEY, and make your first POST /v1/systemone call in curl, Python, or TypeScript. | 3.6k | 2026-09-17 | high | | [Smart home assistant demo walkthrough](https://jevwiki.ai/raw/wiki/guides/smart-home-demo.md) | TypeSafe's smart home demo: one speculative fan-out per utterance routes device commands, while an LLM handles compound splitting and conversational fallback. | 2.3k | 2026-09-17 | medium | | [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) | Measure accuracy, calibration, repeatability, latency and cost on your own labelled set; pick thresholds from confidence buckets; regression-test jaggedness. | 4.3k | 2026-09-21 | high | | [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) | How to phrase instructions and criteria for each question type, with before/after rewrites for literal reading, negation, numbers and dates, plus an edge-case testing loop. | 4.6k | 2026-09-17 | high | ## Ideas (community) (12) | Page | Summary | ~Tokens | Updated | Conf. | |---|---|---|---|---| | [Community repos: what people built and how they use Jev](https://jevwiki.ai/raw/wiki/ideas/community-repos.md) | Index of 58 third-party Jev repos, one line each, split across two domain pages, plus reusable designs and a vetting checklist. | 2.6k | 2026-09-21 | medium | | [Consult guide: could Jev help this project?](https://jevwiki.ai/raw/wiki/ideas/consult.md) | Procedure for an agent asked 'here is my project, could Jev help?': what to read (10-15k tokens), how to find and filter decisions, and the shortlist format to return. | 2.0k | 2026-09-21 | medium | | [Field reports: independent evaluations, critiques, open replicas](https://jevwiki.ai/raw/wiki/ideas/field-reports.md) | What independent testers measured in Jev's first week: repeatable bounded decisions, weak standalone browser control, and probe-measured order and option-set sensitivity. | 3.4k | 2026-09-21 | medium | | [Measurements, access routes and open replicas](https://jevwiki.ai/raw/wiki/ideas/measurements.md) | Numbers measured with Jev — cost, latency, calibration, token accounting, vendor harness figures — plus access routes and replica trust notes. Every figure is one run; re-measure yours. | 3.0k | 2026-09-21 | medium | | [Ideas section overview](https://jevwiki.ai/raw/wiki/ideas/overview.md) | One-screen map of the community-tier ideas section: which index or domain page to open for which question, and how far to trust them. | 0.8k | 2026-09-21 | medium | | [Decision patterns from the community (with fit verdicts)](https://jevwiki.ai/raw/wiki/ideas/patterns.md) | Index of all 37 community decision patterns (ID, primitive, fit verdict, page), routing by project type to one of four domain pages, retrofit order, and anti-patterns. | 2.4k | 2026-09-21 | medium | | [Patterns: agent internals, context and coding agents](https://jevwiki.ai/raw/wiki/ideas/patterns-agents.md) | P01-P11 plus P35-P37: community decision patterns for agent loops, model and security routing, context, memory, coding agents and self-compiling workflows, each with a fit verdict. | 4.4k | 2026-09-21 | medium | | [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md) | Eleven community decision patterns for GTM, content, support and ops — lead scoring, next-best action, churn, draft QA, SEO, triage, approvals — each with a fit verdict. | 4.5k | 2026-09-21 | medium | | [Patterns: judging, search, documents, real-time and markets](https://jevwiki.ai/raw/wiki/ideas/patterns-data.md) | P15-P18 and P24-P27: community decision patterns for judging, moderation, search and ranking, corpus labelling, documents, transcripts, devices and markets, with fit verdicts. | 3.0k | 2026-09-21 | medium | | [Patterns: browser, computer use, voice and product UI](https://jevwiki.ai/raw/wiki/ideas/patterns-interface.md) | Community patterns where Jev picks the next on-screen action or labels items inside a product UI: browser agents, site-exposed tools, desktop/mobile/voice control, in-UI classifiers (P12-P14, P34). | 1.3k | 2026-09-21 | medium | | [Repos: coding agents, orchestration, memory, browser and computer use, integrations](https://jevwiki.ai/raw/wiki/ideas/repos-agents.md) | 32 community repos that put Jev inside a coding agent, an orchestrator, a browser or computer-use loop, or an MCP/CLI integration surface. | 4.4k | 2026-09-21 | medium | | [Repos: data, documents, judging, real-time, markets, business apps, replicas](https://jevwiki.ai/raw/wiki/ideas/repos-apps.md) | 23 community repos that point Jev at rows, documents, media, live simulations, markets, business questions — plus the open replicas of the interface. | 3.8k | 2026-09-21 | medium | ## Concepts (13) | Page | Summary | ~Tokens | Updated | Conf. | |---|---|---|---|---| | [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) | instructions, Choice option descriptions, Score levels and Noul true/false all accept JSON: string, object, array or null (EntryType). | 3.4k | 2026-09-17 | high | | [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md) | Choice picks one option from a fixed set: send type/instructions/criteria, get back choice, probabilities over every option, and confidence. | 4.6k | 2026-09-17 | high | | [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) | confidence is a 0-1 statistic derived from an answer's probabilities distribution; Choice and Score carry it, Noul does not. | 2.3k | 2026-09-17 | high | | [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) | Build a normal software workflow and insert System One only where AI is needed: narrow typed questions, composed in code. | 6.3k | 2026-09-17 | high | | [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) | Nine documented failure modes of jev-1.13 — literal reading, math, dates, indirection, big states, adversarial text, contradictions, invariants, generation — with the mitigation for each. | 3.3k | 2026-09-17 | high | | [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md) | Why TypeSafe post-trains with RLCD for calibrated decisions instead of RLHF/RLVR for generated text. | 1.7k | 2026-09-17 | high | | [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) | Noul asks one yes/no question and returns a single number, the probability that the answer is yes; criteria are optional true/false clarifications. | 2.3k | 2026-09-17 | high | | [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) | The three Jev question types (Choice, Score, Noul), the typed answers they return, how to pick one, and how to batch many questions in one request. | 3.0k | 2026-09-17 | high | | [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) | Score rates a state against an ordered array of described levels and returns a probability-weighted position, the legend, per-level probabilities, and confidence. | 5.1k | 2026-09-17 | high | | [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) | State is the content Jev evaluates: a string, JSON object, or array of text, shared by every question in one request. | 1.7k | 2026-09-17 | high | | [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md) | System One models make fast, typed, calibrated decisions software can consume directly; Jev is TypeSafe's first one. | 2.8k | 2026-09-17 | high | | [Use-case map by industry](https://jevwiki.ai/raw/wiki/concepts/use-case-map.md) | Scannable map of where Jev fits: five capability categories, eighteen industry/function areas, and ten decision shapes. | 3.2k | 2026-09-20 | high | | [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md) | TypeSafe's four workflow evals: same harness for every model, reference labels from GPT-6 Astra + Claude Fable 5.1, source of 193.6x/444.6x. | 4.0k | 2026-09-17 | high | ## Reference (18) | Page | Summary | ~Tokens | Updated | Conf. | |---|---|---|---|---| | [The typesafe-ai agent skill and Claude Code plugin](https://jevwiki.ai/raw/wiki/reference/agent-skill.md) | Install, update, and invoke the typesafe-ai agent skill (Claude Code plugin typesafe 0.5.7, MIT), plus a faithful digest of the guidance SKILL.md gives agents. | 5.2k | 2026-09-21 | high | | [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md) | Exactly four TYPESAFE_* environment variables are read by the SDKs: API_KEY, BASE_URL, DEFAULT_MODEL, LOG_LEVEL — both SDKs read all four. | 2.8k | 2026-09-17 | high | | [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) | Complete wire contract for POST https://api.typesafe.ai/v1/systemone and GET /v1/models: auth, request body, question and answer shapes, usage, errors. | 5.0k | 2026-09-17 | high | | [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) | @typesafe-ai/sdk 0.6.0: install, TypeSafeClient config and defaults, systemOne(), choice/score/noul builders, APIPromise, models.list(), logging. | 6.9k | 2026-09-17 | high | | [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md) | @typesafe-ai/sdk releases: 0.5.7 initial public release, 0.6.0 (2026-09-15) makes Score.criteria an ordered sequence — the one breaking change. | 1.8k | 2026-09-17 | high | | [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) | Error hierarchy of @typesafe-ai/sdk 0.6.0, status-to-class mapping, RetryPolicy defaults (2 retries, 500ms/5s backoff, 0.25 jitter) and RequestOptions. | 5.2k | 2026-09-17 | high | | [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) | Every interface, type alias and exported variable in @typesafe-ai/sdk 0.6.0, with per-property type/required/default tables and generics examples. | 6.0k | 2026-09-17 | high | | [Legal: MCA, DPA, privacy, data retention](https://jevwiki.ai/raw/wiki/reference/legal-and-data.md) | Developer-facing summary of TypeSafe's MCA, DPA, and Privacy Policy: no training on Input, telemetry carve-out, retention, sub-processors, acceptable use, no uptime SLA. | 5.1k | 2026-09-17 | high | | [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md) | Every delta between the preview evaluation endpoint and the stable v1 API, with before/after examples, plus the typesafe-client to typesafe-sdk rename table. | 3.7k | 2026-09-17 | high | | [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) | Jev 1.13 model ID, aliases, $42/Btok pricing with free output tokens, 250k tok/s and 1,200 rpm limits, 64k/32k context rule, and text-only input. | 2.7k | 2026-09-17 | high | | [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md) | Every component schema in TypeSafe's OpenAPI 3.1.0 document (info version 0.2.0): properties, types, requiredness, constraints, and examples. | 4.8k | 2026-09-17 | high | | [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) | typesafe-sdk 0.6.0: install, TypeSafeClient/AsyncTypeSafeClient constructor params, system_one() kwargs, models resource, env vars, logging, and the full export list. | 5.7k | 2026-09-17 | high | | [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md) | typesafe-sdk release history: 0.0.1a0 placeholder, 0.5.7 initial public release (2026-09-14), 0.6.0 (2026-09-15) with the Score.criteria breaking change. | 1.8k | 2026-09-17 | high | | [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md) | Every field of Noul, Choice and Score in typesafe-sdk 0.6.0, their TypedDict equivalents, JSONContent typing, client-side validation, and the 0.6.0 Score.criteria breaking change. | 3.1k | 2026-09-17 | high | | [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md) | SystemOneResponse fields and the .nouls/.choices/.scores views, every answer attribute, Usage, request_id and raw_http_response, plus ListModelsResponse and ModelMetadata. | 3.4k | 2026-09-17 | high | | [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md) | RetryPolicy fields and defaults, which statuses and exceptions are retried, backoff and Retry-After handling, the full exception hierarchy with attributes, timeouts, and public constants. | 4.7k | 2026-09-17 | high | | [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) | One table mapping every HTTP status to its meaning, Python exception, JS error class, retryability, and the recommended client action. | 3.6k | 2026-09-17 | high | | [system-one-adapter: LLM-backed drop-in for TypeSafeClient](https://jevwiki.ai/raw/wiki/reference/system-one-adapter.md) | system-one-adapter answers typesafe_sdk questions with an OpenAI or Anthropic LLM instead of Jev, so you can compare cost, speed, and intelligence on the same code. | 5.0k | 2026-09-17 | high | ## Patterns (5) | Page | Summary | ~Tokens | Updated | Conf. | |---|---|---|---|---| | [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) | Break a ranking judgment into independent Score dimensions, normalize each to 0–1, and combine them with weights your code owns and can retune. | 2.1k | 2026-09-17 | high | | [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) | Treat confidence as a second decision axis: one floor below which nothing is automated, then a per-action threshold sized to the consequences of being wrong. | 2.2k | 2026-09-17 | high | | [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) | Put every question your decision tree could need into one call, including speculative ones, and let code discard the irrelevant answers. | 2.2k | 2026-09-17 | high | | [Intent routing](https://jevwiki.ai/raw/wiki/patterns/intent-routing.md) | Classify the request with one cheap Jev call, then invoke the cheapest adequate handler: deterministic code, a specialist LLM, or a human. | 2.6k | 2026-09-17 | high | | [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) | Catalog of TypeSafe's four architectural patterns — fan-out, confidence routing, composite scoring, intent routing — and when to reach for each. | 1.8k | 2026-09-17 | high | ## Cookbooks (19) | Page | Summary | ~Tokens | Updated | Conf. | |---|---|---|---|---| | [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md) | Rebuild Markdown from de-formatted plain text in two requests: Nouls stitch hard-wrapped lines, then Choices classify each block; code renders every character from the input. | 4.5k | 2026-09-17 | high | | [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md) | An LLM proposes Jev questions, Jev answers them per row to build numeric columns, CatBoost trains and reports back: 38 questions after five rounds reach 1.77 held-out RMSE on wine scores. | 4.7k | 2026-09-17 | high | | [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md) | One Choice question decides whether a quote's surrounding section supports, contradicts, or says nothing about an LLM's claim; a string match catches fabricated quotes first. | 2.8k | 2026-09-17 | high | | [Cookbook: Classification using confidence](https://jevwiki.ai/raw/wiki/cookbooks/classification-using-confidence.md) | Classify SEC filings into 75 SIC industry groups with one Choice; when confidence < 0.9, report the broader division instead — 40% correct becomes 70%, at no extra call. | 2.9k | 2026-09-17 | high | | [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md) | Four Noul questions per retrieved query-passage pair, routed by ordered thresholds, decide what reaches the generator as evidence, as conflict, or not at all. | 3.6k | 2026-09-17 | high | | [Cookbook: Self-consistency — choices](https://jevwiki.ai/raw/wiki/cookbooks/consistency-choice.md) | Runs an 8-Choice moderation rubric 15 times across Jev and six LLM conditions; a 0.60 top-probability floor lifts Jev's decision agreement from 90.8% to 99.2% at 74.2% automation. | 4.3k | 2026-09-17 | high | | [Cookbook: Self-consistency — nouls](https://jevwiki.ai/raw/wiki/cookbooks/consistency-noul.md) | Runs a 14-Noul claims rubric 15 times against Jev and six LLM conditions; Jev's mean probability std dev is 0.0102 at 111ms per call, and an uncertain band routes 0.30-0.70 to a human. | 3.7k | 2026-09-17 | high | | [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md) | Seven Choice questions read a date's parts off a document in one call; code does all the calendar math and gates on the weakest part's confidence. | 3.9k | 2026-09-17 | high | | [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md) | One three-level Score decides merge / curate / leave-unlinked for 450 candidate entity pairs, with three Nouls riding along to tell the curator which field disagrees. | 3.0k | 2026-09-17 | high | | [Cookbook: Function calling](https://jevwiki.ai/raw/wiki/cookbooks/function-calling.md) | Map typed Python functions to Jev Choice/Noul questions so a natural-language command becomes a validated call with a per-argument confidence. | 2.9k | 2026-09-17 | high | | [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) | Walk a deep taxonomy to a leaf by asking one Choice per sibling set, and keep K paths alive with a geometric-mean beam search instead of a greedy walk. | 2.9k | 2026-09-17 | high | | [Cookbook: Guardrails for LLMs](https://jevwiki.ai/raw/wiki/cookbooks/llm-guardrails.md) | Screen every LLM input and output with one Jev request: four hazard Nouls plus a severity Score, then route pass / review / block / support on thresholds you own. | 3.1k | 2026-09-17 | high | | [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md) | Catalog of all 18 TypeSafe cookbooks — goal, primitives and domain each — plus how a cookbook is structured and why the published pip line does not work. | 3.4k | 2026-09-17 | high | | [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md) | Batching 13 questions about one 54k-character document into a single Jev call was 12.2x cheaper and 10.0x faster than 13 single-question calls, with identical answers. | 3.1k | 2026-09-17 | high | | [Cookbook: Pre-parsed value extraction](https://jevwiki.ai/raw/wiki/cookbooks/pre-parsed-value-extraction.md) | A recall-tuned regex finds candidate spans, a Jev Choice over those exact spans picks the one the question asks for, and code copies it verbatim and normalizes it. | 2.7k | 2026-09-17 | high | | [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md) | BM25 builds a 30-candidate shortlist per CLERC query, then one Noul per query-candidate pair re-sorts it: top-1 rises 5% to 18%, top-10 38% to 62% for $0.0645. | 2.6k | 2026-09-17 | high | | [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md) | Extract with a cheap model, verify every field with a battery of Jev Nouls framed so true means wrong, and escalate to a reasoning model only when a flag fires. | 4.0k | 2026-09-17 | high | | [Cookbook: Line-by-line search](https://jevwiki.ai/raw/wiki/cookbooks/semantic-find.md) | Tag a document's lines with ids, rank them with one Choice over those ids, and pair it with a Noul that says whether the document answers the query at all. | 2.4k | 2026-09-17 | high | | [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md) | Two Jev requests per agent turn — rank 182 skills then re-read the top three — cut wrong skill loads from 16.8% to 7.3% and needless loads from 9.8% to 4.0%. | 3.8k | 2026-09-17 | high | ## Syntheses (4) | Page | Summary | ~Tokens | Updated | Conf. | |---|---|---|---|---| | [FAQ for agents and developers](https://jevwiki.ai/raw/wiki/syntheses/faq.md) | Forty answers about Jev — what it is, the API, the SDKs, design, confidence, limits and pricing, company and legal — each linked to the page carrying the detail. | 4.9k | 2026-09-17 | high | | [Glossary](https://jevwiki.ai/raw/wiki/syntheses/glossary.md) | Sixty-nine Jev, TypeSafe, API, SDK and evaluation terms defined in one or two sentences, alphabetical, each linked to the page with the full contract. | 4.7k | 2026-09-17 | high | | [Jev vs LLM JSON mode / structured outputs](https://jevwiki.ai/raw/wiki/syntheses/jev-vs-llm-structured-outputs.md) | What Jev gives you that an LLM in JSON mode does not (and vice versa), a row-by-row comparison, when to pick each, how to combine them, and how to benchmark the pair honestly. | 4.3k | 2026-09-17 | medium | | [Versions and timeline (models, SDKs, API, company)](https://jevwiki.ai/raw/wiki/syntheses/version-timeline.md) | Every datable fact in the wiki on one axis: company, model versions, API, both SDKs, the plugin and adapter, legal documents, repo commits, and where the dates disagree. | 4.0k | 2026-09-17 | medium | ## Entities (11) | Page | Summary | ~Tokens | Updated | Conf. | |---|---|---|---|---| | [Blog: Lies, Damned Lies, and Benchmarks](https://jevwiki.ai/raw/wiki/entities/blog-antibenchmaxxing.md) | 2026-09-11 post against benchmaxxing, ending in TypeSafe's commitment to publish no standard benchmark table and to retire dated eval snapshots. | 1.7k | 2026-09-17 | high | | [Blog: The Bitterest Lesson](https://jevwiki.ai/raw/wiki/entities/blog-bitterest-lesson.md) | 2026-09-10 post arguing the ML priority order is doing the right task > data > compute > algorithms, using InstructGPT vs GPT-3 as the proof. | 1.4k | 2026-09-17 | high | | [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md) | Digest of TypeSafe's launch post: System One vs LLM comparison table, price/speed claims, the evidence section, and the caveats the post states itself. | 2.6k | 2026-09-17 | high | | [Blog: AI: too good to be true, too bad to be useful (2026-06-19)](https://jevwiki.ai/raw/wiki/entities/blog-too-good-to-be-true.md) | Stub: the body of this 2026-06-19 TypeSafe post was not captured (JS-rendered); only title, date, category, and the homepage teaser are known. | 0.7k | 2026-09-17 | low | | [typesafe-ai GitHub organisation and repos](https://jevwiki.ai/raw/wiki/entities/github-repos.md) | The github.com/typesafe-ai org: two SDKs, the agent skill marketplace, the System One adapter, plus infra repos and two forks. | 2.3k | 2026-09-20 | high | | [Jev (model)](https://jevwiki.ai/raw/wiki/entities/jev.md) | Jev is TypeSafe's first System One model: text in, typed decisions with calibrated probabilities out, $0.042/MTok input, 64k context, 70-500 ms. | 1.6k | 2026-09-17 | high | | [Manifesto: Composable AI — Build Prod, Not God](https://jevwiki.ai/raw/wiki/entities/manifesto.md) | TypeSafe's manifesto argues the bottleneck is composability, not intelligence, and lays out a three-step plan to make AI a dependable software primitive. | 1.7k | 2026-09-17 | high | | [Press and third-party coverage](https://jevwiki.ai/raw/wiki/entities/press-and-coverage.md) | Outlet-by-outlet digest of Jev's launch coverage (2026-09-15/16), separating TypeSafe's claims from each outlet's own assertions and caveats. | 3.5k | 2026-09-17 | medium | | [Founders and team](https://jevwiki.ai/raw/wiki/entities/team.md) | TypeSafe AI's three founders (Diogo Almeida CEO, Sasha Sheng COO, Erik Gafni CTO), the team's stated culture and values, and the SDK maintainers. | 1.6k | 2026-09-21 | high | | [TypeSafe AI (company)](https://jevwiki.ai/raw/wiki/entities/typesafe-ai.md) | TypeSafe AI, Inc. is a San Francisco frontier AI lab that left stealth on 2026-09-15 with $40M led by DCVC and Jev, its first System One model. | 2.5k | 2026-09-17 | high | | [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) | console.typesafe.ai is TypeSafe's Web Interface: log in with Google or an email code, try Jev in the Playground, and mint API keys. | 1.1k | 2026-09-17 | medium | ## Tags - **acceptable-use**: [Legal: MCA, DPA, privacy, data retention](https://jevwiki.ai/raw/wiki/reference/legal-and-data.md) - **access**: [Measurements, access routes and open replicas](https://jevwiki.ai/raw/wiki/ideas/measurements.md) - **adapter**: [system-one-adapter: LLM-backed drop-in for TypeSafeClient](https://jevwiki.ai/raw/wiki/reference/system-one-adapter.md) - **advanced**: [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) - **agent**: [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) - **agent-skill**: [The typesafe-ai agent skill and Claude Code plugin](https://jevwiki.ai/raw/wiki/reference/agent-skill.md) - **agents**: [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md), [Patterns: agent internals, context and coding agents](https://jevwiki.ai/raw/wiki/ideas/patterns-agents.md) - **answers**: [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md), [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md) - **anthropic**: [system-one-adapter: LLM-backed drop-in for TypeSafeClient](https://jevwiki.ai/raw/wiki/reference/system-one-adapter.md) - **api-key**: [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) - **api-keys**: [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) - **architecture**: [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md), [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md), [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) - **autoformat**: [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md) - **autoresearch**: [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md) - **batching**: [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md) - **beam-search**: [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) - **benchmarking**: [system-one-adapter: LLM-backed drop-in for TypeSafeClient](https://jevwiki.ai/raw/wiki/reference/system-one-adapter.md) - **benchmarks**: [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md), [Blog: Lies, Damned Lies, and Benchmarks](https://jevwiki.ai/raw/wiki/entities/blog-antibenchmaxxing.md), [Field reports: independent evaluations, critiques, open replicas](https://jevwiki.ai/raw/wiki/ideas/field-reports.md), [Measurements, access routes and open replicas](https://jevwiki.ai/raw/wiki/ideas/measurements.md) - **blog**: [Blog: Lies, Damned Lies, and Benchmarks](https://jevwiki.ai/raw/wiki/entities/blog-antibenchmaxxing.md), [Blog: The Bitterest Lesson](https://jevwiki.ai/raw/wiki/entities/blog-bitterest-lesson.md), [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md), [Blog: AI: too good to be true, too bad to be useful (2026-06-19)](https://jevwiki.ai/raw/wiki/entities/blog-too-good-to-be-true.md) - **bm25**: [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md) - **breaking-changes**: [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md) - **browser-agents**: [Patterns: browser, computer use, voice and product UI](https://jevwiki.ai/raw/wiki/ideas/patterns-interface.md) - **browser-use**: [Patterns: agent internals, context and coding agents](https://jevwiki.ai/raw/wiki/ideas/patterns-agents.md), [Repos: coding agents, orchestration, memory, browser and computer use, integrations](https://jevwiki.ai/raw/wiki/ideas/repos-agents.md) - **calibration**: [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md), [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md), [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md), [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) - **cascade**: [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md) - **catalog**: [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md) - **catboost**: [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md) - **changelog**: [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md), [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md) - **checklist**: [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) - **choice**: [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md), [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md), [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md), [Cookbook: Classification using confidence](https://jevwiki.ai/raw/wiki/cookbooks/classification-using-confidence.md), [Cookbook: Self-consistency — choices](https://jevwiki.ai/raw/wiki/cookbooks/consistency-choice.md), [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md), [Cookbook: Function calling](https://jevwiki.ai/raw/wiki/cookbooks/function-calling.md), [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md), [Cookbook: Pre-parsed value extraction](https://jevwiki.ai/raw/wiki/cookbooks/pre-parsed-value-extraction.md), [Cookbook: Line-by-line search](https://jevwiki.ai/raw/wiki/cookbooks/semantic-find.md), [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md), [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md), [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md) - **citation-check**: [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md) - **claims**: [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md), [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md), [Press and third-party coverage](https://jevwiki.ai/raw/wiki/entities/press-and-coverage.md), [TypeSafe AI (company)](https://jevwiki.ai/raw/wiki/entities/typesafe-ai.md), [FAQ for agents and developers](https://jevwiki.ai/raw/wiki/syntheses/faq.md) - **classification**: [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Cookbook: Classification using confidence](https://jevwiki.ai/raw/wiki/cookbooks/classification-using-confidence.md), [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md), [Intent routing](https://jevwiki.ai/raw/wiki/patterns/intent-routing.md) - **claude-code**: [The typesafe-ai agent skill and Claude Code plugin](https://jevwiki.ai/raw/wiki/reference/agent-skill.md) - **client**: [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md), [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) - **coding-agents**: [Repos: coding agents, orchestration, memory, browser and computer use, integrations](https://jevwiki.ai/raw/wiki/ideas/repos-agents.md) - **community**: [Community repos: what people built and how they use Jev](https://jevwiki.ai/raw/wiki/ideas/community-repos.md), [Measurements, access routes and open replicas](https://jevwiki.ai/raw/wiki/ideas/measurements.md), [Ideas section overview](https://jevwiki.ai/raw/wiki/ideas/overview.md), [Decision patterns from the community (with fit verdicts)](https://jevwiki.ai/raw/wiki/ideas/patterns.md), [Repos: coding agents, orchestration, memory, browser and computer use, integrations](https://jevwiki.ai/raw/wiki/ideas/repos-agents.md), [Repos: data, documents, judging, real-time, markets, business apps, replicas](https://jevwiki.ai/raw/wiki/ideas/repos-apps.md) - **company**: [TypeSafe AI (company)](https://jevwiki.ai/raw/wiki/entities/typesafe-ai.md) - **comparison**: [Jev vs LLM JSON mode / structured outputs](https://jevwiki.ai/raw/wiki/syntheses/jev-vs-llm-structured-outputs.md) - **composable-ai**: [Manifesto: Composable AI — Build Prod, Not God](https://jevwiki.ai/raw/wiki/entities/manifesto.md) - **composition**: [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md), [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) - **computer-use**: [Patterns: browser, computer use, voice and product UI](https://jevwiki.ai/raw/wiki/ideas/patterns-interface.md) - **confidence**: [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md), [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md), [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md), [Cookbook: Classification using confidence](https://jevwiki.ai/raw/wiki/cookbooks/classification-using-confidence.md), [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md), [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) - **configuration**: [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md) - **consistency**: [Cookbook: Self-consistency — choices](https://jevwiki.ai/raw/wiki/cookbooks/consistency-choice.md), [Cookbook: Self-consistency — nouls](https://jevwiki.ai/raw/wiki/cookbooks/consistency-noul.md), [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) - **console**: [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) - **constants**: [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md) - **consult**: [Consult guide: could Jev help this project?](https://jevwiki.ai/raw/wiki/ideas/consult.md) - **context**: [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md), [Patterns: agent internals, context and coding agents](https://jevwiki.ai/raw/wiki/ideas/patterns-agents.md) - **context-length**: [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) - **cookbook**: [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md), [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md), [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md), [Cookbook: Classification using confidence](https://jevwiki.ai/raw/wiki/cookbooks/classification-using-confidence.md), [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md), [Cookbook: Self-consistency — choices](https://jevwiki.ai/raw/wiki/cookbooks/consistency-choice.md), [Cookbook: Self-consistency — nouls](https://jevwiki.ai/raw/wiki/cookbooks/consistency-noul.md), [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md), [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md), [Cookbook: Function calling](https://jevwiki.ai/raw/wiki/cookbooks/function-calling.md), [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md), [Cookbook: Guardrails for LLMs](https://jevwiki.ai/raw/wiki/cookbooks/llm-guardrails.md), [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md), [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md), [Cookbook: Pre-parsed value extraction](https://jevwiki.ai/raw/wiki/cookbooks/pre-parsed-value-extraction.md), [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md), [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md), [Cookbook: Line-by-line search](https://jevwiki.ai/raw/wiki/cookbooks/semantic-find.md), [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md) - **cost**: [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md), [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) - **coverage**: [Press and third-party coverage](https://jevwiki.ai/raw/wiki/entities/press-and-coverage.md) - **criteria**: [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md), [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) - **critiques**: [Field reports: independent evaluations, critiques, open replicas](https://jevwiki.ai/raw/wiki/ideas/field-reports.md) - **culture**: [Founders and team](https://jevwiki.ai/raw/wiki/entities/team.md) - **curl**: [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) - **data**: [Repos: data, documents, judging, real-time, markets, business apps, replicas](https://jevwiki.ai/raw/wiki/ideas/repos-apps.md) - **data-retention**: [Legal: MCA, DPA, privacy, data retention](https://jevwiki.ai/raw/wiki/reference/legal-and-data.md) - **date-extraction**: [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md) - **dates**: [Versions and timeline (models, SDKs, API, company)](https://jevwiki.ai/raw/wiki/syntheses/version-timeline.md) - **decision**: [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) - **decision-guide**: [Jev vs LLM JSON mode / structured outputs](https://jevwiki.ai/raw/wiki/syntheses/jev-vs-llm-structured-outputs.md) - **decision-mapping**: [Consult guide: could Jev help this project?](https://jevwiki.ai/raw/wiki/ideas/consult.md) - **decision-table**: [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) - **decomposition**: [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) - **deduplication**: [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md) - **definitions**: [Glossary](https://jevwiki.ai/raw/wiki/syntheses/glossary.md) - **demo**: [Smart home assistant demo walkthrough](https://jevwiki.ai/raw/wiki/guides/smart-home-demo.md) - **design**: [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) - **dispatch**: [Cookbook: Function calling](https://jevwiki.ai/raw/wiki/cookbooks/function-calling.md) - **documents**: [Patterns: judging, search, documents, real-time and markets](https://jevwiki.ai/raw/wiki/ideas/patterns-data.md), [Repos: data, documents, judging, real-time, markets, business apps, replicas](https://jevwiki.ai/raw/wiki/ideas/repos-apps.md) - **dpa**: [Legal: MCA, DPA, privacy, data retention](https://jevwiki.ai/raw/wiki/reference/legal-and-data.md) - **entity-alignment**: [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md) - **environment-variables**: [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md) - **errors**: [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md), [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md), [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md), [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) - **evals**: [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md), [Blog: Lies, Damned Lies, and Benchmarks](https://jevwiki.ai/raw/wiki/entities/blog-antibenchmaxxing.md), [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md), [Press and third-party coverage](https://jevwiki.ai/raw/wiki/entities/press-and-coverage.md) - **evaluation**: [Cookbook: Self-consistency — nouls](https://jevwiki.ai/raw/wiki/cookbooks/consistency-noul.md), [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) - **evaluations**: [Field reports: independent evaluations, critiques, open replicas](https://jevwiki.ai/raw/wiki/ideas/field-reports.md) - **examples**: [Community repos: what people built and how they use Jev](https://jevwiki.ai/raw/wiki/ideas/community-repos.md) - **exceptions**: [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) - **extraction**: [Cookbook: Pre-parsed value extraction](https://jevwiki.ai/raw/wiki/cookbooks/pre-parsed-value-extraction.md), [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md) - **failure-modes**: [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) - **fan-out**: [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md), [Smart home assistant demo walkthrough](https://jevwiki.ai/raw/wiki/guides/smart-home-demo.md), [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md), [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) - **faq**: [FAQ for agents and developers](https://jevwiki.ai/raw/wiki/syntheses/faq.md) - **feature-engineering**: [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md) - **field-reports**: [Field reports: independent evaluations, critiques, open replicas](https://jevwiki.ai/raw/wiki/ideas/field-reports.md) - **fit-verdicts**: [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md), [Decision patterns from the community (with fit verdicts)](https://jevwiki.ai/raw/wiki/ideas/patterns.md) - **founders**: [Founders and team](https://jevwiki.ai/raw/wiki/entities/team.md) - **function-calling**: [Cookbook: Function calling](https://jevwiki.ai/raw/wiki/cookbooks/function-calling.md) - **funding**: [TypeSafe AI (company)](https://jevwiki.ai/raw/wiki/entities/typesafe-ai.md) - **github**: [typesafe-ai GitHub organisation and repos](https://jevwiki.ai/raw/wiki/entities/github-repos.md) - **glossary**: [Glossary](https://jevwiki.ai/raw/wiki/syntheses/glossary.md) - **gtm**: [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md) - **guardrails**: [Cookbook: Guardrails for LLMs](https://jevwiki.ai/raw/wiki/cookbooks/llm-guardrails.md) - **guide**: [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md), [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) - **hiring**: [Founders and team](https://jevwiki.ai/raw/wiki/entities/team.md) - **http-api**: [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md), [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md), [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md), [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) - **ideas**: [Consult guide: could Jev help this project?](https://jevwiki.ai/raw/wiki/ideas/consult.md), [Ideas section overview](https://jevwiki.ai/raw/wiki/ideas/overview.md), [Patterns: agent internals, context and coding agents](https://jevwiki.ai/raw/wiki/ideas/patterns-agents.md), [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md), [Patterns: judging, search, documents, real-time and markets](https://jevwiki.ai/raw/wiki/ideas/patterns-data.md), [Patterns: browser, computer use, voice and product UI](https://jevwiki.ai/raw/wiki/ideas/patterns-interface.md), [Decision patterns from the community (with fit verdicts)](https://jevwiki.ai/raw/wiki/ideas/patterns.md) - **ideation**: [Use-case map by industry](https://jevwiki.ai/raw/wiki/concepts/use-case-map.md) - **index**: [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md), [Decision patterns from the community (with fit verdicts)](https://jevwiki.ai/raw/wiki/ideas/patterns.md), [Jev Wiki — Master Index](https://jevwiki.ai/raw/wiki/index.md), [Glossary](https://jevwiki.ai/raw/wiki/syntheses/glossary.md) - **industry**: [Use-case map by industry](https://jevwiki.ai/raw/wiki/concepts/use-case-map.md) - **input**: [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) - **install**: [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) - **installation**: [The typesafe-ai agent skill and Claude Code plugin](https://jevwiki.ai/raw/wiki/reference/agent-skill.md) - **instructgpt**: [Blog: The Bitterest Lesson](https://jevwiki.ai/raw/wiki/entities/blog-bitterest-lesson.md) - **instructions**: [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md), [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) - **integration**: [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) - **integrations**: [Community repos: what people built and how they use Jev](https://jevwiki.ai/raw/wiki/ideas/community-repos.md), [Repos: coding agents, orchestration, memory, browser and computer use, integrations](https://jevwiki.ai/raw/wiki/ideas/repos-agents.md) - **intent**: [Intent routing](https://jevwiki.ai/raw/wiki/patterns/intent-routing.md) - **jaggedness**: [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md), [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) - **javascript**: [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md), [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md), [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md), [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md), [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) - **javascript-sdk**: [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md) - **jev**: [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md), [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md), [Jev (model)](https://jevwiki.ai/raw/wiki/entities/jev.md), [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) - **jev-1-13**: [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) - **json**: [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) - **json-mode**: [Jev vs LLM JSON mode / structured outputs](https://jevwiki.ai/raw/wiki/syntheses/jev-vs-llm-structured-outputs.md) - **latency**: [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md), [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) - **launch**: [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md) - **legal**: [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md), [Legal: MCA, DPA, privacy, data retention](https://jevwiki.ai/raw/wiki/reference/legal-and-data.md) - **levels**: [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) - **limitations**: [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) - **limits**: [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md), [Jev (model)](https://jevwiki.ai/raw/wiki/entities/jev.md) - **llm**: [Jev vs LLM JSON mode / structured outputs](https://jevwiki.ai/raw/wiki/syntheses/jev-vs-llm-structured-outputs.md) - **llm-fallback**: [Smart home assistant demo walkthrough](https://jevwiki.ai/raw/wiki/guides/smart-home-demo.md) - **llm-orchestration**: [Intent routing](https://jevwiki.ai/raw/wiki/patterns/intent-routing.md) - **log**: [Activity log](https://jevwiki.ai/raw/wiki/log.md) - **login**: [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) - **manifesto**: [Manifesto: Composable AI — Build Prod, Not God](https://jevwiki.ai/raw/wiki/entities/manifesto.md) - **markdown**: [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md) - **marketing**: [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md) - **measurements**: [Measurements, access routes and open replicas](https://jevwiki.ai/raw/wiki/ideas/measurements.md) - **methodology**: [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md), [Blog: Lies, Damned Lies, and Benchmarks](https://jevwiki.ai/raw/wiki/entities/blog-antibenchmaxxing.md) - **migration**: [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md) - **mission**: [Manifesto: Composable AI — Build Prod, Not God](https://jevwiki.ai/raw/wiki/entities/manifesto.md) - **model**: [Jev (model)](https://jevwiki.ai/raw/wiki/entities/jev.md) - **models**: [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md), [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md), [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md) - **moderation**: [Cookbook: Self-consistency — choices](https://jevwiki.ai/raw/wiki/cookbooks/consistency-choice.md), [Patterns: judging, search, documents, real-time and markets](https://jevwiki.ai/raw/wiki/ideas/patterns-data.md) - **needs-reingestion**: [Blog: AI: too good to be true, too bad to be useful (2026-06-19)](https://jevwiki.ai/raw/wiki/entities/blog-too-good-to-be-true.md) - **noul**: [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md), [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md), [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md), [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md), [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md), [Cookbook: Self-consistency — nouls](https://jevwiki.ai/raw/wiki/cookbooks/consistency-noul.md), [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md), [Cookbook: Function calling](https://jevwiki.ai/raw/wiki/cookbooks/function-calling.md), [Cookbook: Guardrails for LLMs](https://jevwiki.ai/raw/wiki/cookbooks/llm-guardrails.md), [Cookbook: Pre-parsed value extraction](https://jevwiki.ai/raw/wiki/cookbooks/pre-parsed-value-extraction.md), [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md), [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md), [Cookbook: Line-by-line search](https://jevwiki.ai/raw/wiki/cookbooks/semantic-find.md), [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md), [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md), [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md) - **npm**: [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md) - **onboarding**: [FAQ for agents and developers](https://jevwiki.ai/raw/wiki/syntheses/faq.md) - **open-source**: [typesafe-ai GitHub organisation and repos](https://jevwiki.ai/raw/wiki/entities/github-repos.md) - **openai**: [system-one-adapter: LLM-backed drop-in for TypeSafeClient](https://jevwiki.ai/raw/wiki/reference/system-one-adapter.md) - **openapi**: [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md) - **overview**: [Ideas section overview](https://jevwiki.ai/raw/wiki/ideas/overview.md) - **packages**: [typesafe-ai GitHub organisation and repos](https://jevwiki.ai/raw/wiki/entities/github-repos.md) - **parsing**: [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md) - **patterns**: [Use-case map by industry](https://jevwiki.ai/raw/wiki/concepts/use-case-map.md), [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md), [Patterns: agent internals, context and coding agents](https://jevwiki.ai/raw/wiki/ideas/patterns-agents.md), [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md), [Patterns: judging, search, documents, real-time and markets](https://jevwiki.ai/raw/wiki/ideas/patterns-data.md), [Patterns: browser, computer use, voice and product UI](https://jevwiki.ai/raw/wiki/ideas/patterns-interface.md), [Decision patterns from the community (with fit verdicts)](https://jevwiki.ai/raw/wiki/ideas/patterns.md), [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md), [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md), [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md), [Intent routing](https://jevwiki.ai/raw/wiki/patterns/intent-routing.md), [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) - **playbook**: [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) - **playground**: [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) - **plugin**: [The typesafe-ai agent skill and Claude Code plugin](https://jevwiki.ai/raw/wiki/reference/agent-skill.md) - **positioning**: [Manifesto: Composable AI — Build Prod, Not God](https://jevwiki.ai/raw/wiki/entities/manifesto.md) - **press**: [Press and third-party coverage](https://jevwiki.ai/raw/wiki/entities/press-and-coverage.md) - **pricing**: [Jev (model)](https://jevwiki.ai/raw/wiki/entities/jev.md), [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) - **primitives**: [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md), [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md), [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md), [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) - **privacy**: [Legal: MCA, DPA, privacy, data retention](https://jevwiki.ai/raw/wiki/reference/legal-and-data.md) - **probabilities**: [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) - **probability**: [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) - **products**: [TypeSafe AI (company)](https://jevwiki.ai/raw/wiki/entities/typesafe-ai.md) - **progressive-disclosure**: [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md) - **project-assessment**: [Consult guide: could Jev help this project?](https://jevwiki.ai/raw/wiki/ideas/consult.md) - **prompt-injection**: [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md) - **prompting**: [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) - **provenance**: [Versions and timeline (models, SDKs, API, company)](https://jevwiki.ai/raw/wiki/syntheses/version-timeline.md) - **python**: [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md), [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md), [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md), [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md), [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md), [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md), [system-one-adapter: LLM-backed drop-in for TypeSafeClient](https://jevwiki.ai/raw/wiki/reference/system-one-adapter.md) - **python-sdk**: [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md), [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md) - **questions**: [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md), [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md), [FAQ for agents and developers](https://jevwiki.ai/raw/wiki/syntheses/faq.md) - **quickstart**: [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) - **rag**: [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md) - **ranking**: [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) - **rate-limits**: [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md), [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) - **reference**: [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md), [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md), [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md), [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md), [Glossary](https://jevwiki.ai/raw/wiki/syntheses/glossary.md) - **regex**: [Cookbook: Pre-parsed value extraction](https://jevwiki.ai/raw/wiki/cookbooks/pre-parsed-value-extraction.md) - **releases**: [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md), [Versions and timeline (models, SDKs, API, company)](https://jevwiki.ai/raw/wiki/syntheses/version-timeline.md) - **reliability**: [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) - **replicas**: [Community repos: what people built and how they use Jev](https://jevwiki.ai/raw/wiki/ideas/community-repos.md), [Field reports: independent evaluations, critiques, open replicas](https://jevwiki.ai/raw/wiki/ideas/field-reports.md), [Measurements, access routes and open replicas](https://jevwiki.ai/raw/wiki/ideas/measurements.md), [Repos: data, documents, judging, real-time, markets, business apps, replicas](https://jevwiki.ai/raw/wiki/ideas/repos-apps.md) - **repos**: [typesafe-ai GitHub organisation and repos](https://jevwiki.ai/raw/wiki/entities/github-repos.md), [Community repos: what people built and how they use Jev](https://jevwiki.ai/raw/wiki/ideas/community-repos.md), [Repos: coding agents, orchestration, memory, browser and computer use, integrations](https://jevwiki.ai/raw/wiki/ideas/repos-agents.md), [Repos: data, documents, judging, real-time, markets, business apps, replicas](https://jevwiki.ai/raw/wiki/ideas/repos-apps.md) - **rerank**: [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md) - **research-philosophy**: [Blog: The Bitterest Lesson](https://jevwiki.ai/raw/wiki/entities/blog-bitterest-lesson.md) - **responses**: [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md) - **retries**: [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md), [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md), [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) - **retrieval**: [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md), [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md) - **rlcd**: [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md), [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md) - **rlhf**: [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md), [Blog: The Bitterest Lesson](https://jevwiki.ai/raw/wiki/entities/blog-bitterest-lesson.md), [Blog: AI: too good to be true, too bad to be useful (2026-06-19)](https://jevwiki.ai/raw/wiki/entities/blog-too-good-to-be-true.md) - **rlvr**: [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md) - **routing**: [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md), [Ideas section overview](https://jevwiki.ai/raw/wiki/ideas/overview.md), [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md), [Intent routing](https://jevwiki.ai/raw/wiki/patterns/intent-routing.md), [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) - **rubric**: [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) - **safety**: [Cookbook: Guardrails for LLMs](https://jevwiki.ai/raw/wiki/cookbooks/llm-guardrails.md), [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) - **scaling**: [Blog: The Bitterest Lesson](https://jevwiki.ai/raw/wiki/entities/blog-bitterest-lesson.md) - **schemas**: [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md) - **score**: [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md), [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md), [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md), [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md), [Cookbook: Guardrails for LLMs](https://jevwiki.ai/raw/wiki/cookbooks/llm-guardrails.md), [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md), [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md), [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md) - **scoring**: [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) - **sdk**: [typesafe-ai GitHub organisation and repos](https://jevwiki.ai/raw/wiki/entities/github-repos.md), [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md), [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md), [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md), [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md), [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md), [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md), [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md), [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md), [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) - **search**: [Cookbook: Line-by-line search](https://jevwiki.ai/raw/wiki/cookbooks/semantic-find.md), [Patterns: judging, search, documents, real-time and markets](https://jevwiki.ai/raw/wiki/ideas/patterns-data.md) - **skills**: [The typesafe-ai agent skill and Claude Code plugin](https://jevwiki.ai/raw/wiki/reference/agent-skill.md) - **smart-home**: [Smart home assistant demo walkthrough](https://jevwiki.ai/raw/wiki/guides/smart-home-demo.md) - **speculative**: [Smart home assistant demo walkthrough](https://jevwiki.ai/raw/wiki/guides/smart-home-demo.md), [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) - **state**: [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) - **structure**: [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) - **structured-outputs**: [Jev vs LLM JSON mode / structured outputs](https://jevwiki.ai/raw/wiki/syntheses/jev-vs-llm-structured-outputs.md) - **stub**: [Blog: AI: too good to be true, too bad to be useful (2026-06-19)](https://jevwiki.ai/raw/wiki/entities/blog-too-good-to-be-true.md) - **support**: [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md) - **system-one**: [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md), [Jev (model)](https://jevwiki.ai/raw/wiki/entities/jev.md), [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) - **systemone**: [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) - **taxonomy**: [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md), [Cookbook: Classification using confidence](https://jevwiki.ai/raw/wiki/cookbooks/classification-using-confidence.md), [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) - **team**: [Founders and team](https://jevwiki.ai/raw/wiki/entities/team.md) - **terminology**: [Glossary](https://jevwiki.ai/raw/wiki/syntheses/glossary.md) - **testing**: [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) - **third-party**: [Press and third-party coverage](https://jevwiki.ai/raw/wiki/entities/press-and-coverage.md) - **thresholds**: [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md), [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md), [Cookbook: Line-by-line search](https://jevwiki.ai/raw/wiki/cookbooks/semantic-find.md), [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md), [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) - **timeline**: [Versions and timeline (models, SDKs, API, company)](https://jevwiki.ai/raw/wiki/syntheses/version-timeline.md) - **timeouts**: [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md) - **token-budget**: [Consult guide: could Jev help this project?](https://jevwiki.ai/raw/wiki/ideas/consult.md) - **training**: [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md) - **troubleshooting**: [FAQ for agents and developers](https://jevwiki.ai/raw/wiki/syntheses/faq.md) - **trust**: [Blog: Lies, Damned Lies, and Benchmarks](https://jevwiki.ai/raw/wiki/entities/blog-antibenchmaxxing.md) - **types**: [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) - **typesafe-ai**: [TypeSafe AI (company)](https://jevwiki.ai/raw/wiki/entities/typesafe-ai.md) - **typescript**: [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md), [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md), [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) - **ui**: [Patterns: browser, computer use, voice and product UI](https://jevwiki.ai/raw/wiki/ideas/patterns-interface.md) - **uncertainty**: [Cookbook: Self-consistency — choices](https://jevwiki.ai/raw/wiki/cookbooks/consistency-choice.md), [Cookbook: Self-consistency — nouls](https://jevwiki.ai/raw/wiki/cookbooks/consistency-noul.md) - **usage**: [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md) - **use-cases**: [Use-case map by industry](https://jevwiki.ai/raw/wiki/concepts/use-case-map.md) - **v1**: [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md) - **validation**: [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md) - **verification**: [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md), [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md) - **versions**: [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md), [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md), [Versions and timeline (models, SDKs, API, company)](https://jevwiki.ai/raw/wiki/syntheses/version-timeline.md) - **weights**: [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) - **workflow**: [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) - **workflows**: [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md) - **yes-no**: [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) --- title: "Activity log" type: log tags: [log] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: [] summary: "Append-only log of ingestion, lint, and refresh activity." --- # Activity log Append-only. Newest at the bottom. Format: `- YYYY-MM-DD — action: what changed (pages)`. - 2026-09-17 — ingest: snapshot of docs.typesafe.ai (113 pages via sitemap + llms.txt), api.typesafe.ai/openapi.json (info version 0.2.0), typesafe.ai site (home, manifesto, team, 4 blog posts, legal), evals.typesafe.ai (4 workflows), press coverage, and shallow clones of typesafe-sdk-python @420ef4f, typesafe-sdk-js @66880cc, skills @65a39f3, system-one-adapter-python @0bb819b. Manifest written to raw/MANIFEST.json. - 2026-09-17 — create: schema (CLAUDE.md) with fixed page inventory; initial pages written by parallel agents for concepts, reference, patterns, cookbooks, guides, entities, syntheses. - 2026-09-17 — create: 75 content pages written (13 concepts, 18 reference, 5 patterns, 19 cookbooks, 6 guides, 11 entities, 4 syntheses) plus generated index; lint clean (no dangling wikilinks, no orphans). - 2026-09-17 — fix: The Register article re-captured as a claim summary (raw/site/press-theregister.txt); note added on reference/python-sdk about the upstream `model="jev"` sample; note on concepts/primitives about the two upstream batching multipliers (11.5x/9.6x vs 12.2x/10.0x). - 2026-09-17 — deploy: first full deploy to https://jev-wiki.fortibus-group.workers.dev (Cloudflare Workers, static assets). - 2026-09-17 — lint: cold QA pass against the deployed site (8 agent tasks: 7 complete, 1 partial). Fixes: TypeScript routing samples on patterns/confidence-routing and patterns/intent-routing; full status table on reference/http-api; inline caveats on cookbooks/entity-alignment (model id, placeholder key, TYPESAFE_ENDPOINT, concurrency note); playbook Step 0 wording; console key-URL guidance on guides/quickstart and reference/agent-skill; llms.txt now links the playbook first; /raw/wiki/ without .md is accepted. - 2026-09-17 — style: human-facing HTML restyled to FakeNerd.ai Brand Standards Vol. I (Space Grotesk, Paper/Ink/Accent, mast with icon + wordmark → fakenerd.ai, skip link, focus rings). Agent surfaces (/raw, llms.txt, llms-full.txt, index.json) unchanged. - 2026-09-20 — ingest: owner's curated X bookmark folder "Jev" (61 posts, 19 with long-form articles) captured to raw/x/ via scripts/capture_x.py; READMEs and metadata of the 42 GitHub repos they link captured to raw/x-repos/. Raw captures are not published. - 2026-09-20 — create: community-tier ideas/ section (overview, consult, patterns [25 patterns with fit verdicts], field-reports, community-repos), each under a hard token budget. Build now emits per-page token estimates in llms.txt, index.json and wiki/index.md, a "Route by task" table at the top of llms.txt, a size warning over ~6k tokens, and lints source_tier on ideas/ pages. README gains copy-paste agent prompts. Cross-links added from guides/agent-integration-playbook, concepts/use-case-map, entities/github-repos, guides/testing-and-evaluation. - 2026-09-20 — lint: cold consult test against the deployed site (sample helpdesk project, 8 decisions). Agent read 4 pages, ~12.7k tokens (budget 15k), matched 7/8 items to patterns, and was steered away from all four planted bad uses (dollar threshold, SLA timer, reply drafting, nightly summary). Fixes applied: consult guide now groups decisions by shared state before costing, includes a worked cost example, defines the fit vocabulary, and budgets guides/choosing-a-primitive as a conditional step; patterns Sources block compacted (~450 tokens saved); homepage consult prompt points directly at ideas/consult instead of llms.txt. - 2026-09-20 — style: human-facing HTML restyled to FakeNerd.ai Brand Standards Vol. III (white page, grey cards, teal accent, IBM Plex Mono/Sans, prompt-glyph wordmark in the header, circular mark in each page's section header, 2px radius, no italics, outbound links open in a new tab). The locked hub tagline is available behind SHOW_TAGLINE in scripts/build.mjs and is off. No link to fakenerd.ai anywhere. Agent surfaces unchanged. - 2026-09-20 — ingest: @k2sbhai "7 Jev skills" article + attached audit-prompt image (raw/x/). All seven use cases already covered by ideas/patterns; added retrofit start order and community-repo vetting checklist to ideas/patterns, community audit prompt to reference/agent-skill and the README. typesafe-ai/skills re-checked: still at 65a39f3, already covered by reference/agent-skill. - 2026-09-21 — move: public URL is now https://fakenerd.ai/jev-wiki (live proxy of the jev-wiki worker). BASE_URL default updated; HTML root-relative links are prefixed with /jev-wiki and the worker accepts that prefix on any host, so header/home links no longer fall through to the host site's root. - 2026-09-21 — ingest: 5 X posts (@jerryjliu0 DocJev, @startupideaspod/Ryan Vogel, @AIGuide_ GTM list, @shannholmberg marketing list, @charliejhills repo roundup) and 13 repo READMEs (raw/x-repos now 55). Skipped @cyrilXBT Fastlane promo (no Jev mechanics). Two roundup repos (lahfir/agent-desktop, irfndi/prism-liquidity-agent) never mention Jev and are listed as such. - 2026-09-21 — restructure: ideas/ split into indexes + domain pages so consult cost stays flat as the section grows. ideas/patterns is now a ~2k-token index of 33 patterns with routing by project type; patterns live in ideas/patterns-agents (P01-P14), ideas/patterns-data (P15-P18, P24-P27; new P26 document classification/packet splitting, P27 moment finding in transcripts) and ideas/patterns-business (P19-P23, new P28-P33 incl. P33 metric-driven ad/budget/timing decisions = poor fit). ideas/community-repos is now a repo index; detail in ideas/repos-agents and ideas/repos-apps. Field reports gain DocJev pilot numbers and Vogel's email run and failures (budget raised to 4,000). Build now fails when an ideas/ page exceeds its budget. Pattern IDs are permanent. - 2026-09-21 — edit: ideas/patterns-business P33 gains a worked restructure sketch (code computes metric labels, Jev sees labels + semantic parts; request shape checked against reference/http-api), requested by the cold consult test. - 2026-09-21 — move: public URL is now https://jevwiki.ai (custom domain on the jev-wiki worker, plus www). BASE_URL default updated; links are root-relative again. jev-wiki.fortibus-group.workers.dev stays up (workers_dev: true); the /jev-wiki path prefix is still accepted for old links. The fakenerd.ai/jev-wiki copy is a stale static snapshot in another project and is no longer the canonical address. Rebrand away from FakeNerd styling pending new brand standards. - 2026-09-21 — style: human-facing HTML restyled to theconsigliere.ai Brand Standards v2.0 (ink ground, IBM Plex Mono throughout, oxblood emphasis, gilt hairlines, terminal pattern: $ prompts, # comments, bracketed statuses, ~/wiki paths, blinking caret; primary lockup in the footer; roundel favicon). FakeNerd marks and styles removed. Mark assets generated by scripts/make_brand_assets.mjs from the master PNG (transparent parchment version replaces the blend-mode knockout). Agent surfaces unchanged. - 2026-09-21 — ingest: Nate B. Jones, member guide "Find the Jev-shaped problems in your software" (read via his library MCP; used with his permission on condition of credit; digest notes only in raw/nate/, no guide text or prompts reproduced). Added: four-placement routing table on ideas/patterns; new P34 classifier inside an interface element (ideas/patterns-agents); 50-case check and shadow-mode procedure on guides/testing-and-evaluation; two fit-test disqualifiers and a sharper first step on ideas/consult; first-hand measurements and the OpenRouter route on ideas/field-reports; design detail on P18. Public sources he cites captured independently: @nedwize + kyotofin/tax-doc-classifier (P26, repos-apps; 56 repos), @iannuttall (P18), @dabit3 (P34), @gregpr07 (P12). Credit on ideas/overview and the README. Field-reports: second-hand rumour row dropped, replica table condensed to trust notes (detail lives in ideas/repos-apps). - 2026-09-21 — restructure: ideas/patterns-agents split; browser/computer/voice/UI patterns (P12-P14, P34) now on ideas/patterns-interface. ideas/field-reports split; measured numbers, gateway routes and replica trust notes now on ideas/measurements. Pattern index routes to four domain pages. - 2026-09-21 — ingest: Diogo Almeida's (@CompleteSkeptic, TypeSafe CEO) public notes on Jev-centred coding agents (raw/community/, labelled proposed/not shipped): KV-cache routing economics on P02, per-query context selection on P07, conditional AGENTS.md and hierarchical tool routing on P08, new P35 security-aware routing and P36 background read-only task triage. Grep.ai AgentRun article (@MiguelriosEN, @_aj): new P37 self-compiling workflow, vendor numbers on ideas/measurements, limitations on ideas/field-reports. Archer Hume's "Jev's architecture unmasked" (10k-call probe): empirical findings (question isolation verified, option-set effects unverified, output_tokens accounting, batching to 5,000 questions, ECE 0.031) on field-reports/measurements; deductions labelled hypotheses. Repos: ryana/jevify (prompt, linked from reference/agent-skill and consult) and kerpopule/hermes-jev-skills; index at 58. @0xCodila cited once as a restatement; @socialwithaayan used only for a star-drift caveat. Consult guide gains jevify's three opportunity kinds and skipped-judgment prompt. Team page notes Diogo's handle. --- title: "Structured instructions, options, levels, criteria" type: concept tags: [advanced, structure, instructions, criteria, taxonomy] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/primitives__advanced.md - raw/docs/api.md jev_version: "jev-1.13.0" sdk_js: "0.6.0" summary: "instructions, Choice option descriptions, Score levels and Noul true/false all accept JSON: string, object, array or null (EntryType)." --- # Structured instructions, options, levels, criteria > **TL;DR** Every prompt-bearing field of a question is an `EntryType`: `string`, `object`, `array`, or `null`. Use an object when one description carries several kinds of guidance (`what` / `not_for` / `examples`), an array when the instruction is a list of things to check, and a nested object when an option's value is a taxonomy subtree. The field names inside are yours — none are reserved, and the model sees the names along with the values. ## What it is System One models are trained to understand structure. You do not have to flatten a schema, a taxonomy, or a database row into an English sentence before sending it — put the JSON in the field directly. ## Where structure is allowed Every one of these fields is an `EntryType` (see [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md)). | Field | Applies to | Accepted shape | |---|---|---| | `instructions` | Choice, Score, Noul | `string`, `object`, `array`, or `null` | | `criteria` values (option descriptions) | Choice | `string`, `object`, `array`, or `null` | | `criteria` entries (level descriptions) | Score | `string`, `object`, `array`, or `null` | | `criteria.true` and `criteria.false` | Noul | `string`, `object`, `array`, or `null` | Note that raw/docs/api.md types the Choice `criteria` map as `map` while raw/docs/primitives__advanced.md and the JS SDK's `EntryType` allow objects and arrays as option values too. The advanced page and the SDK type are the broader, more recent statement; the worked examples below use objects and arrays as option values. ## When to structure a question - **When it helps with clarity.** When a question has multiple parts, putting them in the form of JSON helps because the keys are labeled. - **When the question needs supporting data.** A schema, a taxonomy, or a database row is already JSON. Use the JSON entirely, or pass in the relevant subfields, instead of serializing them into a string template. Start with strings. Reach for structure when the model keeps confusing two options or scoring between two levels on inputs you think are clear. ## Structured instructions One `field` object describes the field being checked, and each question refers to it by key. The same shape drives a Noul that verifies a value, a Choice that picks one from candidates, and two Scores that place a value on a scale. ```json { "state": { "source_text": "Invoice #4471 issued March 3, 2026 to Beaver Dam Logistics for $12,840.00, net 30." }, "model": "jev-latest", "questions": { "invoice_number_is_correct": { "type": "noul", "instructions": { "field": { "name": "invoice_number", "type": "string", "description": "The identifier printed on the invoice." }, "extracted_value": "4471", "question": "Does `extracted_value` match the `field` as it appears in `source_text`?" } }, "customer_name": { "type": "choice", "instructions": { "field": { "name": "customer_name", "type": "string", "description": "The organization the invoice was issued to." }, "question": "Which option is the value of `field` in `source_text`?" }, "criteria": { "Beaver Logistics": null, "Dam Logistics": null, "Beaver Dam Logistics": null, "Beaver": null, "Dam": null } }, "amount_due": { "type": "score", "instructions": { "field": { "name": "amount_due", "type": "number", "unit": "USD", "description": "The total the invoice asks to be paid." }, "question": "How large is the `field` value in `source_text`?" }, "criteria": [ "Under $1,000", "$1,000 to $10,000", "$10,000 to $100,000", "$100,000 to $1,000,000", "Over $1,000,000" ] }, "payment_terms": { "type": "score", "instructions": { "field": { "name": "payment_terms", "type": "integer", "unit": "days", "description": "Days allowed for payment, from terms such as \"net 30\"." }, "question": "How many days does the `field` in `source_text` allow for payment?" }, "criteria": [ "Due on receipt", "Net 10", "Net 30", "Net 60", "Net 90" ] } } } ``` In code you could loop over the potential records and build one of these questions per field, all sent in a single call. [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md) does something similar. Note the pattern: the *value* is extracted into bounded options (a Choice over candidate strings, a Score over bucket ranges) rather than generated — which is exactly the mitigation [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) recommends for numbers and generation. ### Arrays in instructions Use an array when the instruction is a list of things to check or to compare: ```json "instructions": { "question": "Does the claimed sender identity conflict with the sending domain?", "compare": ["ticket.sender.display_name", "ticket.sender.email"], "focus": "Compare the named organization with the email domain." } ``` ## Structured Choice options ### JSON rubric for boundary clarification ```json { "state": "I ordered the standing desk two weeks ago and tracking still says label created. Was I even charged?", "model": "jev-latest", "questions": { "department": { "type": "choice", "instructions": { "question": "Which team should handle this message?", "focus": "Classify the customer's primary request, not every topic mentioned." }, "criteria": { "billing": { "what": "Charges, invoices, refunds, or subscriptions", "not_for": "Order tracking or account access", "examples": ["I was charged twice", "Where is my refund?"] }, "orders": { "what": "Order status, delivery, cancellation, or returns", "not_for": "Charges or account access", "examples": ["Where is my package?", "Cancel my order"] }, "account": { "what": "Login, password, profile, or security", "not_for": "Charges or delivery", "examples": ["I can't log in", "Change my email"] } } } } } ``` The example tells the model what each option does and does *not* cover. It sharpens the boundary between options. `question`, `focus`, `what`, `not_for`, `examples` are names you invent — see [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md). ### Walking a taxonomy To classify into a deep taxonomy, ask one Choice per level and walk the tree in code. At each step the options are the children of the current node, and **each option's value is the child's subtree**. That lets the model see what lives under a branch before committing to it, which matters when the item belongs to a leaf whose name is not obvious from the branch name alone. ```json { "state": "32oz plastic bottle with a flip straw lid. Fits most bike cages.", "model": "jev-latest", "questions": { "department": { "type": "choice", "instructions": "Which top-level department does this product belong to?", "criteria": { "Sporting Goods": { "Cycling": ["Bike Bottles & Cages", "Bike Lights", "Helmets"], "Fitness": ["Yoga Mats", "Resistance Bands"], "Outdoor": ["Tents", "Sleeping Bags", "Hydration Packs"] }, "Home & Kitchen": { "Drinkware": ["Water Bottles", "Travel Mugs", "Tumblers"], "Cookware": ["Pots & Pans", "Bakeware"] }, "Baby & Toddler": ["Sippy Cups", "Bottle Warmers", "Bibs"] } } } } ``` The bottle plausibly fits under two departments. Showing the subtrees lets the model see that both `Sporting Goods > Cycling > Bike Bottles & Cages` and `Home & Kitchen > Drinkware > Water Bottles` exist, and weigh the listing's emphasis on bike cages against everyday drinkware. The `probabilities` on this answer tell you whether the split is close enough to explore both branches. Once a department is chosen, ask the next Choice with that department's children as the options and their subtrees as the values, and repeat until you reach a leaf. In code this could be a loop over a nested dict, where each question's `criteria` is simply the current node. [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) shows a similar walk, including a beam search that keeps several candidate paths alive when the probabilities are close. **Subtrees can get large.** If a branch is too large, trim the value to its direct children and a sample of leaves. ## Structured Score levels Each entry in a Score `criteria` array can be an object. Use the same field names on every level. ```json { "state": "Fixed the null check in the payment handler. Also refactored the retry loop while I was in there, and bumped the SDK version since the old one had that timeout bug.", "model": "jev-latest", "questions": { "pr_scope": { "type": "score", "instructions": { "question": "How focused is this pull request description on a single change?", "note": "Judge the number of independent changes, not the size of any one change." }, "criteria": [ { "summary": "One change, clearly stated", "signals": [ "A single fix or feature", "Nothing described as \"also\" or \"while I was in there\"" ] }, { "summary": "One main change plus a small related tweak", "signals": [ "A primary change and one minor adjacent edit", "The tweak supports the main change" ] }, { "summary": "Several independent changes bundled together", "signals": [ "Two or more unrelated fixes or features", "Changes that could each be their own PR" ] } ] } } } ``` Note that the Score `legend` in the response echoes structured levels back verbatim — see the worked response in [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md). ## Structured Noul criteria Noul `criteria` is optional; when the yes/no boundary is subtle, structured `true` and `false` descriptions let you pin it down with a definition and examples on each side. ```json { "state": { "sender": { "display_name": "Beaver Dam Builders Ltd.", "email": "donotreply@payroll.example" }, "message": "Your Q3 bonus is ready. Reply with your login password so we can verify your identity and release the funds." }, "model": "jev-latest", "questions": { "requests_credentials": { "type": "noul", "instructions": { "question": "Does the `message` ask the recipient to disclose a sensitive credential?", "inspect": "message", "focus": "Look for a request to send the credential itself, not a request to change or reset it." }, "criteria": { "true": { "what": "Asks the recipient to reply with, type, or send a password, PIN, one-time code, or other security sensitive answer", "examples": [ "Reply with your password", "Send us the 6-digit code you just received" ] }, "false": { "what": "No sensitive credential is requested", "examples": [ "Reset your password from the settings page", "Your statement is ready" ] } } } } } ``` The `focus` line here does the work that [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) calls "state the exact condition": it rules out the neighbouring case (reset requests) that a literal reading would otherwise sweep in. ## Gotchas - **No field names are reserved.** `what`, `not_for`, `examples`, `question`, `focus`, `note`, `signals`, `field`, `inspect`, `compare` are all invented in the docs' examples. Use short names that label what follows, and keep them consistent across sibling options or levels. - **The model sees the key names.** A badly named key is a badly worded prompt. - **Structure is not a substitute for a clear instruction.** Adding JSON to a question that is really two questions still hides two judgments in one question. - **Large subtrees cost tokens and add distractors** — the state and questions share one token budget, and [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) warns that irrelevant detail costs accuracy. - Choice option *names* remain plain strings and are what comes back in `choice` and in the `probabilities` keys, however structured the descriptions are. ## Related - [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md), [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) — the per-type contracts - [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) — when to escalate from a string to an object - [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) — literal reading, indirection, context rot - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — declared wire types - [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) — `EntryType`, `ChoiceCriteria`, `ScoreCriteria` - [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md), [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md) — structure in production shapes ## Sources - raw/docs/primitives__advanced.md (https://docs.typesafe.ai/primitives/advanced) - raw/docs/api.md (https://docs.typesafe.ai/api) --- title: "Choice questions" type: concept tags: [choice, primitives, classification, probabilities, confidence] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/primitives__choice.md - raw/docs/api.md - raw/docs/primitives.md jev_version: "jev-1.13.0" sdk_python: "0.6.0" summary: "Choice picks one option from a fixed set: send type/instructions/criteria, get back choice, probabilities over every option, and confidence." --- # Choice questions > **TL;DR** `{"type": "choice", "instructions": "...", "criteria": {"option": "description or null", ...}}`. The answer is `{"type": "choice", "choice": "", "probabilities": {option: float summing to 1}, "confidence": 0..1}`. Up to 255 options. Add an `other` option when your list may not cover every input; read `probabilities` and `confidence`, not just `choice`. ## When to use / when not to use Use a Choice when the answer is one of a fixed set of options: which team handles a ticket, which category a product belongs to, which language a code snippet is written in. - If the answer is a position on a spectrum → [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md). - If it's a yes or no → [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md). - Full comparison: [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md). Example questions from raw/docs/primitives__choice.md: ``` "What programming language is this code written in" → options: python, javascript, typescript, go, rust, other "What type of meeting is this based on the title and description" → options: standup, planning, retrospective, one on one, brainstorm, none of the above "Which product category does this item belong to" → options: electronics, clothing, home garden, food and beverage ``` ## Request contract The POST body to the [TypeSafe API](https://jevwiki.ai/raw/wiki/reference/http-api.md) has three top-level fields: `state` (the content to evaluate), `model`, and `questions` (a map from question ids you choose to question objects). | Field | Type | Required | Description | |---|---|---|---| | `type` | `"choice"` | yes | Always `"choice"`. | | `instructions` | `string \| object \| array` | yes | What the model should decide — the question it answers. | | `criteria` | `map` | yes | The answer options. Each key is an option name; each value is a description of that option, or `null` when the option needs no extra detail. | Field types are as spelled in raw/docs/api.md. Per [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md), `instructions` and each `criteria` value may also be an object or an array (both are `EntryType`, which also permits `null`). You choose the question id; the answer comes back under the same id, and **the model never sees the id**. The option names *and* their descriptions are both sent to the model, so write descriptions that separate the options from each other. ### Minimal request ```json { "state": "My running shoes arrived in the wrong size. Can I swap them for a size 10?", "model": "jev-latest", "questions": { "department": { "type": "choice", "instructions": "Which team should handle this?", "criteria": { "returns": "Exchanges, refunds, wrong or damaged items", "shipping": "Delivery status, delays, lost packages", "billing": "Charges, invoices, payment problems" } } } } ``` The same question in the Python SDK: ```python from typesafe_sdk import Choice, TypeSafeClient with TypeSafeClient() as client: response = client.system_one( state="My running shoes arrived in the wrong size. Can I swap them for a size 10?", questions={ "department": Choice( instructions="Which team should handle this?", criteria={ "returns": "Exchanges, refunds, wrong or damaged items", "shipping": "Delivery status, delays, lost packages", "billing": "Charges, invoices, payment problems", }, ), }, ) print(response.answers["department"].choice) ``` Use the `system_one` method or the `https://api.typesafe.ai/v1/systemone` endpoint. The `model` field selects which model handles the request. In the JavaScript SDK the helper is `choice(instructions, criteria)`, returning a `ChoiceQuestion` — see [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md). ## Response contract | Field | Type | Description | |---|---|---| | `type` | `"choice"` | Matches the question type. | | `choice` | `string` | The option with the highest probability. | | `probabilities` | `map` | Every option mapped to its probability. The values sum to 1. | | `confidence` | `number` | 0 to 1, computed from how `probabilities` is spread. A flat shape (probability spread across several options) means low confidence; a single peak means high confidence. | ```json { "model": "jev-latest", "answers": { "department": { "type": "choice", "choice": "returns", "confidence": 1.0, "probabilities": { "shipping": 0.0, "returns": 1.0, "billing": 0.0 } } }, "usage": { "input_tokens": 330, "output_tokens": 34 } } ``` This ticket is an easy one, so all of the probability is on `returns` and confidence is 1.0. A ticket that mentioned a wrong size *and* a missing refund would split probability between `returns` and `billing`, and confidence would drop. See [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md). ## Option limits and coverage - A Choice question accepts **up to 255 options**. - Adding options costs a few tokens each, so give the model the full list of teams, categories, or products rather than a shortlist. - Add an `other` or `none of the above` option when the list might not cover every input, so the model can say none of the others fit. - For a deep hierarchy or large taxonomy, chain Choice questions level by level; [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) runs a beam search over Choice probabilities, keeping the best `K` candidate paths at each level instead of committing to a single greedy path. ## Ask more than one Choice per call Ask every Choice question your code might need in a single request rather than one request per question. Questions are evaluated in parallel; adding questions barely changes the response time, and the code can ignore answers it doesn't need. Extra questions still cost tokens. See [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) and [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md). ### Worked example: five Choice questions, one ambiguous ticket State: `"Shoes arrived two weeks late and in the wrong size. Also I see two charges on my card. What are you going to do about this?"` ```json { "state": "Shoes arrived two weeks late and in the wrong size. Also I see two charges on my card. What are you going to do about this?", "model": "jev-latest", "questions": { "department": { "type": "choice", "instructions": "Which team should handle this?", "criteria": { "returns": "Exchanges, refunds, wrong or damaged items", "shipping": "Delivery status, delays, lost packages", "billing": "Charges, invoices, payment problems" } }, "return_reason": { "type": "choice", "instructions": "If the customer wants to return something, why?", "criteria": { "wrong_size": "The item doesn't fit", "wrong_item": "A different product was delivered", "damaged": "The item arrived broken or faulty", "changed_mind": "The item is fine, the customer no longer wants it", "other": "A return reason that fits none of the above" } }, "shipping_issue": { "type": "choice", "instructions": "If this is a shipping problem, which kind is it?", "criteria": { "not_delivered": "The package never arrived", "delayed": "The package is late but still on its way", "wrong_address": "The package went to the wrong place", "damaged_in_transit": "The package arrived damaged", "other": "A shipping problem that fits none of the above" } }, "requested_resolution": { "type": "choice", "instructions": "What does the customer want to happen?", "criteria": { "exchange": "Swap the item for a different one", "refund": "Money back", "replacement": "The same item sent again", "information": "Just an answer, no action needed" } }, "tone": { "type": "choice", "instructions": "What is the customer's tone?", "criteria": { "calm": null, "frustrated": null, "angry": null } } } } ``` Two of these are speculative: `return_reason` only matters if `department` is `returns`, and `shipping_issue` only if it's `shipping`. The `tone` question uses `null` descriptions because the option names are clear on their own. Response: ```json { "model": "jev-latest", "answers": { "department": { "type": "choice", "choice": "returns", "confidence": 0.39, "probabilities": { "shipping": 0.02, "billing": 0.38, "returns": 0.6 } }, "return_reason": { "type": "choice", "choice": "wrong_size", "confidence": 1.0, "probabilities": { "wrong_size": 1.0, "wrong_item": 0.0, "other": 0.0, "changed_mind": 0.0, "damaged": 0.0 } }, "shipping_issue": { "type": "choice", "choice": "delayed", "confidence": 0.53, "probabilities": { "delayed": 0.63, "other": 0.37, "damaged_in_transit": 0.0, "not_delivered": 0.0, "wrong_address": 0.0 } }, "requested_resolution": { "type": "choice", "choice": "exchange", "confidence": 0.16, "probabilities": { "information": 0.1, "exchange": 0.37, "replacement": 0.24, "refund": 0.29 } }, "tone": { "type": "choice", "choice": "frustrated", "confidence": 0.88, "probabilities": { "angry": 0.08, "frustrated": 0.92, "calm": 0.0 } } }, "usage": { "input_tokens": 588, "output_tokens": 212 } } ``` How to read it: - `department` is `returns` at probability 0.60, but `billing` has 0.38 because of the double charge, which lowers confidence to 0.39. The top option is clear enough to act on, but **the second option is not noise**. - `return_reason` is `wrong_size` at confidence 1.0 — the ticket says so clearly. - `shipping_issue` is split between `delayed` (0.63) and `other` (0.37). It is speculative and `department` didn't come back as shipping, so the code ignores it. - `requested_resolution` confidence is 0.16 because the distribution is flat: the customer didn't say what they want. - `tone` is `frustrated` at probability 0.92, confidence 0.88. ### Reading those answers in code ```python from typesafe_sdk import Choice, TypeSafeClient TRIAGE_QUESTIONS = { "department": Choice( instructions="Which team should handle this?", criteria={ "returns": "Exchanges, refunds, wrong or damaged items", "shipping": "Delivery status, delays, lost packages", "billing": "Charges, invoices, payment problems", }, ), "return_reason": Choice( instructions="If the customer wants to return something, why?", criteria={ "wrong_size": "The item doesn't fit", "wrong_item": "A different product was delivered", "damaged": "The item arrived broken or faulty", "changed_mind": "The item is fine, the customer no longer wants it", "other": "A return reason that fits none of the above", }, ), "shipping_issue": Choice( instructions="If this is a shipping problem, which kind is it?", criteria={ "not_delivered": "The package never arrived", "delayed": "The package is late but still on its way", "wrong_address": "The package went to the wrong place", "damaged_in_transit": "The package arrived damaged", "other": "A shipping problem that fits none of the above", }, ), "requested_resolution": Choice( instructions="What does the customer want to happen?", criteria={ "exchange": "Swap the item for a different one", "refund": "Money back", "replacement": "The same item sent again", "information": "Just an answer, no action needed", }, ), "tone": Choice( instructions="What is the customer's tone?", criteria={"calm": None, "frustrated": None, "angry": None}, ), } def triage(ticket: str) -> None: with TypeSafeClient() as client: response = client.system_one( state=ticket, questions=TRIAGE_QUESTIONS, ) answers = response.answers department = answers["department"] if department.confidence < 0.3: # Not clear which team to send to. Let a person decide. send_to_manual_triage(ticket) return if department.choice == "returns": # return_reason answer is only used here assign(ticket, team="returns", issue=answers["return_reason"].choice) elif department.choice == "shipping": # shipping_issue answer is only used here assign(ticket, team="shipping", issue=answers["shipping_issue"].choice) else: assign(ticket, team="billing") # A second team with a real share of the probability gets a copy for team, probability in department.probabilities.items(): if team != department.choice and probability > 0.25: notify(ticket, team=team) resolution = answers["requested_resolution"] if resolution.confidence < 0.5: # The customer hasn't said what they want. Ask, don't guess. ask_customer_what_they_want(ticket) elif resolution.choice == "refund": flag_for_refund_approval(ticket) if answers["tone"].choice == "angry": flag_for_senior_agent(ticket) ``` For the ticket above this assigns the ticket to the returns team with issue `wrong_size`, sends the billing team a copy, and asks the customer what they want. The code does not use the `shipping_issue` answer. One request, five answers, and the routing logic is ordinary `if` statements. Adding another Choice question keeps the request count at one. The [smart home assistant demo](https://jevwiki.ai/raw/wiki/guides/smart-home-demo.md) evaluates every user request against a long list of Choice questions in one call: request category, room, device, and action — most irrelevant to any one request, and the code ignores them. ## Structured instructions and criteria Start with a one-line description per option. When two options are similar and the model keeps confusing them, describe each one with an **object** instead of a string: what the option covers, what belongs to a neighboring option instead, and a few example inputs. ```json { "state": "I sent the shoes back a week ago. When do I get my money?", "model": "jev-latest", "questions": { "return_topic": { "type": "choice", "instructions": { "question": "Which returns topic is the customer asking about?", "focus": "Classify the information the customer wants." }, "criteria": { "return_policy": { "what": "Whether and how an item can be returned", "not_for": "Progress of a return already sent", "examples": [ "Can I return shoes I've worn once?", "How long do I have to return an order?" ] }, "return_status": { "what": "Progress of a return already sent", "not_for": "Whether and how an item can be returned", "examples": [ "Has my return arrived yet?", "When will my refund be paid?" ] } } } } } ``` ```json { "model": "jev-latest", "answers": { "return_topic": { "type": "choice", "choice": "return_status", "confidence": 1.0, "probabilities": { "return_policy": 0.0, "return_status": 1.0 } } }, "usage": { "input_tokens": 407, "output_tokens": 32 } } ``` The field names `question`, `focus`, `what`, `not_for`, and `examples` are **not part of the API, and none are reserved**. You choose them, the same way you choose option names. The model sees the names along with the values, so use short names that label what follows. More shapes — including taxonomy subtrees as option values — in [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md). ## Gotchas - `choice` alone throws away information. A 0.60/0.38 split and a 1.00/0.00 split both produce the same `choice`. Gate on `confidence` or inspect `probabilities` ([Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md)). - An option not in `criteria` can never be returned. Without an `other`, the probability mass lands on whichever listed option is least wrong. - A Choice is **relative** (which option), while a Noul is **absolute** (is this true). Per [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md), a Choice over options and one Noul per option answer different questions, and a threshold tuned on one does not carry over to the other. - Do not use numbers as option names hoping for ordering — that is what Score is for. ## Related - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — the three types and how to batch them - [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md), [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) — the other two primitives - [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) — decision table - [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) — phrasing rules and before/after examples - [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) — JSON options, rubrics, taxonomies - [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) — what `confidence` means - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — wire contract - [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md) — `Choice` in the Python SDK - [Intent routing](https://jevwiki.ai/raw/wiki/patterns/intent-routing.md), [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md), [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) - [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) — beam search over Choice probabilities ## Sources - raw/docs/primitives__choice.md (https://docs.typesafe.ai/primitives/choice) - raw/docs/api.md (https://docs.typesafe.ai/api) - raw/docs/primitives.md (https://docs.typesafe.ai/primitives) --- title: "Confidence vs probability" type: concept tags: [confidence, probabilities, thresholds, routing, calibration] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/confidence.md - raw/docs/introduction.md - raw/docs/concepts__how-to-build-with-system-one.md - raw/docs/models.md jev_version: "jev-1.13.0" sdk_python: "0.6.0" summary: "confidence is a 0-1 statistic derived from an answer's probabilities distribution; Choice and Score carry it, Noul does not." --- # Confidence vs probability > **TL;DR** `probabilities` is the full distribution over your Choice options or Score levels. `confidence` collapses that distribution's *shape* into one number from 0 to 1 so you can threshold on it directly. Choice and Score answers carry `confidence`; **Noul answers do not**. Gate different actions at different thresholds according to their stakes. ## The two fields | Field | On which answers | Type | Meaning | |---|---|---|---| | `probabilities` | Choice, Score | distribution over options (Choice) or levels (Score) | The model's probability mass on each possible outcome. | | `confidence` | Choice, Score | number, 0 to 1 | A statistic computed from `probabilities` that summarizes how concentrated the distribution is. | | `choice` | Choice | the option key | The selected option. | | `score` | Score | number | The score on your rubric. | | `noul` | Noul | number, 0–1 | The probability the statement is true. Noul answers do not carry a `confidence` property. | (The `choice` / `score` / `noul` rows and the "Noul (0–1)" typing come from `raw/docs/introduction.md`; the rest from `raw/docs/confidence.md`.) ## How confidence differs from probability All Score and Choice answers include a `probabilities` property representing the probability distribution across the options (for Choice) or levels (for Score). **The shape of that distribution is what tells you how certain the model is**: concentrated on one outcome means a confident answer, spread out means an uncertain one. `confidence` is a statistic computed from the probability distribution the answer already gives you. TypeSafe computes it for you and returns it on every Choice and Score answer, so the common case needs no extra work on your side. The distinction that matters in code: - A **probability** answers "how likely is *this particular outcome*?" - **Confidence** answers "how decisive is the distribution as a whole?" A flatter distribution means lower confidence. Low confidence on a Choice often means **none of the options are a clear winner** over the others. Low confidence on a Score often means the levels are **ambiguous, multi-dimensional, or the state doesn't contain enough to go on** — which is usually a signal to fix the question or the state, not just to escalate. > **A solid default.** TypeSafe provides `confidence` "as a convenient measure that fits most use-cases, but you are never locked into our definition. Depending on what you are evaluating, a different measure may serve you better, which is exactly why we give you the full `probabilities` in the response." The docs do **not** publish the exact formula; they defer the pros and cons of different computations to a future cookbook. If you need a specific measure (entropy, margin between top-two, etc.), compute it yourself from `probabilities`. (The formula being unpublished is stated in the source; treating margin/entropy as your alternatives is inferred.) ## "I don't know" is a useful signal > "If an intelligent system, whether human or machine, cannot express honest uncertainty, the system cannot be trusted." Confidence gives you a built-in mechanism for the model to say "I'm not sure about this one." This lets your code implement different behavior for different levels of certainty, which the docs call the foundation for building systems you can actually rely on. ## Three paths for using confidence A useful starting pattern is to divide confidence into three ranges, each producing a different system behavior: | Band | Behavior | |---|---| | **High confidence** | Act automatically. The model has a clear read and you can proceed without human involvement. | | **Medium confidence** | Proceed with caution. The model has a reasonable answer but is not certain. Depending on context, ask the user to confirm, flag for review, or gather more information before acting. | | **Low confidence** | Do not act. Route to a human, request clarification, or fall back to a different system. The model is telling you it does not have enough information or the question is not a good fit. | Where you draw those boundaries depends on the stakes. The source does **not** attach numbers to these three bands. ## Thresholds scale with risk A confidence threshold is not one number. Different actions within the same system should be gated at different levels depending on the consequences of getting it wrong. ```python theme={null} response = client.system_one( state=user_message, questions={ "action": Choice( instructions="What is the user trying to do?", criteria={ "check_balance": "View account balance", "approve_transfer": "Approve the pending withdrawal request", "support": "Get help with an issue", }, ), }, ) action = response.answers["action"] confidence = action.confidence if confidence < 0.5: # Model is genuinely unsure. Don't guess. route_to_human(user_message) elif action.choice == "check_balance": # Low stakes. Showing the wrong screen is recoverable. show_balance(account_id) elif action.choice == "approve_transfer": if confidence > 0.9: # High stakes, high confidence. Proceed with confirmation. confirm_then_execute(account_id) else: # High stakes, moderate confidence. Verify first. ask_user_to_confirm(account_id) ``` The `0.5` confidence floor catches anything the model reports as genuinely uncertain. Above that, the threshold for acting without confirmation is higher for a destructive operation (`> 0.9`) than for a read-only one (no extra gate). **Your code encodes the risk tolerance.** > The correct threshold values depend on your domain and the performance of the model for your use case. Start with conservative thresholds, test with your own data, and adjust as you observe results. Note the shape of this example: the confidence floor is checked **first**, before the `choice` is branched on. Reading `.choice` without checking `.confidence` throws away the reason to use a calibrated model at all. Other threshold values that appear elsewhere in the docs, for calibration of your own expectations — not as recommended defaults: | Threshold | Context | Source | |---|---|---| | `confidence < 0.5` | Route to human, any action | raw/docs/confidence.md | | `confidence > 0.9` | Act on a high-stakes, destructive action | raw/docs/confidence.md | | `confidence < 0.8` | Route a Choice to human review | raw/docs/concepts__how-to-build-with-system-one.md | | `confidence < 0.75` | Route a support-ticket topic Choice to human review | raw/docs/concepts__how-to-build-with-system-one.md | | `confidence >= 0.7` | Trust a Score before acting on its value | raw/docs/concepts__how-to-build-with-system-one.md | ## Gotchas - **Noul has no `confidence`.** For a yes/no question the probability *is* the uncertainty: `noul` near `0.5` is the uncertain case. Do not write `answers["x"].confidence` against a Noul answer. - **Confidence is not accuracy for one item.** Calibration is a property of groups of predictions; see [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md). - **High confidence on the wrong question is still wrong.** A confidently answered broad question hides its compound judgment — decompose first, per [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md). - **Aliases move thresholds.** If you have tuned confidence thresholds against a specific version, pin that versioned model ID (e.g. `jev-1.13.0`) instead of `jev-latest`. See [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md). - **Test thresholds empirically.** The docs suggest plotting confidence against accuracy on your own data rather than adopting any number from the docs. ## Related - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — which answers carry which fields - [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md) / [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) / [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) — per-primitive response shape - [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) — the pattern this page underpins - [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md) — why the probabilities are calibrated - [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) — where confidence sits in the design workflow - [Cookbook: Classification using confidence](https://jevwiki.ai/raw/wiki/cookbooks/classification-using-confidence.md) — a worked recipe - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — pinning versions before tuning thresholds ## Sources - raw/docs/confidence.md (https://docs.typesafe.ai/confidence) - raw/docs/introduction.md (https://docs.typesafe.ai/introduction) — per-type return fields - raw/docs/concepts__how-to-build-with-system-one.md (https://docs.typesafe.ai/concepts/how-to-build-with-system-one) — additional threshold examples --- title: "How to build software with System One" type: concept tags: [architecture, design, decomposition, workflow, composition] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/concepts__how-to-build-with-system-one.md jev_version: "jev-1.13.0" sdk_python: "0.6.0" summary: "Build a normal software workflow and insert System One only where AI is needed: narrow typed questions, composed in code." --- # How to build software with System One > **TL;DR** Keep control flow, deterministic rules, and side effects in code. Break broad judgments into narrow, typed questions with explicit `instructions` and `criteria`. Give each question only the context it needs. Ask many independent questions in one request (they run in parallel), combine the answers with your own weights and thresholds, and route on `confidence`. ## What it is System One is TypeSafe's model for building **AI-powered software, not agents**. It does not generate code or choose its own next action. It provides AI primitives that embed into software, so code remains in control while the model handles common-sense judgments over unstructured data. The docs' own summary — build a normal software workflow and insert System One only where AI is needed: - Keep control flow, deterministic rules, and side effects in code. - Break broad judgments into narrow, typed questions with explicit instructions and criteria. - Give each question only the context it needs. - Use probabilities and confidence to act, ask for review, or escalate. - Ask independent questions together, then compose their answers in code. ### Three software architectures | Architecture | How it works | |---|---| | Traditional software | A complex decision tree made from simple software primitives. Because each primitive is reliable, developers compose them into higher-level abstractions. | | LLM agents | An agent processes instructions and chooses its next step. Works well when a person is monitoring, but every loop introduces another opportunity to go off the rails. | | AI-powered software | Code handles deterministic work and owns control flow. The model appears only where the system needs programmable common sense or must interpret unstructured data. Each AI task is kept atomic and constrained. | ### What makes System One composable | Property | What it buys you | |---|---| | **Structured** | Type-safe by construction. Decisions and probabilities conform to the software types and JSON schema your code expects; code never has to recover a value from generated prose. | | **Parallel** | Questions are evaluated independently and in parallel. One primitive's result does not become hidden context that changes another's. | | **Comparable** | Outputs are sortable and can drive smart `if` statements, thresholds, and comparisons. | | **Fast** | Most queries complete in about 100 ms — fast enough for real-time request paths and user interfaces. | | **Calibrated confidence** | RLCD ([AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md)) communicates uncertainty through calibrated probabilities instead of tending toward overconfidence. | | **Self-consistent** | Designed to return stable answers across repeated evaluations. See [Cookbook: Self-consistency — nouls](https://jevwiki.ai/raw/wiki/cookbooks/consistency-noul.md). | Because every output is constrained to the supplied options, the model returns a full probability distribution over those options rather than inventing a value outside the schema. TypeSafe states its target is a **greater than 100× intelligence-to-speed-and-cost ratio**, on the bet that cheaper intelligence creates much more demand. ## The design workflow (7 steps) ### 1. Use code when you can Keep deterministic work in code. It is reliable and cheap. Avoid agent `while` loops when a software workflow can express the same behavior. ```python theme={null} days_overdue = (today - invoice.due_date).days if days_overdue > 30: route_to_collections(invoice) ``` See [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) for bounded ways to compose model decisions with code. ### 2. Decompose the input state Include only the context relevant to the current questions. This helps the model avoid distractions and context rot. Do not rely on knowledge stored in model weights when current information can come from your own knowledge base. ```json title="request" theme={null} { "state": { "ticket_message": "My flight was cancelled. Can I get a refund?", "refund_policy": "Cancelled flights are eligible for a full refund." }, "questions": { "policy_supports_refund": { "type": "noul", "instructions": "Does the refund policy support the refund requested in the ticket?" } } } ``` ### 3. Use structure in the input state Use nested JSON for the `state` and `questions` fields. Point questions at specific values when that removes ambiguity, and **include the backtick characters around each path inside the question**. Use a backticked dot-and-index path such as `` `support.tickets[0].message` ``. ```json title="request" theme={null} { "state": { "support": { "tickets": [ { "message": "I was charged twice for order A-104." }, { "message": "How do I reset my password?" } ] }, "commerce": { "orders": [ { "id": "A-104", "charges": [ { "amount_usd": 49, "status": "captured" }, { "amount_usd": 49, "status": "captured" } ] } ] }, "account": { "security": { "password_reset": "Email a reset link to the address on file." } } }, "questions": { "duplicate_charge": { "type": "noul", "instructions": "Do `support.tickets[0].message` and `commerce.orders[0].charges` indicate a duplicate charge?" }, "password_reset_supported": { "type": "noul", "instructions": "Can `account.security.password_reset` resolve the request in `support.tickets[1].message`?" } } } ``` ### 4. Decompose the questions Ask the most explicit, narrow, specific, atomic questions you can. Break down complex or ill-defined questions into separate questions that each evaluate one property. > The docs flag this as "probably the most important concept in this guide. Broad questions hide several judgments behind one answer. Atomic questions expose those judgments so you can inspect, tune, and combine them in code." **Worked example — spam detection.** One broad question (bad): ```json title="One broad question (bad)" theme={null} { "is_spam": { "type": "noul", "instructions": "Is `message` spam?" } } ``` Decomposed questions (good), over a state whose `message` has `sender.display_name` `"Acme Payroll"`, `sender.email` `"rewards@claim-bonus.example"`, subject `"Urgent: claim your employee bonus"`, a bonus-offer body, and a `links[0]` of text `"Claim bonus"` → `http://claim-bonus.example/acme`: ```json title="Decomposed questions (good)" theme={null} { "requests_credentials": { "type": "noul", "instructions": "Does `message.body` ask the recipient to provide a password or other login credential?" }, "offers_unexpected_reward": { "type": "noul", "instructions": "Does `message.body` claim the recipient received an unexpected prize, payment, or reward?" }, "creates_time_pressure": { "type": "noul", "instructions": "Does `message.subject` or `message.body` pressure the recipient to act quickly?" }, "sender_identity_mismatch": { "type": "noul", "instructions": "Does the organization named in `message.sender.display_name` conflict with the domain in `message.sender.email`?" }, "link_domain_mismatch": { "type": "noul", "instructions": "Does the domain in `message.links[0].url` conflict with the organization named in `message.sender.display_name`?" }, "disguises_link_destination": { "type": "noul", "instructions": "Does `message.links[0].text` conceal or misrepresent the destination in `message.links[0].url`?" } } ``` **Worked example — verifying a tool-call trace.** The bad version asks one question, `tool_calls_are_correct`: *"Is `trace.tool_calls` correct for `request` and `available_tools`?"* The good version asks nine, each checking one property of the same state (a `request` for Seattle weather in fahrenheit on `2026-09-03`, an `available_tools` map with `geocode_city` and `get_weather`, and a `trace` where `tool_calls[1].arguments.unit` is `"celsius"`): ```json title="Decomposed questions (good)" theme={null} { "geocode_tool_is_relevant": { "type": "noul", "instructions": "Is `trace.tool_calls[0].name` an appropriate tool for resolving `request.location`?" }, "geocode_location_matches": { "type": "noul", "instructions": "Does `trace.tool_calls[0].arguments.city` match `request.location`?" }, "geocode_arguments_match_schema": { "type": "noul", "instructions": "Does `trace.tool_calls[0].arguments` conform to `available_tools.geocode_city.parameters`?" }, "geocode_result_matches_call": { "type": "noul", "instructions": "Does `trace.tool_results[0].tool_call_id` match `trace.tool_calls[0].id`?" }, "weather_tool_is_relevant": { "type": "noul", "instructions": "Is `trace.tool_calls[1].name` an appropriate tool for answering `request.text`?" }, "weather_arguments_match_schema": { "type": "noul", "instructions": "Does `trace.tool_calls[1].arguments` conform to `available_tools.get_weather.parameters`?" }, "weather_uses_geocoded_coordinates": { "type": "noul", "instructions": "Do the coordinates in `trace.tool_calls[1].arguments` match those in `trace.tool_results[0].output`?" }, "weather_date_matches": { "type": "noul", "instructions": "Does `trace.tool_calls[1].arguments.date` match `request.date`?" }, "weather_unit_matches": { "type": "noul", "instructions": "Does `trace.tool_calls[1].arguments.unit` match `request.unit`?" } } ``` The payoff: the broad question returns one number that hides the unit mismatch; the decomposed set isolates it in `weather_unit_matches`. ### 5. Use structure in the questions Keep atomic questions short. When `instructions` or `criteria` need several kinds of guidance, use objects or arrays with named fields instead of flattening everything into a dense prose string. This makes the decision boundary easier to scan, review, and tune. For a Choice, describe **what belongs in each option**, **what belongs in a neighboring option instead** (`not_for`), and a few representative `examples`. Use the same field names across options so the model can compare them directly. ```json title="questions" theme={null} { "card_help_topic": { "type": "choice", "instructions": { "question": "Which disposable virtual card topic is the user asking about?", "focus": "Classify the information the user wants." }, "criteria": { "get_disposable_virtual_card": { "what": "Purpose, eligibility, or setup", "not_for": "Quantity, transaction, or merchant restrictions", "examples": [ "How can I get a disposable virtual card?", "What are disposable cards for?" ] }, "disposable_card_limits": { "what": "Quantity, transaction, or merchant restrictions", "not_for": "Purpose, eligibility, or setup", "examples": [ "How many disposable cards can I make per day?", "Where can I use a disposable card?" ] } } } } ``` (State for that example: the string `"How many disposable virtual cards can I make per day?"`.) A short, unambiguous question or criterion can remain a string. Add structure when it separates guidance that would otherwise blur together. See [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) for the full set of places structure is accepted. ### 6. Ask a lot of questions Ask many narrow, independent questions about the same state in one request. This is how you maximize effectiveness and intelligence per dollar with the API: questions run in parallel, and code can combine their signals without adding serial model round trips. See [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) and [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md). ### 7. Combine outputs in code, then route on uncertainty Combine independent answers with deterministic rules or weighted sums. For learned composition, use the probabilities as features in a downstream classical ML model. ```python theme={null} answers = response.answers # Combine independent signals into one application-specific score. quality = ( 0.4 * answers["answers_request"].noul + 0.4 * answers["citations_are_supported"].noul + 0.2 * (1 - answers["contradicts_context"].noul) ) ``` Make code take different actions for confident and unconfident answers. Escalate uncertain cases to a person or a more expensive reasoning model. Test thresholds by plotting confidence against accuracy on your data. ```python theme={null} answer = response.answers["card_help_topic"] if answer.confidence < 0.8: route_to_human_review(ticket) else: route_to_handler(answer.choice, ticket) ``` See [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) for preserving individual judgments while combining them, [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md) for training a classical model on System One outputs when you lack labels (use an ensemble of expensive reasoning models to generate them), and [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) for matching thresholds to the risk of each action. > **Tip from the docs:** decomposition does not require more round trips. Questions over the same state run in parallel. ## Putting it all together The full worked example from the docs: a support-ticket triage that keeps deterministic work in code, sends only relevant structured context, evaluates many atomic questions in one request, and composes the answers with explicit confidence gates. ```python title="triage_ticket.py" theme={null} from typesafe_sdk import Choice, Noul, NoulCriteria, Score, TypeSafeClient def triage_ticket(ticket, customer): # Handle deterministic states without calling a model. if ticket["status"] == "closed": return "no_action" open_orders = [ order for order in customer["orders"] if order["status"] != "delivered" ] # Include only the structured context needed by the questions below. state = { "ticket": { "message": ticket["message"], "sender": ticket["sender"], "links": ticket["links"], }, "customer": { "plan": customer["plan"], "open_orders": open_orders, }, "policy": { "sensitive_credentials": ["password", "security code", "API key"], }, } # Ask structured, atomic questions together so they run in parallel. questions = { "topic": Choice( instructions={ "question": "Which team should handle `ticket.message`?", "focus": "Classify the customer's primary request.", }, criteria={ "billing": { "what": "Charges, invoices, refunds, or subscriptions", "not_for": "Order tracking or account access", "examples": ["I was charged twice", "Where is my refund?"], }, "orders": { "what": "Order status, delivery, cancellation, or returns", "not_for": "Charges or account access", "examples": ["Where is my order?", "Cancel my shipment"], }, "account": { "what": "Login, profile, permissions, or security", "not_for": "Charges or order tracking", "examples": ["Reset my password", "I cannot sign in"], }, }, ), "requests_credentials": Noul( instructions={ "question": "Does the message request a sensitive credential?", "compare": [ "`ticket.message`", "`policy.sensitive_credentials`", ], "focus": "Look for a request to disclose the credential itself.", }, criteria=NoulCriteria( true={ "what": "Asks the recipient to disclose a listed credential", "examples": [ "Reply with your password", "Send us your API key", ], }, false={ "what": "Does not ask the recipient to disclose a credential", "not_for": "A legitimate instruction to reset a credential", "examples": ["Use this link to reset your password"], }, ), ), "sender_identity_mismatch": Noul( instructions={ "question": "Does the claimed sender identity conflict with its domain?", "compare": [ "`ticket.sender.display_name`", "`ticket.sender.email`", ], "focus": "Compare the named organization with the email domain.", }, criteria=NoulCriteria( true={ "what": "Claims an organization unrelated to the email domain", "examples": ["Acme Payroll sent from claim-bonus.example"], }, false={ "what": "The identity and domain agree or make no conflicting claim", "examples": ["Acme Payroll sent from acme.example"], }, ), ), "unexpected_reward": Noul( instructions={ "question": "Does the message announce an unexpected reward?", "inspect": "`ticket.message`", "focus": "Look for an unsolicited prize, payment, or reward claim.", }, criteria=NoulCriteria( true={ "what": "Announces an unrequested prize, payment, or reward", "examples": ["You were selected for a $1,000 bonus"], }, false={ "what": "Contains no reward claim or discusses an expected payment", "not_for": "A customer asking about a known refund or payroll deposit", "examples": ["When will my approved refund arrive?"], }, ), ), "refund_requested": Noul( instructions={ "question": "Does the customer explicitly request a refund or credit?", "inspect": "`ticket.message`", "focus": "Require a requested remedy, not a billing complaint alone.", }, criteria=NoulCriteria( true={ "what": "Directly asks for money back or an account credit", "examples": ["Please refund the duplicate charge"], }, false={ "what": "Does not ask for a refund or credit", "not_for": "A complaint or billing question without a requested remedy", "examples": ["Why was I charged twice?"], }, ), ), "mentions_open_order": Noul( instructions={ "question": "Does the message refer to a supplied open order?", "compare": [ "`ticket.message`", "`customer.open_orders`", ], "focus": "Match an order id or other identifying details.", }, criteria=NoulCriteria( true={ "what": "Refers to an open order by id or identifying details", "examples": ["Where is order A-104?"], }, false={ "what": "Does not identify any supplied open order", "not_for": "A generic order question with no matching details", "examples": ["How long does shipping usually take?"], }, ), ), "frustration": Score( instructions={ "question": "How frustrated does the customer appear?", "inspect": "`ticket.message`", "focus": "Judge expressed frustration, not issue severity.", }, criteria=[ { "what": "Calm and matter-of-fact", "signals": ["Neutral wording", "No complaint about the experience"], }, { "what": "Frustrated but civil", "signals": ["Expresses annoyance", "Remains constructive"], }, { "what": "Very angry or threatening to leave", "signals": ["Hostile language", "Threatens cancellation or churn"], }, ], ), } with TypeSafeClient() as client: response = client.system_one( state=state, questions=questions, ) # Compose independent spam signals with weights controlled by code. answers = response.answers spam_risk = ( 0.45 * answers["requests_credentials"].noul + 0.30 * answers["sender_identity_mismatch"].noul + 0.25 * answers["unexpected_reward"].noul ) # Escalate uncertain judgments instead of guessing. spam_is_uncertain = 0.4 < spam_risk < 0.6 if spam_is_uncertain or answers["topic"].confidence < 0.75: return route_to_human_review(ticket) if spam_risk >= 0.6: return quarantine_as_spam(ticket) # Let code decide which speculative answers matter on this path. if answers["topic"].choice == "billing": return route_to_billing( ticket, refund_requested=answers["refund_requested"].noul >= 0.7, ) if answers["topic"].choice == "orders": return route_to_orders( ticket, mentions_open_order=answers["mentions_open_order"].noul >= 0.7, ) priority = ( "high" if answers["frustration"].confidence >= 0.7 and answers["frustration"].score >= 1.5 else "normal" ) return route_to_account_support(ticket, priority=priority) ``` Contracts visible in that example, worth memorizing: - Imports come from `typesafe_sdk`: `Choice`, `Noul`, `NoulCriteria`, `Score`, `TypeSafeClient`. - `TypeSafeClient()` is a context manager; the call is `client.system_one(state=..., questions=...)`. - `questions` is a dict keyed by your own names; answers come back under the same keys via `response.answers[...]`. - Value accessors per type: `.noul` (float 0–1), `.choice` (the option key), `.score` (float), and `.confidence` on Choice and Score. - `Noul` criteria use `NoulCriteria(true=..., false=...)`; `Choice` criteria are a dict keyed by option name; `Score` criteria are an **ordered list** of level descriptions (list order is level order, lowest first; the frustration example's three entries run calm → frustrated → very angry — confirmed by [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md)). Per SDK v0.6.0, `Score.criteria` is an ordered sequence, not an int-keyed dict. - Structured `instructions` fields used in the source: `question`, `focus`, `inspect`, `compare`. Structured criteria fields: `what`, `not_for`, `examples`, `signals`. ## Gotchas - **Speculative answers cost nothing extra in latency.** The example asks `refund_requested` and `mentions_open_order` even though only one branch will use them — that is the intended pattern, not waste. - **Two different uncertainty gates.** `spam_is_uncertain` thresholds a *derived* score band (`0.4 < spam_risk < 0.6`), while `answers["topic"].confidence < 0.75` thresholds the model's own confidence. Noul answers do not carry `confidence`; see [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md). - **`not_for` is doing real work.** Contrastive criteria (what belongs here vs. the neighboring option) are what make a Choice boundary crisp. - **Backticks matter.** When pointing a question at a nested path, the docs explicitly require the backtick characters around the path inside the question text. - **Do not let a broad question hide a compound judgment.** If you cannot name exactly one property the question tests, it is not atomic yet. ## Related - [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md) — what the model is - [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) — building the input - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — Choice, Score, Noul - [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) — structured instructions, options, levels, criteria - [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) — thresholds and escalation - [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) — asking many questions at once - [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) — combining answers - [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) — risk-matched gates - [Cookbook: Parallel questions](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md) — parallel questions in practice - [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) — client and `system_one()` signature ## Sources - raw/docs/concepts__how-to-build-with-system-one.md (https://docs.typesafe.ai/concepts/how-to-build-with-system-one) --- title: "Jev 1.13 jaggedness: known failure modes" type: concept tags: [jaggedness, failure-modes, jev-1-13, limitations, reliability] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/model-jaggedness__jev-1.13.md - raw/docs/primitives__choice.md - raw/docs/primitives__noul.md jev_version: "jev-1.13.0" sdk_python: "0.6.0" summary: "Nine documented failure modes of jev-1.13 — literal reading, math, dates, indirection, big states, adversarial text, contradictions, invariants, generation — with the mitigation for each." --- # Jev 1.13 jaggedness: known failure modes > **TL;DR** `jev-1.13` is fast, calibrated and good at common-sense judgment, but it reads instructions literally, is not a calculator, cannot order dates, loses accuracy on indirection and on large irrelevant states, is not hardened against adversarial text, gets confused by criteria that contradict the instruction, does not honour structural invariants across separate questions, and is not trained to generate text. Keep arithmetic, dates, counting and text generation in your code. **Applies to `jev-1.13`. Last reviewed 2026-09-17** (per raw/docs/model-jaggedness__jev-1.13.md). ## What "jaggedness" means here `jev-1.13` does the best on [System One](https://jevwiki.ai/raw/wiki/concepts/system-one.md) tasks. It may struggle with tasks that require additional levels of indirection. It can be quite literal in its understanding. It struggles with tasks that require numeric precision. Upstream states that many of these edges will be fixed in later versions. ## The nine failure modes | # | Failure mode | Do this instead | |---|---|---| | 1 | Literal reading | Write the exact condition, criteria for each available options | | 2 | Math and Numbers | Keep the arithmetic in code | | 3 | Date and time comparison | Extract components; compare in code | | 4 | Indirection | Reduce hops; point to the relevant state | | 5 | Large state full of irrelevant detail | Filter first; send only what the question needs | | 6 | Adversarial content | Write precise prompts, and test edge cases before deploying | | 7 | Contradictory instructions and criteria | Align the criteria and instruction | | 8 | Common-sense structural invariants | Ask each decision one way; enforce identities in code | | 9 | Generation | Use a generative model | (Table reproduced from the source; the "do this instead" column is upstream's wording verbatim.) ## 1. Literal reading `jev-1.13` answers the question you wrote, not the one you meant. Scoping words, negations, and implied conditions are read at face value. A question will be answered based on the words written in the instruction, whereas a person might have read the intent behind the instructions. **Instead:** state the exact condition in the `instructions`. Be specific. Put boundary cases in the criteria. **When you look at a wrong answer and find yourself explaining what you really meant, that explanation is the missing half of the instruction.** Where interpretation is unavoidable, split it into two literal questions and combine them in code. See [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) for worked before/after rewrites. ## 2. Math and numbers Jev is not a calculator. Implement any mathematical logic in code. Jev performs better on semantic questions than mathematical ones. ### Counting `jev-1.13` does not count reliably — characters in a word, occurrences of a term in a passage, items in a long list. The model recognizes the shape of an answer rather than tallying, and **the error grows with the size of the thing being counted**. Before asking a counting question, ask why the count needs a model at all. If the unit is something a regular expression or a parser can find, the count belongs in code. **Instead:** count in code. Iterate over the candidates, ask one question for each, then add up the answers yourself. ```python from typesafe_sdk import Noul, TypeSafeClient client = TypeSafeClient(model="jev-1.13") YES = 0.5 # up to you on what you want the threshold to be, depends on your usecase. items = ["typesafe", "apple", "california", "banana", "likes", "calibration", "orange", "vertex"] result = client.system_one( {"items": items}, { f"item_{i}": Noul(instructions=f"Is `items[{i}]` the name of a fruit?") for i in range(len(items)) }, ) count = sum(result.nouls[f"item_{i}"].noul > YES for i in range(len(items))) ``` Note: this upstream snippet reads `result.nouls[...]`, while every other Python sample in the docs reads `response.answers[...]`. Both spellings appear in the sources; see *Contradictions* below and [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md). ### Numeric representations `jev-1.13` performs better on semantic representations than numeric. Questions about colors using hex values underperform compared to those using English names; given RGB triples or hex values it cannot reliably judge whether two values are near each other. Similarly, questions about high-level programming languages perform better than questions about low-level assembly or binary-encoded instructions. **Instead:** do the conversion in code and pass in either the computed number or a named bucket. Keep the model for the part that is genuinely a judgment, such as whether a color reads as a warning. ### Math using Score Do **not** use score outputs (expectations and probability) to compute the exact magnitude of a number between two levels of a criterion. You can use the expectation to check if it passes a particular threshold, but `jev-1.13`'s score levels are weak in numerical calibration: it will not be able to help you reconstruct the exact number by interpolating between the nearest two levels. See [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md). ## 3. Date and time comparison `jev-1.13` reads dates as text, not as ordered quantities. Asking which of two dates comes first, how far apart they are, or whether one falls inside a window is unreliable. It gets worse with mixed formats, relative references, and domain boundaries such as quarters, settlement windows, and accrual periods. **Instead:** split the work. Extraction is a judgment, so give it to the model; arithmetic is not, so keep it in code. Every part of a date is a small closed set: twelve months, thirty-one possible days, a bounded range of years. That turns extraction into a [Choice](https://jevwiki.ai/raw/wiki/concepts/choice.md) over enumerated options rather than free-form parsing, and it gives you somewhere to put an explicit "not stated" option so a missing part is reported rather than guessed. Code assembles the parts into a real date and owns everything after that: ordering, duration, offset, and weekday. [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md) has the worked version, including relative dates and confidence gating. ## 4. Indirection Instructions carrying double negatives or complex indirection are answered less reliably. A question about a property of a property, or one that requires multiple hops of reasoning, costs accuracy. **Instead:** write your instructions as directly as possible. When possible, identify the relevant parts of state by name — the backticked dot-and-index paths shown in [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md). ## 5. Large state full of irrelevant detail Accuracy falls as the state grows with content unrelated to the decision. Unrelated detail acts as a distractor, and a large state makes it harder to tell which part of the input produced a wrong answer. **Instead:** retrieve and filter in code first, and send only the fields the question needs. When it's not possible to filter in state, use a [Noul](https://jevwiki.ai/raw/wiki/concepts/noul.md) to filter for relevance — [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md) has a worked example. `jev-1.13` has a bounded context window; see [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) for the exact token limits. ## 6. Adversarial content State is data, and `jev-1.13` does not treat it as hostile by default. Content written to adversarially steer the model — an injected instruction, a deliberately misleading framing, or text that argues for its own classification — can move the answer. TypeSafe says it expects to improve on this in the future. **Instead:** be explicit in the criteria. Test your integration thoroughly before deploying it to many users. See [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md). ## 7. Contradictory instructions and criteria When the `instructions` and the `criteria` ask for different things, `jev-1.13` might get confused. The best performance comes from clear phrasing. For example, **a Noul where `true` maps to no and `false` maps to yes will perform worse.** Aim for instructions which are easy for the average person to read and understand. **Instead:** treat the criteria as an extension of the instruction. Align the two using clear and precise language. ## 8. Common-sense structural invariants `jev-1.13` is extremely consistent — expect quantitatively similar outputs for semantically similar inputs. However, many structural invariants one might imagine to hold are simply not guaranteed by the model. "Is the customer asking for a refund?", asked as a Noul and as a yes/no Choice on the ticket *"I'm not happy with the fit. What are my options here?"*: | Noul `noul` | Choice `yes` | Choice `no` | Choice `confidence` | |---|---|---|---| | 0.22 | 0.01 | 0.99 | 0.97 | The comparable numbers are `noul` and `probabilities["yes"]`, and it is not obvious how to interpret either the Choice output and confidence for the Noul question or vice versa. The same question and its negation, "Is the customer asking for something other than a refund?", as two Nouls on the ticket *"I was charged twice for the same order. Can someone look into this?"*: | `refund` | `not_refund` | Sum | |---|---|---| | 0.72 | 0.47 | 1.19 | There are many reasons that `P(noul)` and `1 - P(not noul)` may not be directly comparable. **Instead:** don't rely on expected structural invariance, and word questions to mean directly what you want. Don't carry a threshold tuned on a Noul over to a Choice, and don't hold the model to arithmetic identities between separate questions. A Choice over options and one Noul per option answer different questions: **the Choice is relative, settling *which* option, while each Noul is absolute and can be low for all of them.** [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md) uses both on the same shortlist — the Choice to pick a skill and the Nouls to decide whether to suggest one at all. ## 9. Generation `jev-1.13` is not trained to generate text. You can force it to by chaining choices, but this will not work well and will be very slow. For data extraction, it is better to extract possible options using regex or a generative model and let `jev-1.13` pick the correct extraction. **Instead:** when the answer space is bounded, turn extraction into a [Choice](https://jevwiki.ai/raw/wiki/concepts/choice.md) over the options rather than asking for the value itself. If you really need to generate text, use a different model. ## Checklist: avoid the following Reproduced from the source's closing reminder: - Asking the model something code can compute exactly. - Hiding several judgments inside one question. - System Two tasks: more layers of indirections. - Giving it more context in `state` than the question needs. Jev suffers from context rot, so unrelated material in the `state` costs you accuracy. TypeSafe invites reports of new failure modes on its Discord (https://discord.com/invite/WUujKYBp8s). ## Contradictions noticed between sources - **`result.nouls[...]` vs `response.answers[...]`.** The counting snippet on the jaggedness page reads answers through `result.nouls[...]`; every Python sample in raw/docs/primitives.md, raw/docs/primitives__choice.md and raw/docs/primitives__score.md reads `response.answers[...]`. Treat `answers` as the documented accessor and check [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md) before relying on `nouls`. - **Positional `system_one` arguments.** The same snippet calls `client.system_one({...}, {...})` positionally and sets the model on the client (`TypeSafeClient(model="jev-1.13")`), whereas other samples use `client.system_one(state=..., questions=...)`. Both appear in the sources. ## Related - [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) — how to write around modes 1, 4 and 7 - [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) — how to avoid modes 8 and 9 by picking the right type - [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) — testing edge cases before deploying - [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md), [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) — the primitives referenced above - [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) — filtering the state before you send it - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — context window and model aliases - [Jev (model)](https://jevwiki.ai/raw/wiki/entities/jev.md) — the model itself - [Cookbook: Date extraction](https://jevwiki.ai/raw/wiki/cookbooks/date-extraction.md), [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md), [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md) ## Sources - raw/docs/model-jaggedness__jev-1.13.md (https://docs.typesafe.ai/model-jaggedness/jev-1.13) - raw/docs/primitives__choice.md (https://docs.typesafe.ai/primitives/choice) - raw/docs/primitives__noul.md (https://docs.typesafe.ai/primitives/noul) --- title: "AI primer: why calibrated decision models" type: concept tags: [rlcd, rlhf, rlvr, calibration, training] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/introduction__machine-learning-primer.md - raw/docs/models.md jev_version: "jev-1.13.0" summary: "Why TypeSafe post-trains with RLCD for calibrated decisions instead of RLHF/RLVR for generated text." --- # AI primer: why calibrated decision models > **TL;DR** RLHF optimizes for human preference, RLVR for verifiable rewards; TypeSafe adds a third path, **RLCD** (Reinforcement Learning for Calibrated Decisions), which returns decisions and probabilities instead of text. Calibration means that across many predictions, outcomes given probability `0.2` occur about 20% of the time — a property of groups, never a guarantee about a single answer. ## What it is Most AI products are built around a conversation between a model and a person. TypeSafe starts from a different bet: **large-scale automation will be dominated by AI-to-AI and AI-to-software interactions**, so the machine interface matters more than the chat interface. > **Machine Native Intelligence** (TypeSafe's term): AI with software-like properties such as structure, reliability, observability, testability, speed, consistency, and low cost. ### Building prod, not God TypeSafe is not trying to build a model that does everything. It is designed for production systems where code needs a narrow decision it can inspect and act on. TypeSafe's stated expectation: large-scale AI automation will be **closer to 99% machine-to-machine interactions and 1% human interaction**. That shifts the design target from responses that feel good to read toward outputs that behave predictably inside software. (See [Manifesto: Composable AI — Build Prod, Not God](https://jevwiki.ai/raw/wiki/entities/manifesto.md).) ## How it works (mechanism) ### Three post-training approaches Pretrained language models have been adapted in two major ways; TypeSafe adds a third. RLHF and RLVR are given for context — TypeSafe's training path is RLCD. | Approach | Full name | What it produced / optimizes for | |---|---|---| | **RLHF** | Reinforcement learning from human feedback | Turned pretrained models into chatbots. Trains models to produce responses people prefer. | | **RLVR** | Reinforcement learning with verifiable rewards | Created reasoning models that are strong at tasks such as mathematics, but slower and more expensive. | | **RLCD** | Reinforcement learning for calibrated decisions | Trains TypeSafe to return decisions and calibrated probabilities instead of generated text. | RLHF was used to train InstructGPT and ChatGPT and was co-invented by **Diogo Almeida**, cofounder of TypeSafe. (See [Founders and team](https://jevwiki.ai/raw/wiki/entities/team.md).) ### RLCD and calibrated decisions RLCD optimizes for a different output contract: - The model does not generate text. - It returns decisions and probabilities. - Higher probability should correspond to a greater chance that the answer is correct. Calibration makes uncertainty usable by software. Across many predictions from a well-calibrated model: - Outcomes assigned a probability of `0.2` should occur about 20% of the time. - Outcomes assigned a probability of `0.8` should occur about 80% of the time. - Outcomes assigned a probability of `1.0` should occur 100% of the time. **These rates describe groups of predictions, not a guarantee about any single answer.** This is the single most important caveat on the page for anyone writing code against Jev: you cannot audit calibration one request at a time. See [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) for deciding when software should act or escalate. ### The problems with RLHF RLHF teaches a model to say things that people prefer. That objective works well for chatbots, but it can also reward **sycophancy** and **confident-sounding hallucinations**. Preference optimization also causes **mode dropping**: the model learns to favor a particular style, such as instruction following, while reducing the probability of other possible outputs. Mode dropping is a milder version of **mode collapse** — the classic generative-adversarial-network failure mode where a generator learns to produce the same kind of output repeatedly because that output continues to fool the discriminator. > **Warning from the docs:** an output can be compelling to a person without being reliable enough for unattended automation. Human preference and machine trustworthiness are different optimization targets. RLHF remains a good fit for conversational models. TypeSafe's position is that production automation needs a different training objective — one centered on constrained decisions and calibrated uncertainty. ## Why it matters for code - **Probabilities are features, not decoration.** Because they are trained to be calibrated, you can threshold, weight, and sum them; you can also feed them into a downstream classical ML model. See [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) and [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md). - **Uncertainty is a control signal.** A model that can say "I don't know" lets code split into act / confirm / escalate paths. See [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md). - **Validate calibration on your own data in aggregate.** Bucket answers by reported probability and measure the hit rate per bucket; a single wrong high-probability answer is not evidence of miscalibration. (inferred: the page states the group property but does not prescribe a validation procedure.) - **RLCD is the reason Jev is not customizable per account.** Jev is not fine-tuned or LoRA-adapted with customer data; the same weights serve every account, and you shape answers through `state`, `instructions`, and `criteria`. See [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md). ## Gotchas - "Calibrated" is not "accurate". A model can be perfectly calibrated and still be wrong on any given item; calibration says the *reported* confidence matches the *observed* frequency. - Probability `1.0` in the docs' framing means 100% of the time across the group — do not read a single `1.0` as a proof. - Nothing on this page claims Jev is smarter than an RLVR reasoning model; the claim is that it is trained for a different output contract. Intelligence claims live in [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md) and [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md). ## Related - [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md) — the model class this training produces - [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) — how calibration surfaces as a field you branch on - [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) — designing workflows around calibrated answers - [Manifesto: Composable AI — Build Prod, Not God](https://jevwiki.ai/raw/wiki/entities/manifesto.md) — "Composable AI — Build Prod, Not God" - [Founders and team](https://jevwiki.ai/raw/wiki/entities/team.md) — Diogo Almeida and the founders - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — why Jev is not fine-tuned per customer ## Sources - raw/docs/introduction__machine-learning-primer.md (https://docs.typesafe.ai/introduction/machine-learning-primer) - raw/docs/models.md (https://docs.typesafe.ai/models) — for "Jev is not fine-tuned or LoRA-adapted with customer data" --- title: "Noul (yes/no) questions" type: concept tags: [noul, primitives, probability, yes-no, thresholds] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/primitives__noul.md - raw/docs/api.md - raw/docs/primitives.md - raw/docs/model-jaggedness__jev-1.13.md jev_version: "jev-1.13.0" sdk_python: "0.6.0" summary: "Noul asks one yes/no question and returns a single number, the probability that the answer is yes; criteria are optional true/false clarifications." --- # Noul (yes/no) questions > **TL;DR** `{"type": "noul", "instructions": ""}`, with an optional `criteria: {"true": "...", "false": "..."}`. The answer is `{"type": "noul", "noul": <0..1>}` — the probability that the answer is **yes**. There is no `confidence` field on a Noul answer. Threshold `noul` in your code when you need a boolean. ## When to use / when not to use Use a Noul when the answer is yes or no: does this message ask for a refund, does this resume mention distributed systems, does this comment contain personal data. - If the answer is one of several options → [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md). - If it's a position on a spectrum → [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md). - Comparison of all three: [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md). Example questions from raw/docs/primitives__noul.md: ``` "Is the customer requesting a refund?" "Does this resume mention experience with distributed systems?" "Does the message contain personally identifiable information?" "Does the room have a minifridge?" ``` ## Probability-that-yes semantics A Noul answer is a single number, `noul`, **the probability that the answer is yes**. It ranges from 0 to 1. - Near 1 → a strong yes. - Near 0 → a strong no. - Near 0.5 → the model gives yes and no similar probability. Phrase the instruction so that a high probability means "yes", so the returned answer is unambiguous in its meaning. Most often you will threshold `noul` into a boolean when your code needs a hard decision. ### 0.5 is not "medium" Noul does not return a separate confidence value, and 0.5 does **not** mean a medium amount of the thing you asked about. For "Is the candidate strong in Python?", 0.5 means the model splits its probability between yes and no — not that the candidate has medium skill. Define what "strong" means, or use a [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) with defined levels (no experience, some familiarity, daily use, deep expertise). An unclear definition makes the probability hard to interpret. If what you want is a measurement rather than a decision, that is a Score question, not a Noul. See [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) for how Choice and Score confidence differs from a Noul probability. ## Request contract | Field | Required | Type | Description | |---|---|---|---| | `type` | Yes | `"noul"` | Must be `"noul"`. | | `instructions` | Yes | `string \| object \| array` | The yes/no question or statement to evaluate. | | `criteria` | No | `object` with `true` / `false` | Optional `{ true, false }` descriptions clarifying what a yes and a no mean. | Per raw/docs/api.md, `criteria.true` is "What a yes (value near 1) means" and `criteria.false` is "What a no (value near 0) means". Both may be a string, an object, an array, or `null` — see [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md). In the JavaScript SDK both parameters are optional: `noul(instructions?, criteria?)`, with `instructions` defaulting to `null` ([JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md)). ### Example request — one Noul with criteria, one without ```json { "state": "I have asked three times now. Can I please just talk to a real person?", "model": "jev-latest", "questions": { "is_human_escalation": { "type": "noul", "instructions": "Is the customer asking for a human agent?" }, "is_repeat_contact": { "type": "noul", "instructions": "Has the customer contacted support about this before?", "criteria": { "true": "Mentions a prior attempt, ticket, or that they have asked before", "false": "No sign of any previous contact" } } } } ``` ### Response ```json { "model": "jev-latest", "answers": { "is_human_escalation": { "type": "noul", "noul": 0.99 }, "is_repeat_contact": { "type": "noul", "noul": 0.93 } }, "usage": { "input_tokens": 360, "output_tokens": 39 } } ``` A Noul answer carries only `type` and `noul`. There is no `probabilities` map and no `confidence`. ### Python SDK ```python from typesafe_sdk import Noul, TypeSafeClient with TypeSafeClient() as client: response = client.system_one( state="I have asked three times now. Can I please just talk to a real person?", questions={ "is_human_escalation": Noul( instructions="Is the customer asking for a human agent?", ), "is_repeat_contact": Noul( instructions="Has the customer contacted support about this before?", criteria={ "true": "Mentions a prior attempt, ticket, or that they have asked before", "false": "No sign of any previous contact", }, ), }, ) print(response.answers["is_human_escalation"].noul) print(response.answers["is_repeat_contact"].noul) ``` (The `Noul(instructions=..., criteria={...})` construction and reading `.noul` off `response.answers[id]` are both attested in raw/docs/primitives.md and raw/docs/primitives__noul.md; this combined snippet is assembled from those two shapes — **(inferred)** only in that the upstream Noul page shows the request as JSON rather than Python.) ## Writing a Noul question - **A Noul evaluates one yes/no question.** It is defined by its `instructions`. - **Phrasing.** Beyond a plain question, you can phrase the instruction as a statement for the model to evaluate for truthfulness: for "the customer is requesting a refund", a value near 1 means the statement is true. Try both phrasings with your own data to see what works best. - **Optional `criteria`.** The instruction is enough for most Noul questions, but when the boundary between yes and no is subtle, pass `criteria` with `true` and `false` descriptions to pin down what each outcome means. Try your Noul prompts with and without criteria to see which works better in your use case. - **Keep `true` meaning yes.** Per [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md), a Noul where `true` maps to "no" and `false` maps to "yes" performs worse. Treat the criteria as an extension of the instruction and align the two. Structured `true`/`false` objects (a definition plus examples on each side) are shown in [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) and in [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md). ## Using the number in code ```python YES = 0.5 # up to you on what you want the threshold to be, depends on your usecase. ``` The threshold is yours to pick and belongs in your code, not in the prompt. Two cautions from [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md): - **Don't carry a threshold tuned on a Noul over to a Choice.** A Choice over options is *relative* (which option wins), while each Noul is *absolute* and can be low for all of them. - **Don't expect arithmetic identities between separate questions.** On the ticket "I was charged twice for the same order. Can someone look into this?", the question and its negation asked as two Nouls returned: | `refund` | `not_refund` | Sum | |---|---|---| | 0.72 | 0.47 | 1.19 | `P(noul)` and `1 - P(not noul)` are not directly comparable. For a counting use case, ask one Noul per item and add up the thresholded answers in code rather than asking for a count — the worked snippet is in [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md). ## Gotchas - No `confidence` field exists on a Noul answer; a value near 0.5 is the only "uncertain" signal you get. - 0.5 means split probability, not a medium quantity. - Vague predicates ("strong", "important", "recent") make the number uninterpretable. State the exact condition ("Does the resume state that the candidate has used Python at work?"). - A Noul and a yes/no Choice on the same text can disagree sharply. Example from [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) on "I'm not happy with the fit. What are my options here?": Noul `noul` 0.22 versus Choice `probabilities["yes"]` 0.01 with `confidence` 0.97. ## Related - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — the three types and how to batch them - [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) — the other two primitives - [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) — decision table - [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) — phrasing and negation pitfalls - [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) — structured `true`/`false` criteria - [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) — why Noul has no separate confidence - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — wire contract - [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md) — Noul as a relevance filter ## Sources - raw/docs/primitives__noul.md (https://docs.typesafe.ai/primitives/noul) - raw/docs/api.md (https://docs.typesafe.ai/api) - raw/docs/primitives.md (https://docs.typesafe.ai/primitives) - raw/docs/model-jaggedness__jev-1.13.md (https://docs.typesafe.ai/model-jaggedness/jev-1.13) --- title: "Primitives: Choice, Score, Noul" type: concept tags: [primitives, questions, answers, choice, score, noul] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/primitives.md - raw/docs/api.md jev_version: "jev-1.13.0" sdk_python: "0.6.0" summary: "The three Jev question types (Choice, Score, Noul), the typed answers they return, how to pick one, and how to batch many questions in one request." --- # Primitives: Choice, Score, Noul > **TL;DR** A Jev request is a `state` plus a map of `questions`, each with an id you choose, a `type` (`choice`, `score`, `noul`), `instructions`, and usually `criteria`. Each question returns a typed answer under the same id: `choice`/`probabilities`/`confidence`, `score`/`legend`/`probabilities`/`confidence`, or a single `noul` probability. Ask many questions in one request — they run in parallel and cost only their own tokens. ## What primitives are Primitives are the small, typed building blocks you compose in code. They come in pairs: a **question** defines one judgment for a [System One model](https://jevwiki.ai/raw/wiki/concepts/system-one.md) to make about a [state](https://jevwiki.ai/raw/wiki/concepts/state.md), and its **answer** is the typed value that comes back. You compose the answers in your code to make decisions. | Type | What it answers | Returns | |---|---|---| | [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md) | Which of these options? | `choice`, `probabilities`, `confidence` | | [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) | Which level? | `score`, `legend`, `probabilities`, `confidence` | | [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) | Is this true? | `noul` (0 to 1) | You can ask one question or send several together. Every question in a request sees the same state, is evaluated independently, and returns a typed answer under the ID you chose. ## One snap judgment per question System One models are built for fast, focused judgments. Ask for a judgment a knowledgeable person makes in a second given the right context. "Does this message convey urgency?" is a good question. "Analyze this message and determine the best course of action" is not — that needs slow reasoning, and it is a signal to break the task into small questions and compose the answers in code. If the judgment depends on several independent factors, ask about each factor separately and combine the answers with your own logic. Instead of "rate this startup pitch", ask about market size, technical feasibility, and differentiation, then weight them in code. When priorities shift, change the value of the weights rather than rewriting a prompt. ## How a question is defined Every question has an ID, a `type`, and `instructions`. Choice and Score also take `criteria`; Noul accepts `criteria` as an optional clarification of what yes and no mean. - **ID** — the key you pick, such as `refund_requested`. It identifies the answer in the response. Per [raw/docs/api.md](https://docs.typesafe.ai/api), "The key is not sent to the underlying model and is not used in inference." Write the complete question in `instructions` even when the ID seems self-explanatory. - **`type`** — one of `choice`, `score`, or `noul`. - **`instructions`** — the question you are asking about the state. This is where your evaluation logic goes. Write it as a clear, specific question, or as a statement for the model to judge. - **`criteria`** — the possible answers: a map of options for a Choice, an ordered list of levels for a Score, and an optional `{true, false}` description for a Noul. ```python from typesafe_sdk import Noul questions = { "refund_requested": Noul( instructions="Does the customer request a refund?", ), } ``` ## Choosing a type - **Choice** fits when the answer is one of a known set of options with no order between them: routing a ticket to a department, classifying a document type, detecting a programming language. Give the full list, and add an `other` or `none of the above` option when the list might not cover every input. - **Score** fits when the answer falls on a spectrum and you can describe what each point on that spectrum means: bug severity, customer frustration, skill level. - **Noul** fits a clean yes/no question where the probability itself is the useful signal. Use Noul for a yes/no judgment and Score to measure a position on a spectrum. A Noul value of 0.5 means the model gives yes and no equal probability; it does **not** mean "medium". For skill level, use a Score with defined levels (no experience, some familiarity, daily use, deep expertise); for a yes/no decision, define the condition clearly ("Does the resume state that the candidate has used Python at work?"). If two types both seem to fit, prefer the one whose answer your code can act on directly. See [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) for the full decision table. ## What comes back | Type | Answer fields | How to read it | |---|---|---| | Choice | `choice`, `probabilities`, `confidence` | `choice` is the selected option. `probabilities` is the distribution across every option. `confidence` summarizes how peaked that distribution is. | | Score | `score`, `legend`, `probabilities`, `confidence` | `score` is a position along your levels and can fall between two of them. `legend` repeats the levels by number. `probabilities` is the distribution across levels. | | Noul | `noul` | The probability that the answer is yes. Near 1 is a strong yes, near 0 a strong no, near 0.5 uncertain. Noul has no separate `confidence`. | Two properties make these composable: - **Every answer is constrained to the options you supplied.** The model returns a probability distribution over your options or levels, never a value outside them. Your code never has to recover a value from generated prose. - **Every answer is independent.** One question's answer is not hidden context for another. You can add or remove questions without changing the others' results. [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) explains how `confidence` is derived from `probabilities`. [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) has the exact wire types. ## Referencing specific fields of the state When a question is about one part of a structured state, name it in the `instructions` with a dot-and-index path to its key, **including the backticks**. ```json { "ticket": { "subject": "Duplicate charge", "messages": [ {"from": "customer", "text": "I was charged twice for order A-104. Please refund the duplicate."}, {"from": "support", "text": "We are checking the charges."} ] }, "order": { "id": "A-104", "charges": [ {"amount_usd": 49, "status": "captured"}, {"amount_usd": 49, "status": "captured"} ] }, "refund_policy": "Duplicate charges are eligible for a refund." } ``` ```python questions = { "refund_requested": { "type": "noul", "instructions": "Does `ticket.messages[0].text` request a refund?", }, "policy_supports_refund": { "type": "noul", "instructions": ( "Does `refund_policy` support the refund requested " "in `ticket.messages[0].text`, given `order.charges`?" ), }, } ``` ## Ask multiple questions together Send every question that uses the same state in one request; you can mix types freely. System One models evaluate every question in a request in parallel. Adding questions barely changes the response time and costs only the tokens for the extra questions, which are cheap. **Asking a question you might not need is close to free.** ```python from typesafe_sdk import Choice, Noul, Score, TypeSafeClient state = { "ticket_message": "My flight was cancelled. Can I get a refund?", "refund_policy": "Cancelled flights are eligible for a full refund.", } with TypeSafeClient() as client: response = client.system_one( state=state, questions={ "refund_requested": Noul( instructions="Does `ticket_message` request a refund?", ), "request_type": Choice( instructions="What is the main request in `ticket_message`?", criteria={ "refund": "The customer wants money returned.", "rebooking": "The customer wants a replacement flight.", "information": "The customer is asking for information only.", }, ), "frustration": Score( instructions="How frustrated does the customer appear in `ticket_message`?", criteria=[ "Calm and neutral.", "Concerned but civil.", "Very angry or using strong language.", ], ), }, ) print(response.answers["refund_requested"].noul) print(response.answers["request_type"].choice) print(response.answers["frustration"].score) ``` ### Speculative questions Ask every question your code might need, including ones whose answer only matters for some inputs, and let the code decide which answers to use — the [speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) pattern. The [parallel questions cookbook](https://jevwiki.ai/raw/wiki/cookbooks/parallel-questions.md) shows that batching 13 questions into one call is **11.5x cheaper and 9.6x faster** than 13 separate calls, with no change in the answers (that is the figure on the upstream primitives page; the cookbook itself prints 12.2x cheaper, 10.0x faster — different runs, same conclusion). The number of questions in one request is limited only by the request's token budget, which the state and the questions share. Per raw/docs/primitives.md the budget is "around 32,000 tokens, roughly 150,000 characters of English text" (see [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) for the authoritative limit). ### Splitting a complex judgment A judgment that depends on several things is best split into one question per thing, combined in code with weights for relative importance — the [composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) pattern. Worked example in [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md). ### When one question depends on another Questions in the same request are independent: one answer does not become context for another question. Make a second request only when your code genuinely cannot build it until it has the first answer — it needs the answer to fetch more data for the state, to decide what the state is made of, or to pick the next question's options. Two requests are the exception, not the rule. Real examples: [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md) (rank 182 skills, then fetch the full text of the top three and re-judge), [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md) (merge lines into blocks that did not exist before the first request), [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) (each Choice answer decides the next request's options). ## Gotchas - Question IDs are never seen by the model. Do not encode meaning in them. - Answers are independent — do not expect one question's phrasing to constrain another's answer, and do not expect arithmetic identities to hold between them (see [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md)). - Extra questions are cheap but not free: they still cost input and output tokens. - More state is not better. Unrelated material in the `state` costs accuracy. ## Related - [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) — decision table for picking a type - [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) — how to phrase `instructions` and `criteria` - [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md), [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) — full contract per type - [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) — JSON inside `instructions` and `criteria` - [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) — how to shape the input - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — the wire contract - [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) — where in your code to call Jev - [The typesafe-ai agent skill and Claude Code plugin](https://jevwiki.ai/raw/wiki/reference/agent-skill.md) — the skill that tells a coding agent to batch questions ## Sources - raw/docs/primitives.md (https://docs.typesafe.ai/primitives) - raw/docs/api.md (https://docs.typesafe.ai/api) --- title: "Score questions" type: concept tags: [score, primitives, levels, rubric, confidence] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/primitives__score.md - raw/docs/api.md - raw/docs/primitives.md jev_version: "jev-1.13.0" sdk_python: "0.6.0" summary: "Score rates a state against an ordered array of described levels and returns a probability-weighted position, the legend, per-level probabilities, and confidence." --- # Score questions > **TL;DR** `{"type": "score", "instructions": "...", "criteria": ["level 0 …", "level 1 …", …]}` — `criteria` is an **ordered array**, at least 2 levels and up to 10. The answer is `{"type": "score", "score": , "legend": {...}, "probabilities": {"0": …}, "confidence": 0..1}`. `score` is the probability-weighted mean of the level numbers, so different distributions can produce the same score — always read `probabilities` and `confidence` too. ## When to use / when not to use Use a Score when the answer is a position on a spectrum and you can describe what each point on that spectrum means: bug severity, customer frustration, report quality, skill level. - If the answer is one of a fixed set of unordered options → [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md). - If it's a clean yes/no → [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md). - If there is no in-between at all and the answer is one of a few discrete categories, use a Choice instead, or split the question into several Noul questions. - Decision table: [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md). Example Score questions from raw/docs/primitives__score.md: ``` "How severe is the bug being reported?" → 0: Cosmetic; no impact to functionality → 1: Broken or degraded feature, but workaround exists → 2: Blocking issue; no workaround exists "How formal is this outfit based on the description" → 0: gym clothes → 1: casual → 2: business casual → 3: formal → 4: black tie "How relevant is this candidate's experience to the job posting" → 0: completely unrelated → 1: adjacent field → 2: some direct experience → 3: deep, direct experience ``` ## Request contract Same three top-level fields as any other question type: `state`, `model`, `questions`. | Field | Type | Required | Description | |---|---|---|---| | `type` | `"score"` | yes | Always `"score"`. | | `instructions` | `string \| object \| array` | yes | What the model should rate. | | `criteria` | `array` | yes | An **ordered array** of level descriptions, from the low end of the scale to the high end. At least two levels, up to 10. | `instructions` and each level in `criteria` may be a string, an object, an array, or `null` (all are `EntryType`) — see [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md). ### Levels are an ordered sequence Each entry in `criteria` is a level: one point on the spectrum, described in words. **A level's number is its position in the array, starting at 0**, so a three-entry array gives levels 0, 1 and 2. The order of the array *is* the numbering. In SDK 0.6.0 `Score.criteria` is an ordered sequence, not an int-keyed dict. The model gets the descriptions and nothing else. Each level is judged on its own against the state — it does not see a level's number or its neighbours. The `score` in the response is a position on that spectrum: for a three-level scale it runs from 0 to 2, and it can land between two levels. ### Minimal request ```json { "state": "The export button crashes the settings page in Safari. It works in Chrome, but a few of our customers only use Safari.", "model": "jev-latest", "questions": { "bug_severity": { "type": "score", "instructions": "How severe is the reported issue?", "criteria": [ "Cosmetic; no impact to functionality", "Broken or degraded feature, but workaround exists", "Blocking issue; no workaround exists" ] } } } ``` ```python from typesafe_sdk import Score, TypeSafeClient with TypeSafeClient() as client: response = client.system_one( state="The export button crashes the settings page in Safari. It works in Chrome, but a few of our customers only use Safari.", questions={ "bug_severity": Score( instructions="How severe is the reported issue?", criteria=[ "Cosmetic; no impact to functionality", "Broken or degraded feature, but workaround exists", "Blocking issue; no workaround exists", ], ), }, ) print(response.answers["bug_severity"].score) ``` The question id (`bug_severity`) is not sent to the model; the answer comes back under the same id. In the JavaScript SDK the helper is `score(instructions, criteria)` with "At least two descriptions indexed by score from zero; entries may be `null`" — see [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md). ## Response contract | Field | Type | Description | |---|---|---| | `type` | `"score"` | Matches the question type. | | `score` | `number` | The position on the level number line, from 0 to the top level number. Each level number multiplied by its probability, added up. Can land between levels. | | `legend` | `map` | Each level number mapped back to its description. | | `probabilities` | `map` | The probability of each level, keyed by level number **as a string**. The values sum to 1. | | `confidence` | `number` | 0 to 1, computed from how `probabilities` is spread. A single peak means high confidence; probability spread over several levels means low confidence. | ```json { "model": "jev-latest", "answers": { "bug_severity": { "type": "score", "score": 1.3, "confidence": 0.54, "legend": { "0": "Cosmetic; no impact to functionality", "1": "Broken or degraded feature, but workaround exists", "2": "Blocking issue; no workaround exists" }, "probabilities": { "0": 0.0, "1": 0.7, "2": 0.3 } } }, "usage": { "input_tokens": 332, "output_tokens": 18 } } ``` `score` here is `0 × 0.0 + 1 × 0.70 + 2 × 0.30 = 1.30`. That matches the report: the export is broken, and switching to Chrome is a workaround for most customers but not for the ones who only use Safari. Confidence is 0.54 because the distribution is split. **SDK note:** using the Python SDK, `ScoreAnswer` has `score`, `confidence`, `probabilities`, and `legend` as typed fields, and it keys `probabilities` and `legend` by **integer** level rather than by string. See [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md). ## Reading a Score Same question and levels, different bug reports: | State | `score` | `confidence` | Level 0 | Level 1 | Level 2 | |---|---|---|---|---|---| | The export button is misaligned by a few pixels on the settings page. | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 | | The PDF export button does nothing when clicked. I can still export to CSV and convert it myself, but that takes ages. | 1.0 | 1.0 | 0.0 | 1.0 | 0.0 | | Export to PDF fails with a spinner that never finishes. Some of our team say CSV export still works for them, others say it fails too. | 1.12 | 0.81 | 0.0 | 0.88 | 0.12 | | The export button crashes the settings page in Safari. It works in Chrome, but a few of our customers only use Safari. | 1.3 | 0.54 | 0.0 | 0.7 | 0.3 | | Nobody on our team can log in since this morning. We get a 500 error on every attempt. | 2.0 | 1.0 | 0.0 | 0.0 | 1.0 | (Levels 0/1/2 columns are `probabilities`.) Key readings: - Confidence 1.0 means the returned distribution puts all its probability on one level. **This describes the model's answer, not a guarantee that the answer is correct.** - The score is a probability-weighted mean of the level numbers. More weight on level 2 raises the score. It does **not** measure "the fraction of customers without a workaround" or any other real-world quantity. - **Different distributions can produce the same score.** A score of 1.0 can mean all probability is on level 1, or half on each of levels 0 and 2. Read `probabilities` and `confidence` alongside the score to tell these apart. - A fractional score is a position. Use it to rank items, or round it to the nearest level when your code needs one outcome ([Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md) rounds to the nearest level to make a decision). - Low confidence on a Score usually means one of three things: the levels overlap for this state, the question is measuring more than one thing, or the state doesn't say enough to place it. See [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md). ## Writing good levels - **Describe situations, not degrees.** "Broken or degraded feature, but workaround exists" gives the model something to match the state against. "Moderately severe" doesn't. - **Numbers alone don't work.** Every level is evaluated separately; the model doesn't see a level's number or its neighbours, so "worse than the previous level" means nothing to it. On the misaligned-button report: ``` instructions: "Rate severity from 0 to 2, where 2 is worst" criteria: ["0", "1", "2"] → score 0.57, confidence 0.35, probabilities 0: 0.43, 1: 0.57, 2: 0.0 ``` The same report with the three descriptive levels scores 0.0 at confidence 1.0. - **Use as many levels as you can describe distinctly, up to 10.** Three is fine. Don't add levels you can't describe distinctly. - **One dimension per question.** A level that says "punctual and smart and experienced" measures three things, and an input high on one and low on another can't be placed: confidence drops and the score means less. Split into one Score per thing and combine in code. - **Give a rare extreme its own level.** A sentiment scale that ends at "very angry" can add "abusive or threatening"; without that level both messages may receive a score near the top and the score alone may not distinguish them. - **Test against your own data.** Two wordings of the same scale can behave differently on your data. Checking answers against known examples beats chasing higher confidence — higher confidence alone does not show that a description is better. ## Splitting a complex judgment into several Scores A judgment that depends on several things is best split into one Score per thing, then combined in code with weights for relative importance. The weights are yours: when the combined result doesn't match what your team would decide, change them in code and run again. Send all the Score questions in one request — they run in parallel. Request (the spinner ticket with more context): ```json { "state": "Export to PDF fails with a spinner that never finishes. Some of our team say CSV export still works for them, others say it fails too. This is the third time I'm writing in and honestly I'm done. Steps: open any report, click Export, choose PDF. Chrome 128 on macOS.", "model": "jev-latest", "questions": { "severity": { "type": "score", "instructions": "How severe is the reported issue?", "criteria": [ "Cosmetic; no impact to functionality", "Broken or degraded feature, but workaround exists", "Blocking issue; no workaround exists" ] }, "frustration": { "type": "score", "instructions": "How frustrated is the customer?", "criteria": [ "Calm, just stating facts", "Frustrated but civil", "Very angry, strong language or threatening to leave" ] }, "report_quality": { "type": "score", "instructions": "How much does the report give an engineer to work with?", "criteria": [ "No detail; just says something is broken", "Names the feature but no steps or environment", "Steps to reproduce or environment, but not both", "Steps to reproduce and environment" ] } } } ``` Response: ```json { "model": "jev-latest", "answers": { "severity": { "type": "score", "score": 1.24, "confidence": 0.63, "legend": { "0": "Cosmetic; no impact to functionality", "1": "Broken or degraded feature, but workaround exists", "2": "Blocking issue; no workaround exists" }, "probabilities": { "0": 0.0, "1": 0.76, "2": 0.24 } }, "frustration": { "type": "score", "score": 1.45, "confidence": 0.33, "legend": { "0": "Calm, just stating facts", "1": "Frustrated but civil", "2": "Very angry, strong language or threatening to leave" }, "probabilities": { "0": 0.0, "1": 0.55, "2": 0.45 } }, "report_quality": { "type": "score", "score": 3.0, "confidence": 1.0, "legend": { "0": "No detail; just says something is broken", "1": "Names the feature but no steps or environment", "2": "Steps to reproduce or environment, but not both", "3": "Steps to reproduce and environment" }, "probabilities": { "0": 0.0, "1": 0.0, "2": 0.0, "3": 1.0 } } }, "usage": { "input_tokens": 468, "output_tokens": 43 } } ``` - `severity` 1.24 at confidence 0.63 — the export is broken and some have a workaround. - `frustration` 1.45 at confidence 0.33 — the wording is civil, but "third time" and "I'm done" shift weight toward the top level (0.55 / 0.45). For this ticket the two levels overlap, which explains the low confidence. - `report_quality` 3.0 at confidence 1.0 — steps and browser version are both stated. ### Normalize before combining The three scales have different lengths: a four-level scale returns 0 to 3 and a three-level scale returns 0 to 2, so a top score on one is bigger than a top score on the other. **Divide each score by its top level number, `len(criteria) - 1`**, to put every score on 0 to 1. Then the weights mean what they say. ```python from typesafe_sdk import Score, TypeSafeClient TRIAGE_QUESTIONS = { "severity": Score( instructions="How severe is the reported issue?", criteria=[ "Cosmetic; no impact to functionality", "Broken or degraded feature, but workaround exists", "Blocking issue; no workaround exists", ], ), "frustration": Score( instructions="How frustrated is the customer?", criteria=[ "Calm, just stating facts", "Frustrated but civil", "Very angry, strong language or threatening to leave", ], ), "report_quality": Score( instructions="How much does the report give an engineer to work with?", criteria=[ "No detail; just says something is broken", "Names the feature but no steps or environment", "Steps to reproduce or environment, but not both", "Steps to reproduce and environment", ], ), } def normalized(answers, question_id: str) -> float: """Put a score on 0 to 1 by dividing by its top level number.""" top_level = len(TRIAGE_QUESTIONS[question_id].criteria) - 1 return answers[question_id].score / top_level def priority(ticket: str) -> float: with TypeSafeClient() as client: response = client.system_one( state=ticket, questions=TRIAGE_QUESTIONS, ) answers = response.answers severity = normalized(answers, "severity") frustration = normalized(answers, "frustration") report_quality = normalized(answers, "report_quality") # A detailed report helps an engineer investigate, so it raises priority a little. return 0.6 * severity + 0.3 * frustration + 0.1 * report_quality ``` For the response above the normalized scores are 0.62 (severity), 0.725 (frustration), and 1.0 (report quality), so the priority is `0.6 × 0.62 + 0.3 × 0.725 + 0.1 × 1.0 = 0.6895`, which rounds to `0.69`. This is the [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) pattern. ## Structured level descriptions Start with plain strings. When the model keeps scoring between two neighbouring levels on inputs you think are clear, give each level an object with a field for what the level covers and a field with a few example situations. **Use the same field names on every level** so the model can compare like with like. ```json { "state": "Export to PDF fails with a spinner that never finishes. Some of our team say CSV export still works for them, others say it fails too.", "model": "jev-latest", "questions": { "bug_severity": { "type": "score", "instructions": "How severe is the reported issue?", "criteria": [ { "what": "Cosmetic; no impact to functionality", "examples": ["typo in a label", "misaligned icon"] }, { "what": "Broken or degraded feature, but workaround exists", "examples": ["export fails in one browser but works in another"] }, { "what": "Blocking issue; no workaround exists", "examples": ["cannot log in", "data loss"] } ] } } } ``` The `legend` echoes the structured levels back: ```json { "model": "jev-latest", "answers": { "bug_severity": { "type": "score", "score": 1.06, "confidence": 0.91, "legend": { "0": { "what": "Cosmetic; no impact to functionality", "examples": [ "typo in a label", "misaligned icon" ] }, "1": { "what": "Broken or degraded feature, but workaround exists", "examples": [ "export fails in one browser but works in another" ] }, "2": { "what": "Blocking issue; no workaround exists", "examples": [ "cannot log in", "data loss" ] } }, "probabilities": { "0": 0.0, "1": 0.94, "2": 0.06 } } }, "usage": { "input_tokens": 379, "output_tokens": 18 } } ``` With plain strings this ticket scored 1.12 at confidence 0.81; with examples it scores 1.06 at 0.91. **Examples only help when they look like your real inputs.** The opening Safari report with three different sets of level objects: | Level description | `score` | `confidence` | |---|---|---| | plain string: no object with examples | 1.30 | 0.54 | | Added examples array with useful example: "export fails in one browser but works in another" | 1.07 | 0.90 | | Added examples array with example unrelated to browsers: "search fails, but browsing categories still works" | 1.28 | 0.57 | The matching example concentrates more probability on one level; the unrelated example changes the result only slightly compared with plain strings. **Higher confidence does not establish which answer is correct.** Choose examples with known expected levels, then test the revised descriptions on separate inputs before keeping them. ## Gotchas - `score` is a probability-weighted mean, not a measurement. Do not interpolate it back into a real-world quantity. Per [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md), `jev-1.13`'s score levels are weak in numerical calibration: use the expectation to check a threshold, not to reconstruct an exact number between two levels. - Levels below 2 or above 10 are outside the contract (minimum two is enforced by the API; ten is the documented maximum). - Scales of different lengths are not comparable until normalized by `len(criteria) - 1`. - The Python SDK keys `probabilities` and `legend` by `int`; the HTTP response keys them by `string`. Code that switches between the two must convert. ## Related - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — the three types and how to batch them - [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md) — the other two primitives - [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) — decision table - [Writing instructions and criteria that Jev reads correctly](https://jevwiki.ai/raw/wiki/guides/writing-instructions-and-criteria.md) — level-writing rules with before/after examples - [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md) — structured levels and instructions - [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) — what `confidence` means and how to gate on it - [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md) — weighting several Scores in code - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md), [Python SDK responses, answers, usage, models](https://jevwiki.ai/raw/wiki/reference/python-sdk-responses.md) — exact field types - [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md) — rounding a Score to the nearest level ## Sources - raw/docs/primitives__score.md (https://docs.typesafe.ai/primitives/score) - raw/docs/api.md (https://docs.typesafe.ai/api) - raw/docs/primitives.md (https://docs.typesafe.ai/primitives) --- title: "State: what you send Jev" type: concept tags: [state, input, context, limits, json] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/concepts__state.md - raw/docs/models.md jev_version: "jev-1.13.0" summary: "State is the content Jev evaluates: a string, JSON object, or array of text, shared by every question in one request." --- # State: what you send Jev > **TL;DR** `state` is the single input every question in a request is evaluated against. It may be a string, a JSON object, or an array of text values — nothing else; no images, audio, or video. Prefer an object with descriptive field names. Budget: 64k tokens for `state` + all questions, and 32k tokens for `state` + the single longest question. ## What it is **State** is the content you ask a System One model to evaluate — a support message, a passage of text, or the current state of your application. You pass it in the `state` field of an API request, alongside the questions you want answered. Each request evaluates **one state against one or more questions**. All questions see the same state and are evaluated independently. You can mix [Choice](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Score](https://jevwiki.ai/raw/wiki/concepts/score.md), and [Noul](https://jevwiki.ai/raw/wiki/concepts/noul.md) questions in one request. The docs' mental model: state is "the material you would present to a panel of experts before asking them to make a judgment." ## Supported shapes | Format | Useful for | Example | |---|---|---| | String | A message, article, or passage | `"My card was charged twice."` | | Object | Named fields, related records, or application state | `{"message": "My card was charged twice.", "order_id": "A-104"}` | | Array | A sequence of messages or records | `["Hi", "My customer number is TS1337.", "My card was charged twice."]` | The simplest state is a plain string: ```python theme={null} state = "My card was charged twice." ``` In Python, pass the corresponding string, dictionary, or list directly to `client.system_one(state=...)`. **Choose an object for most requests** so each part of the state has a descriptive name and its relationships remain clear. A string is suitable when the use case is simple and requires only one piece of text. ### A composite object is still one state ```json title="A support conversation as state" theme={null} { "ticket": { "subject": "Duplicate charge", "messages": [ {"from": "customer", "text": "I was charged twice for order A-104. Please refund the duplicate."}, {"from": "support", "text": "We are checking the charges."} ] }, "order": { "id": "A-104", "charges": [ {"amount_usd": 49, "status": "captured"}, {"amount_usd": 49, "status": "captured"} ] }, "refund_policy": "Duplicate charges are eligible for a refund." } ``` This object is one state, even though it contains a conversation, an order, and a policy. Put related information together when the decision requires comparing those parts. ## Limits and constraints | Constraint | Value | Source | |---|---|---| | Total context per request | 64k tokens (`state` plus **all** questions combined) | raw/docs/models.md | | Per-question budget | 32k tokens for `state` plus the **single longest** question | raw/docs/models.md | | Input types | Text only: string, JSON object, or array of text values. No image, audio, or video input. | raw/docs/models.md, raw/docs/concepts__state.md | | Language | English is the primary training language and where accuracy is best; other languages including CJK are accepted but not handled equally well | raw/docs/models.md | Jev ingests the `state` once and evaluates every question against it in parallel, which is why the two budgets differ: the 64k budget covers state plus every question, while the 32k budget applies to state plus only the longest question. Practical consequence: a large state leaves each individual question a smaller allowance, and packing many *short* questions into one request is cheap under the 32k rule but still consumes the 64k total. Pre-process non-text inputs (images, audio, video, binaries) into text or structured fields before sending them as `state`. ## Best practices - **Separate content from questions.** The state contains the content and supporting facts; [questions](https://jevwiki.ai/raw/wiki/concepts/primitives.md) define the judgments to make about that material. Keep the refund request and the policy in the state, then ask whether the customer requested a refund and whether the policy supports it. - **Send only relevant context.** Include only what the current questions need; this helps the model avoid distractions and context rot. See [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md). - **Use nested JSON and name things.** Descriptive keys let questions point at specific values. Reference a nested value from a question's `instructions` with a backticked dot-and-index path, e.g. `` `support.tickets[0].message` `` — include the backtick characters around each path inside the question text. - **Do not rely on model weights for facts you own.** Put current information from your own knowledge base into the state. - **Watch accuracy as the state grows.** See [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) for how accuracy shifts with state size. - **Pay attention to confidence on non-English content**; test on your own data before relying on Jev for a non-English workload. ## Gotchas - There is exactly **one** `state` per request. If you need two documents compared, put both inside one object — do not send two requests unless the decisions are genuinely independent. - Arrays are described as arrays "of text values" / "a sequence of messages or records". The conversation example in the docs nests objects inside an object; the array row's example is a flat list of strings. - All questions see the whole state. There is no per-question scoping mechanism other than pointing at a path inside `instructions`. - The 32k state-plus-longest-question limit is a separate ceiling from the 64k total: staying under 64k does not guarantee you are under 32k for a long question. ## Related - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — the questions asked about a state - [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md) — what the model does with it - [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) — decomposing state and questions - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — context length, pricing, rate limits - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — the request schema - [Jev 1.13 jaggedness: known failure modes](https://jevwiki.ai/raw/wiki/concepts/jaggedness-jev-1-13.md) — accuracy as state grows - [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) — packing many questions into one request ## Sources - raw/docs/concepts__state.md (https://docs.typesafe.ai/concepts/state) - raw/docs/models.md (https://docs.typesafe.ai/models) --- title: "System One Models" type: concept tags: [system-one, jev, rlcd, calibration, architecture] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/concepts__system-one.md - raw/docs/introduction.md - raw/site/blog-introducing-system-one.txt jev_version: "jev-1.13.0" summary: "System One models make fast, typed, calibrated decisions software can consume directly; Jev is TypeSafe's first one." --- # System One Models > **TL;DR** A System One model evaluates one `state` and returns typed answers plus calibrated probabilities — never generated text. Jev is TypeSafe's flagship and first System One model. Call it with `POST /v1/systemone` (or an SDK), ask [Choice, Score, and Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) questions in parallel against the same state, and branch on the results in your own code. ## What it is System One models are a class of AI models built to make fast, structured decisions that software can use directly. A System One model evaluates a [state](https://jevwiki.ai/raw/wiki/concepts/state.md) and returns typed answers and probabilities. Like an LLM, a System One model understands natural-language input. Unlike an LLM, it returns typed decisions and probabilities rather than generated text. It does not write replies, produce code, or generate explanations of its reasoning. You define the possible answers in advance through [primitives](https://jevwiki.ai/raw/wiki/concepts/primitives.md): | Primitive | Question | Example answer space | Example output | |---|---|---|---| | Choice | Which team should handle this ticket? | `billing`, `technical`, or `account` | `choice: "billing"` | | Score | How frustrated is this customer? | 0 = calm, 1 = frustrated, 2 = very frustrated | `score: 1.4` | | Noul | Does this message request a refund? | True or false | `noul: 0.95` | Links: [Choice questions](https://jevwiki.ai/raw/wiki/concepts/choice.md), [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md), [Noul (yes/no) questions](https://jevwiki.ai/raw/wiki/concepts/noul.md). The docs mark the table above as illustrative configurations and values; see the individual primitive pages for the real configuration options and full response fields. Return fields by question type, per `raw/docs/introduction.md`: | Question type | Goal | Returns | |---|---|---| | Choice | Choose an option from a list | `choice`, `probabilities`, `confidence` | | Score | Score the state on a rubric | `score`, `probabilities`, `confidence` | | Noul | Is this statement true? | `noul` (0–1) | > Jev currently accepts **text input only**: strings, JSON objects, and arrays of text. Images, audio, and video are not supported (yet). Founder Diogo Almeida's framing in the launch blog post: "Think of Jev as a frontier-intelligence function call: unstructured state in, typed probabilistic decisions out." ### Where the name comes from TypeSafe takes the name from Daniel Kahneman's *Thinking, Fast and Slow*: System 1 thinking is fast and intuitive, System 2 is slower and more deliberate. The emphasis here is on fast, focused judgments. The blog FAQ adds that "System 1 thinking" has also implied error-prone, and states TypeSafe's belief that System One Models can be made more reliable than the alternatives. The model name **Jev** is after William Stanley Jevons — TypeSafe expects machine intelligence to follow the Jevons-paradox path of coal, where each order-of-magnitude drop in the cost of intelligence unlocks orders of magnitude more use cases. ## How it works (mechanism) Three mechanisms matter when you write code against it: 1. **Training objective — RLCD.** TypeSafe trains with Reinforcement Learning for Calibrated Decisions, a third post-training path alongside RLHF and RLVR. Probabilities are optimized against outcomes so they reflect uncertainty. Calibration is measured across *groups* of predictions; it does **not** guarantee any individual answer is correct. See [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md). 2. **Parallel sampler.** The blog describes a new model architecture with a "parallel sampler for maximum efficiency": all outputs are generated in a single query rather than one token at a time, each conditioned on the last. This is why adding questions barely changes response time. 3. **Constrained output space.** Possible outputs and structure are defined in advance, so the model "never makes type errors" and, per TypeSafe, "can't hallucinate" a value outside your schema. TypeSafe notes this claim is not empirical: "Schema matching is guaranteed, thus we can confidently add 0% into the plots." ### Frontiers, old and new (TypeSafe's comparison) The launch blog contrasts existing LLMs with System One + Jev. Reproduced as TypeSafe states it — these are TypeSafe's claims about its own product and about competitors: | Dimension | Existing LLMs | System One + Jev | |---|---|---| | Optimized with | RLHF (Reinforcement Learning with Human Feedback) / RLVR (Reinforcement Learning with Verifiable Rewards) | RLCD (Reinforcement Learning for Calibrated Decisions) | | Optimizes for | Human preference: writeups and chat responses human raters prefer. Verifiable rewards: outputs that can be programmatically verified. | Calibrated decisions: answers with epistemically honest probabilities on System One tasks. | | Inputs | Unstructured data (e.g. text) with an emphasis on sequential messages | Structured program state | | Outputs | Strings / generated text — flexible, but must be parsed and validated, and can be hallucinations or refusals | Type-safe structured values, defined in advance, with calibrated probabilities and confidence scores | | Sampling | Sequential: one token at a time, each conditioned on the last | Parallel: all outputs in a single query, "incredibly efficient and hardware-aware" | | Cost | Input `$0.20`–`$10` / MTok; output tokens ~5x more expensive than input | Input `$0.042` / MTok (`$42` per billion tokens); output tokens FREE ("too cheap to meter") | | Speed | End-to-end 3 to 329 seconds for frontier models | End-to-end 70 ms–500 ms; TypeSafe claims 40x–200x faster "for the same levels of frontier intelligence for System One shaped queries" | | Confidence | Models tend to be overconfident and inconsistent even when prompted for a confidence estimate | Always communicates confidence and uncertainty; calibrated (higher confidence means higher accuracy) and more consistent | | Use cases | Human-in-the-loop tasks (chatbots, copilots, coding agents); verifiable problems (math proofs, kernel optimization); demos | AI-powered workflows / "smart if-statements"; map-reducing over big data; real-time applications; verifying, scoring, judging and guardrailing other AI | TypeSafe also claims Jev "achieves similar levels of intelligence on System One tasks compared to existing LLMs, while being two orders of magnitude faster and more efficient." Its headline workflow-eval figures are **193.6x faster, 444.6x cheaper**, which TypeSafe says "are on the higher end of real world gains" — see [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md) for the methodology and caveats, and [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) for the shipped price, rate limits, and context window. ## Why it matters for code Because outputs are typed and constrained, your code can inspect, sort, threshold, and combine answers without parsing prose. The canonical shape of a workflow (from the refund example in the docs): 1. Build a state containing the customer's message, the relevant transactions, and the refund policy. 2. Ask independent questions together — whether a refund was requested, whether the evidence indicates a duplicate charge, whether the policy supports a refund. 3. Combine the answers with deterministic checks in code, then route the case for action or review. All three question types can be mixed in a single API call. Every question is evaluated in parallel and in isolation against the same state in one go. Because each question is evaluated independently, adding more questions does not create context rot. Answers also carry [confidence](https://jevwiki.ai/raw/wiki/concepts/confidence.md), so you decide when to act and when to escalate to a person or a reasoning model. **Atomic questions, composed in code.** Treat each question as a gut-check determination: the kind of judgment a highly knowledgeable person could make in a few seconds given the right context. If a question would require extended reasoning or weighs multiple independent factors, decompose it and combine the results in code. Instead of "rate this startup pitch," ask separately about market size, technical feasibility, and differentiation, then combine the scores with your own formula — when priorities shift you change a coefficient rather than rewriting a prompt. See [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md). ## When to use / when not to use **Use it when** the decision is narrow, the answer space is known in advance, the consumer is code rather than a human reader, and you need speed, cost, or calibrated uncertainty: classification, routing, scoring, detection, extraction, verification, guardrails, ranking, feature extraction. See [Use-case map by industry](https://jevwiki.ai/raw/wiki/concepts/use-case-map.md). **Do not use it when** you need generated text, code, or an explanation; when the model must choose its own next action (System One "does not generate code or choose its own next action"); or when the input is an image, audio, or video — pre-process to text first. ## Gotchas - **Calibration is a population property.** A `0.8` answer is not a promise about that answer; it is a promise about the long-run rate across many `0.8` answers. - **English first.** Jev's primary training language is English; other languages including CJK scripts are accepted but currently have lower accuracy. - **Pin versions if you tune thresholds.** The examples use `jev-latest`, which is also the SDK default and currently resolves to `jev-1.13.0`. Aliases move; the response's `model` field reports which versioned ID answered. - **Cardinality ceiling.** The blog's Wikiracing demo states "Jev supports a cardinality up to 255," and that for higher-cardinality choices TypeSafe used a two-stage system of scoring independently then making an explicit choice. - **Speed claims are measured from TypeSafe's laptops.** "Our published evals are generally run from our laptops on the West Coast (this is where our service is currently based)." ## Related - [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) — what you send as the input - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — Choice, Score, Noul - [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) — thresholding on certainty - [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) — the full design workflow - [AI primer: why calibrated decision models](https://jevwiki.ai/raw/wiki/concepts/machine-learning-primer.md) — RLHF vs RLVR vs RLCD - [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md) — where 193.6x / 444.6x comes from - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — prices, rate limits, context length, aliases - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — `POST /v1/systemone` wire contract - [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md) — the launch post itself ## Sources - raw/docs/concepts__system-one.md (https://docs.typesafe.ai/concepts/system-one) - raw/docs/introduction.md (https://docs.typesafe.ai/introduction) - raw/site/blog-introducing-system-one.txt (https://typesafe.ai/blog/introducing-system-one-models-and-jev) --- title: "Use-case map by industry" type: concept tags: [use-cases, industry, patterns, ideation] created: 2026-09-17 updated: 2026-09-20 confidence: high sources: - raw/docs/concepts__use-case-map.md - raw/docs/models.md - raw/site/blog-introducing-system-one.txt jev_version: "jev-1.13.0" summary: "Scannable map of where Jev fits: five capability categories, eighteen industry/function areas, and ten decision shapes." --- # Use-case map by industry > **TL;DR** Find the closest row below, steal the example decisions, and turn each one into a narrow typed question. The last table (**decision shapes**) is the fastest route from a vague idea to a primitive: match your problem to a shape, then pick Choice, Score, or Noul. ## What it is TypeSafe's map for brainstorming where a System One model fits. The docs' instruction: "Open the closest industry, scan the example decisions, and adapt them to the documents and actions in your own workflow." ## Capability categories | Category | What it means | |---|---| | **AI Automation Software** | Interleave AI with reliable software so you can run it a million times in the background without a human co-pilot. Code owns control flow (not markdown files) while TypeSafe handles the semantic decisions and language understanding. | | **Real-time applications** | Frontier intelligence at real-time speeds (150 ms) means AI can make decisions faster than human perception. Fast and smart enough to be programmed to play games or embedded into a UI. | | **AI Map Reduce over Big Data** | 100x cheaper means you can process giant datasets: search relevant information over giant corpuses, classify giant agent traces, extract features to make predictions. | | **Universal Verification** | Verify the input prompt, extractions, reasoning traces, tool calls, or inputs of any other AI. Detect jailbreaks, citation errors, hallucinations, mistakes, or other error modes that other AIs or LLMs make, at a fraction of the cost of the actual LLM call. | | **Harness Engineering** | Use Jev queries to make your harness smarter — model routing, semantic context retrieval, LLM error detection and guardrails, reasoning-trace classification at lightspeed and a fraction of the cost. | > Note the "150 ms" and "100x cheaper" figures here are TypeSafe's marketing shorthand on this page; the shipped numbers are `$0.042` / MTok input with free output and a 70 ms–500 ms end-to-end range. See [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) and [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md). ## Industry and function map Every bullet below is verbatim from the source page, grouped by its accordion. | Area | Example decisions | |---|---| | **Search and retrieval** | Replace or supplement embeddings in RAG pipelines with semantic search, scoring, and ranking. • Score query-to-candidate relevance. • Rerank results with pairwise comparisons. • Cross-encode queries and candidates for higher precision. • Select useful context for downstream AI workflows. | | **Scientific discovery** | Screen papers against inclusion and exclusion criteria for systematic reviews. • Label passages in interview transcripts, open-ended survey responses, and field notes using predefined themes or categories. • Check whether cited passages support claims in manuscripts and generated summaries. • Flag missing methodological details, such as controls, dataset descriptions, and experimental settings. • Identify entities and relationships across papers to build research knowledge graphs, linking findings to supporting passages. | | **Model routing** | Use Jev to build a custom router that chooses which LLM receives each prompt. • Set routing rules and thresholds for your specific workflow. • Classify intent and domain. • Estimate difficulty and risk. • Escalate requests that need a more expensive model. | | **LLM guardrails** | Place semantic checks on every LLM input, output, and tool call at a fraction of the cost of the LLM call. • Detect jailbreaks and prompt injection. • Identify policy violations and sensitive-data exposure. • Detect tool-call errors and response-quality failures in real time. • Log structured check results and probabilities to make AI system and harness failures easier to trace. | | **Semantic code linting** | Use Jev queries to add automated semantic lints to code and writing. • Define checks for your team's coding conventions and writing guidelines. • Run these checks in CI and flag violations for review. | | **Feature extraction for predictive modeling** | Use Jev to extract probabilistic features from natural-language data. • Combine these features with structured data to train models for tasks with ground-truth outcomes. • Use autoresearch workflows to propose feature definitions and evaluate their predictive value against held-out ground truth. | | **Recruiting** | Evaluate resumes, applications, and interview feedback against explicit, job-related criteria. • Identify relevant experience. • Score evidence for required competencies. • Match candidates to roles. • Route candidates to hiring managers or recruiters. • Escalate uncertain cases for human review. | | **Lead generation** | Match company profiles, executive biographies, and inbound messages to an ideal customer profile. • Score industry fit and company maturity. • Detect buyer relevance, pain points, and purchase intent. • Prioritize and route leads. | | **Customer support** | Classify incoming tickets by issue, product area, and customer intent. • Process call transcripts to extract customer issues, commitments, and follow-up actions. • Detect urgency, frustration, churn risk, and refund requests. • Route cases to the right team, queue, or automated workflow. • Verify support responses against policies and the customer's request. | | **Insurance claims** | Classify first-notice-of-loss reports, adjuster notes, and supporting documents. • Detect claim complexity, missing information, and potential fraud indicators. • Prioritize claims for straight-through processing or specialist review. • Escalate uncertain or high-risk cases to a human adjuster. | | **Financial crime** | Evaluate transaction narratives, KYC documents, and alert histories for suspicious characteristics. • Match entities across inconsistent names, profiles, and records. • Prioritize alerts by risk, relevance, and evidence quality. • Route ambiguous cases to investigators for review. | | **Legal and compliance** | Classify contracts, policies, regulatory filings, and marketing claims. • Detect missing clauses, prohibited claims, and policy violations. • Verify documents against explicit legal or compliance requirements. • Escalate high-risk or uncertain findings to counsel or compliance teams. | | **E-commerce marketplaces** | Classify and normalize product listings across inconsistent seller catalogs. • Extract product attributes from titles and descriptions. • Detect prohibited listings, counterfeit signals, review abuse, and policy violations. • Rank products and route uncertain listings for human review. | | **Moderation and trust and safety** | Apply company-specific, nuanced criteria to decide which posts meet your moderation standards. • Moderate user content and automated conversations across communities, customer support, and SDR workflows. • Detect toxicity, harassment, spam, fraud, unsafe advice, personal-data exposure, opt-out requests, and policy-violating claims. • Combine severity and confidence to allow, warn, review, or block content. | | **Advertising** | Evaluate creative assets, campaign copy, landing pages, and placement context. • Classify brand safety and audience suitability. • Check regulatory compliance and prohibited claims. • Evaluate creative quality and ad-to-landing-page alignment. | | **Gaming** | Evaluate player reports, in-game chat, reviews, and support conversations. • Moderate chat and detect abuse, toxicity, or suspicious behavior. • Annotate content and score frustration or engagement. • Detect churn signals and route player-support requests. | | **Risk assessment** | Convert incident reports, claims notes, transaction descriptions, and vendor assessments into probabilistic risk indicators. • Use these indicators in insurance and underwriting workflows. • Classify risk types and detect suspicious characteristics. • Score severity and prioritize review. • Extract features for broader risk models. | | **Demand forecasting** | Enrich forecasting models with semantic signals from customer inquiries, sales notes, product reviews, support tickets, and market reports. • Extract purchase intent, urgency, and product interest. • Detect supply concerns, competitive pressure, and emerging demand themes. • Feed those features into a forecasting model alongside historical time-series data. | | **Graphs and knowledge graphs** | Annotate and verify knowledge graphs with typed semantic decisions. • Classify relationships and entity types. • Detect contradictions between records or claims. • Support probabilistic traversal and hierarchical classification. | ## Decision shapes (the fastest lookup) | Decision shape | Reach for it when | Examples | |---|---|---| | **Classification** | One known category should win | Intent, topic, department, risk type, entity type | | **Detection** | You need a probability that one property is present | Spam, fraud, urgency, jailbreaks, sensitive data | | **Scoring** | The answer belongs on an ordered rubric | Severity, relevance, quality, frustration, suitability | | **Routing** | A category selects the next code path | Tool use, escalation, model routing, support queues | | **Search** | You need to find items that match a natural-language query | Semantic search, document discovery, candidate generation | | **Retrieval** | A workflow needs the most relevant context or records | RAG context, evidence retrieval, knowledge lookup | | **Ranking** | Items need to be ordered by semantic relevance or quality | Search results, recommendations, candidate prioritization | | **Verification** | An artifact must be checked for specific failure modes | Citation support, policy violations, tool-call errors, response quality | | **ML Feature Extraction** | A downstream classical ML model needs semantic signals | Purchase intent, product interest, competitive pressure, churn signals | | **Structured Data Extraction** | Known fields must be recovered from unstructured input | Candidate attributes, order fields, document labels | ## Why it matters for code The shape tells you the primitive (inferred mapping — the source page does not state it explicitly): Classification and Routing → [Choice](https://jevwiki.ai/raw/wiki/concepts/choice.md); Detection and Verification → [Noul](https://jevwiki.ai/raw/wiki/concepts/noul.md); Scoring, Ranking, and Search relevance → [Score](https://jevwiki.ai/raw/wiki/concepts/score.md); Structured Data Extraction and ML Feature Extraction → a fan-out of several of the above, one question per field or feature. See [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md). Several of these areas have a distilled cookbook: [Cookbook: Line-by-line search](https://jevwiki.ai/raw/wiki/cookbooks/semantic-find.md), [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md), [Cookbook: Classifying RAG passages](https://jevwiki.ai/raw/wiki/cookbooks/classifying-rag-passages.md), [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md), [Cookbook: Guardrails for LLMs](https://jevwiki.ai/raw/wiki/cookbooks/llm-guardrails.md), [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md), [Cookbook: Knowledge graph entity alignment](https://jevwiki.ai/raw/wiki/cookbooks/entity-alignment.md), [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md), [Cookbook: Skill suggestion](https://jevwiki.ai/raw/wiki/cookbooks/skill-suggestion.md). ## Gotchas - This page is an ideation map, not a capability guarantee. Nothing here has an accuracy number attached; for measured workflows see [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md). - "Search" and "Retrieval" over a large corpus imply one Jev call per candidate (or per batch you pack into one state) — the cost model, not a vector index, is what makes that viable. - Anything you pick still has to be decomposed into atomic questions before it works well; see [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md). ## Related - [Decision patterns from the community (with fit verdicts)](https://jevwiki.ai/raw/wiki/ideas/patterns.md) — index of community-sourced decision patterns with fit verdicts; business uses in [Patterns: marketing, sales, GTM, content, support and ops](https://jevwiki.ai/raw/wiki/ideas/patterns-business.md) (complements TypeSafe's own map) - [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) — turning a use case into questions - [Choosing between Choice, Score, Noul](https://jevwiki.ai/raw/wiki/guides/choosing-a-primitive.md) — Choice vs Score vs Noul - [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md) — four measured end-to-end workflows - [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) — the reusable compositions - [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md) — worked recipes - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — the real speed and price figures ## Sources - raw/docs/concepts__use-case-map.md (https://docs.typesafe.ai/concepts/use-case-map) - raw/docs/models.md (https://docs.typesafe.ai/models) — shipped price - raw/site/blog-introducing-system-one.txt (https://typesafe.ai/blog/introducing-system-one-models-and-jev) — 70 ms–500 ms end-to-end range --- title: "Workflow evals: how TypeSafe measures Jev" type: concept tags: [evals, benchmarks, methodology, claims, workflows] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/site/evals-site.txt - raw/site/evals-security_incidents.txt - raw/site/evals-agent_trace_observability.txt - raw/site/evals-invoice_processing.txt - raw/site/evals-customer_service.txt - raw/site/blog-introducing-system-one.txt jev_version: "jev-1.13.0" summary: "TypeSafe's four workflow evals: same harness for every model, reference labels from GPT-6 Astra + Claude Fable 5.1, source of 193.6x/444.6x." --- # Workflow evals: how TypeSafe measures Jev > **TL;DR** TypeSafe fixes a code workflow, runs every model through the same harness, and scores each model against reference labels produced by averaging **GPT-6 Astra** and **Claude Fable 5.1** at high thinking. Across four workflows Jev is claimed **193.6x faster and 444.6x cheaper**; TypeSafe itself says these "are on the higher end of real world gains." Treat the numbers as vendor-run, self-labeled, and useful mainly as evidence for the *architecture* claim: a structured workflow beats a single prompt for every model tested. ## What it is A vendor-published eval suite at `https://evals.typesafe.ai/` with four end-to-end automation workflows. Its framing sentence: "Real world tasks can be executed via **structured workflows** or **standalone prompts**. Structure is always better." The headline plot averages "one model configuration's accuracy, cost and time over the four workflows with equal weight, against the consensus labels. Every model runs at its provider's default reasoning setting. Up and to the left is better." Model families plotted: **TypeSafe, OpenAI, Anthropic, Fireworks**, each in two variants — `workflow` and `prompt`. Two Pareto frontiers are drawn: "nothing is both cheaper and more accurate" and "nothing is both faster and more accurate." ## Methodology ### 1. Decompose the work, build a harness "To automate a task, we decompose the decisions into programmatic rules and intelligent judgments. Rather than ask a model to solve the entire problem in one shot (like the prompt examples in the plot), we ask independent narrow questions and defer to code where possible." The three question types used, as the eval site describes them: | Type | Question | What the model returns | |---|---|---| | **Noul** | yes or no | a probability | | **Choice** | one option from a defined set | a distribution over the choices, as well as confidence | | **Score** | a continuous rating on a scale | a score, distribution over the levels, and confidence | The results are then used programmatically to produce the output actions. **The key finding:** "Averaged across the four example tasks, every model is more accurate, cheaper and faster in the workflow than it is with the same policy as a prompt." This is the most portable result on the site — it is about harness design, not about Jev. The site's toy illustration is an expense-claims policy, where each sentence becomes either a typed question or a code rule: 1. Every claim comes with a receipt. If the receipt cannot be read, ask the employee for a new one. 2. Work out what kind of expense it is: a meal, travel, or equipment. 3. A meal over $75 needs a manager's sign-off when the description on the claim does not clearly match the receipt. 4. Everything else is approved. ### 2. Assume the harness is correct "Instead of debating the correctness of the harness and labels, we assume that the code is correct, and measure against the current smartest large models. For this eval, the reference labels are generated via an average of the responses of **GPT-6 Astra and Claude Fable 5.1, both at high thinking**, answering every question in the harness. All other models are evaluated using the provider's default reasoning settings." Restated in the blog: "every model gets the same workflow. We test how they compare to the average of the smartest models (in this case, Astra and Fable)." TypeSafe explicitly does **not** optimize for a ground-truth classification and does not allow the harness or model to change — "potentially allowing for overfitting via harness engineering." ### 3. Wrap the LLMs so they can answer the same questions "The LLMs use our **System One LLM** wrapper, which constrains LLMs to output structured decisions compatible with our API. We have found this to be the most accurate way to get decisions from LLMs, but this tends to be slower and more expensive than giving decisions without probabilities." Each workflow page also publishes a handful of qualitative cases: "for each model, one where it alone differs from the other two; one where all three miss the reference; one where all three agree." The three models walked through on those pages are labelled **TypeSafe**, **Opus**, and **Sol**. ## The four workflows | Workflow | Task | Inputs | Output | |---|---|---|---| | **Security Incidents** | "A security alert fires on a laptop or a server. Given the alert and everything on file about that machine, we decide whether to close it, pass it to an analyst, or contain it now." | The alert (what fired, on which asset, when); the asset (environment, tier, owner); open tickets; registered devices; scheduled maintenance; standing authorizations | **one of** `AUTO CLOSE`, `NOTIFY USER`, `ESCALATE TIER2`, `KILL PROCESS`, `DISABLE ACCOUNT`, `ESCALATE URGENT` | | **Agent Trace Observability** | "A support agent has just finished with a customer. Given the whole run, every tool call included, we decide whether a person needs to look at it, and how soon." | The agent's instructions; the conversation; tool calls with arguments and results; the final message; customer feedback when left | **one of** `AUTO-CLOSE`, `NOT A BUG`, `HUMAN REVIEW`, `PRIORITY REVIEW`, `FILE ISSUE · ROUTE`, `PAGE ON-CALL` | | **Invoice Processing** | "A vendor's bill arrives. Given the bill, the order behind it, and what was actually delivered, we decide whether it gets paid, held, or sent back." | The invoice; the purchase order; the contract; the vendor record; prior invoices; correspondence; delivery evidence; approvals | **any that apply**: `PAY`, `SCHEDULE`, `SHORT PAY`, `ROUTE FOR APPROVAL`, `HOLD FOR DOCUMENTS`, `REQUEST CORRECTED INVOICE`, `DISPUTE LINES`, `FRAUD REVIEW`, `DUPLICATE` | | **Customer Service** | "A customer writes in. Given the thread so far and the state of their account, we decide what the assistant should say and do next." | The conversation; the customer record; the account (subscription, recent charges, refunds, card status); a pending proposal | **any that apply, sometimes none**: `SAY`, `REFUND`, `FREEZE CARD`, `SET INTENT`, `HAND OFF`, `FLAG FOR REVIEW`, `CLOSE` | ### Workflow structures (worth copying) **Security Incidents** — four stages. (1) Read the alert: three questions about the alert and the records joined to it — was the activity unauthorized, does a record explain it, how strong is the evidence. (2) Close, queue, or act: code combines the three answers with how important the machine is and where it runs; borderline identity alerts also notify the user. (3) The state of the incident: acting opens **eleven more questions** — credentials, live sessions, mail, anything left behind to run later, processes, network traffic, and how far the activity spread. (4) Choose the response: the playbook takes the first group whose conditions are met, then the strongest step in it that still applies; when no group applies, the alert is escalated. **Agent Trace Observability** — three stages. (1) Permission on irreversible actions: every action the agent took that cannot be undone is measured against what it was permitted to do at that point in the run; a breach pages on-call and the review ends there. (2) Task completion and user satisfaction, asked as two separate questions reading different parts of the run "so neither colours the other." (3) The two answers select one of four outcomes — healthy, an expectation gap, an overt failure, or a silent failure — and each asks one further question and then ends the review: close, queue, file a bug, or send to a person. **Invoice Processing** — four stages. (1) Read the documents: seven rounds of questions, one subject at a time; "sums, dates, account numbers and statuses are computed in code rather than asked." (2) Reasons to stop: four conditions end the review immediately — a fraud pattern, an invoice already paid, the wrong vendor or company, or a document that is not an invoice. (3) Holds, disputes and corrections: three rule lists run side by side, every rule that applies adds its actions. (4) Releasing the payment: a sequence of yes-or-no checks decides how the payment leaves. **Customer Service** — four stages. (1) Intent, frustration and risk flags: **eleven readings of the conversation at once** — what the customer wants and how they want it resolved, how frustrated they sound, how urgent it is, and flags such as unauthorized activity, a legal threat, or a request for a person. (2) Consent, fraud, money, retention: four follow-ups plus a tie-break when two intents are close, each running only when the first reading calls for it, with the records it needs attached. (3) Check the assistant's claims against the record — "did it tell the customer a refund had gone through, or that the card was frozen, when neither had happened?" (4) Nine sections run top to bottom: safety, the assistant's claims, a pending proposal, handing off, closing, then the issue itself; the first rule that applies in a section emits its actions, otherwise the next section runs. Common design signature across all four: **many atomic questions asked at once, deterministic arithmetic and status checks kept in code, early-exit stop conditions, and ordered rule groups where the first match wins.** ## What "193.6x faster, 444.6x cheaper" means From the blog: "This is where the claims of 193.6x faster, 444.6x cheaper on our home page comes from." - The comparison is **Jev vs. the LLMs running the identical workflow harness**, averaged across the four workflows above — not Jev vs. a raw LLM API call, and not a benchmark of intelligence. - The LLM baselines run through the System One LLM wrapper, which TypeSafe says "tends to be slower and more expensive than giving decisions without probabilities" — the wrapper is part of what makes the multiplier large. - TypeSafe frames accuracy separately: "Jev is off the charts – owning the Pareto frontier for almost 2 orders of magnitude." - TypeSafe's own bound on the number: "we expect that these are on the higher end of real world gains." ### Caveats TypeSafe publishes (verbatim in substance) 1. **Authorship bias.** "These content of these workflows were not deliberately chosen nor constructed to make our model look good, and are not in our training distribution. However, they were made by individuals on our model capabilities team, so some bias could exist." 2. **Reference-label bias.** "We use the average of GPT-6 Astra and Fable 5.1 as the reference answer, which biases answers towards OpenAI and Anthropic's models. We likely underestimate the relative performance of our model and DeepSeek's models." Note the direction: the scoring reference *is* two of the competitors, so Jev can never score above the reference by construction. 3. **Wrapper overhead.** The LLMs are constrained through TypeSafe's own System One LLM wrapper (above). 4. **Reasoning settings are asymmetric.** Reference labels use Astra and Fable "both at high thinking"; every evaluated model runs at "the provider's default reasoning setting." 5. **Measurement location.** "Our published evals are generally run from our laptops on the West Coast (this is where our service is currently based)" — latency numbers include that network path. 6. **Complexity is deliberate.** "Note that the calls here are significantly more complex than the side-by-side demonstration above. That's because they're more representative of the types of production workloads needed for true business automation." ### Separate claims that are *not* from the workflow evals - The **side-by-side demo** used **GPT-5.6 Terra** with default reasoning, "because we've found it to be the most comparable at intelligence to Jev on average," on a deliberately short, dense state — TypeSafe notes "the relatively shorter input paints our model in an advantageous light," and that the only disagreement in the recorded run was on "Churn likelihood level," which TypeSafe calls genuinely ambiguous. - The **hallucination / type-error plot** uses OpenRouter numbers for LLMs ("there almost certainly is bias here: more complex queries might be routed to better models"), and Jev's 0% is **not empirical**: "Schema matching is guaranteed, thus we can confidently add 0% into the plots." - The **Wikiracing demo** ran against non-reasoning modes of the models (except Astra at its lowest reasoning setting), so "our speedups here tend to be a lot less than in previous demos." ## Why it matters for code - **Copy the harness shape, not the score.** The transferable result is that the same policy expressed as a workflow beat the same policy expressed as a prompt for *every* model tested. - **Ask questions in bulk.** Three of the four workflows front-load a large parallel batch (eleven questions in two of them) and only then branch. See [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md). - **Keep arithmetic in code.** Invoice Processing explicitly computes sums, dates, account numbers and statuses in code rather than asking the model. - **Early exits are cheap correctness.** Both Invoice Processing and Agent Trace Observability end the review immediately on a stop condition rather than scoring everything first. - **Build your own reference set the same way** if you lack labels: an ensemble of expensive reasoning models answering every question in your harness. See [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) and [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md). ## Gotchas - These are **vendor-run evals with vendor-generated labels**. There is no independent ground truth and no third-party replication in the sources. - "Accuracy" here means **agreement with the Astra+Fable average**, not correctness. - The four workflows are the published set; the site notes deeper material (examples, disagreements, full queries) lives on `evals.typesafe.ai` itself, which the captured text only summarizes. - Per-workflow numeric results are not present in the captured text — the plots are images. Do not quote per-workflow accuracy figures from this page; only the aggregate 193.6x / 444.6x is textually attested. ## Related - [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md) — the claims this eval backs - [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) — the harness design the evals embody - [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) — bulk parallel questions - [Confidence-gated routing](https://jevwiki.ai/raw/wiki/patterns/confidence-routing.md) — probability-driven branching - [Testing and evaluating a Jev workflow](https://jevwiki.ai/raw/wiki/guides/testing-and-evaluation.md) — evaluating your own workflow - [Blog: Introducing System One Models & Jev (2026-09-15)](https://jevwiki.ai/raw/wiki/entities/blog-introducing-system-one.md) — the launch post - [Blog: Lies, Damned Lies, and Benchmarks](https://jevwiki.ai/raw/wiki/entities/blog-antibenchmaxxing.md) — TypeSafe on benchmarks - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — the price and latency the evals rest on ## Sources - raw/site/evals-site.txt (https://evals.typesafe.ai/) - raw/site/evals-security_incidents.txt (https://evals.typesafe.ai/security_incidents.html) - raw/site/evals-agent_trace_observability.txt (https://evals.typesafe.ai/agent_trace_observability.html) - raw/site/evals-invoice_processing.txt (https://evals.typesafe.ai/invoice_processing.html) - raw/site/evals-customer_service.txt (https://evals.typesafe.ai/customer_service.html) - raw/site/blog-introducing-system-one.txt (https://typesafe.ai/blog/introducing-system-one-models-and-jev) — "Evidence / Technical Results" --- title: "The typesafe-ai agent skill and Claude Code plugin" type: reference tags: [agent-skill, claude-code, plugin, skills, installation] created: 2026-09-17 updated: 2026-09-21 confidence: high sources: - raw/docs/agent-skill.md - raw/github/skills/README.md - raw/github/skills/skills/typesafe-ai/SKILL.md - raw/github/skills/.claude-plugin/plugin.json - raw/github/skills/.claude-plugin/marketplace.json - raw/x/k2sbhai-2101657436696547773-image.md - raw/x-repos/ryana__jevify.md jev_version: "jev-1.13.0" summary: "Install, update, and invoke the typesafe-ai agent skill (Claude Code plugin typesafe 0.5.7, MIT), plus a faithful digest of the guidance SKILL.md gives agents." --- # The typesafe-ai agent skill and Claude Code plugin > **TL;DR** `claude plugin marketplace add typesafe-ai/skills` then `claude plugin install typesafe@typesafe-ai` (Claude Code), or `npx skills add typesafe-ai/skills --skill typesafe-ai` (other agents, `-g` for global). Invoke with `/typesafe:typesafe-ai` or by saying "use the TypeSafe skill". The skill's core instruction to agents is that the **live docs are the source of truth** — and Mintlify serves any docs page as Markdown by appending `.md`. ## Facts | Field | Value | Source | |---|---|---| | Skill name | `typesafe-ai` | SKILL.md frontmatter `name` | | Plugin name | `typesafe` | `.claude-plugin/plugin.json` | | Plugin version | `0.5.7` | `.claude-plugin/plugin.json` | | Marketplace name | `typesafe-ai` | `.claude-plugin/marketplace.json` | | Plugin description | "Agent skills for building with the TypeSafe System One API." | plugin.json | | Marketplace plugin entry description | "Full context on the TypeSafe API: question types, architectural patterns, and best practices" | marketplace.json | | Plugin source | `./` (repo root) | marketplace.json | | Author / owner | TypeSafe AI, https://typesafe.ai | plugin.json, marketplace.json | | Homepage | https://typesafe.ai | plugin.json | | Repository | https://github.com/typesafe-ai/skills | plugin.json | | License | MIT | plugin.json, SKILL.md frontmatter, repo `LICENSE` ("Copyright (c) 2026 TypeSafe AI") | | Skill path in repo | `skills/typesafe-ai/SKILL.md` | README.md | | Raw SKILL.md URL | https://raw.githubusercontent.com/typesafe-ai/skills/main/skills/typesafe-ai/SKILL.md | docs + README | | Repo commit captured | `65a39f393687675ce170e6094757de20370365b9` | raw/MANIFEST.json | Note the version mismatch to be aware of: the **plugin** is at `0.5.7` while the Python and JS SDKs are at `0.6.0`. The plugin version does not track the SDK version. ## What it is From `raw/docs/agent-skill.md`: "Drop-in skill for Claude Code, Codex, and other agent environments." > The TypeSafe agent skill gives your AI coding agent full context on the TypeSafe API: the three question [types](/primitives), the architectural [patterns](/patterns), and best practices for structuring evaluations. The repo README frames it as: "Agent skills for building with [TypeSafe](https://typesafe.ai): typed decisions and probabilities from System One models." The skill table in the README lists exactly one skill: | Skill | Purpose | |---|---| | `typesafe-ai` | Design TypeSafe workflows, find current docs and cookbooks, and compose typed judgments in code | SKILL.md's own `description` frontmatter says when an agent should load it: "Use when a feature needs programmable common sense, when brainstorming what AI could make possible in an app, or when an LLM prompt-and-parse step could become a structured decision. Applications include routing, ranking, extraction, verification, and interactive experiences; these are starting points, not the limits." ## Installation ### Claude Code plugin > Run these two commands in your terminal: ```bash claude plugin marketplace add typesafe-ai/skills claude plugin install typesafe@typesafe-ai ``` ### Other agents (skills.sh) ```bash npx skills add typesafe-ai/skills --skill typesafe-ai ``` > Choose your agent when prompted. Installation is project-local by default; add `-g` to install globally. ```bash npx skills add typesafe-ai/skills --skill typesafe-ai -g ``` ### Copy-to-your-agent prompt The docs supply a prompt to paste into any coding agent, verbatim: ```text Install the TypeSafe skill. If you're in Claude Code, run `claude plugin marketplace add typesafe-ai/skills`, then `claude plugin install typesafe@typesafe-ai`. If you're in another agent, run `npx skills add typesafe-ai/skills --skill typesafe-ai` and select your agent. Use one installation method. You can read the skill directly at https://github.com/typesafe-ai/skills/blob/main/skills/typesafe-ai/SKILL.md (raw: https://raw.githubusercontent.com/typesafe-ai/skills/main/skills/typesafe-ai/SKILL.md). Then use the TypeSafe skill when working on this project. ``` ### Manual installation > For manual installation, copy the entire [skills/typesafe-ai directory](https://github.com/typesafe-ai/skills/tree/main/skills/typesafe-ai), including its reference files, into your agent's skills directory. **Choose one installation method to avoid duplicate copies.** ### Updates For the Claude Code plugin: ```bash claude plugin marketplace update typesafe-ai claude plugin update typesafe@typesafe-ai ``` > Restart Claude Code or run `/reload-plugins` to load the update. To enable automatic updates, open `/plugin`, select **Marketplaces → typesafe-ai → Enable auto-update**. For skills.sh installations: ```bash npx skills update ``` > For manual copies, replace the entire skill directory with the latest GitHub version. ## Invocation > Naming the skill in your prompt — "use the TypeSafe skill" — works in any agent [...] With the Claude Code plugin, you can also invoke `/typesafe:typesafe-ai` directly. The README's example ask: "Use TypeSafe to route incoming support tickets by department, with human review for uncertain decisions." Example prompts from the docs, verbatim: ```text Using the TypeSafe skill, explore the project and find opportunities for using intelligent judgement to stand in for complex parsing or other fragile code. ``` ```text Using the TypeSafe skill, run some experiments using the TypeSafe API key that I've exported to `TYPESAFE_API_KEY`. Propose changes based on the most promising results. ``` ```text Using the TypeSafe skill, analyze my code and see if there are any applicable cookbooks (https://console.typesafe.ai/docs/cookbooks) that show how I could refactor my code to be less fragile or complex. ``` A longer community prompt for the same job is [`ryana/jevify`](https://github.com/ryana/jevify) (no licence, so linked rather than copied; pointed to by [@mathfax](https://x.com/mathfax/status/2102111616175403215), who appears to work at TypeSafe, as an example of teaching agents to use Jev). It has the agent read the docs, inspect the project, sort opportunities into direct savings, better outcomes and new capabilities, look for design assumptions that only exist because semantic computation used to be expensive, compare each idea with simpler alternatives (rules, caching, embeddings, conventional classifiers), and design an evaluation that could prove the idea wrong. See [Repos: coding agents, orchestration, memory, browser and computer use, integrations](https://jevwiki.ai/raw/wiki/ideas/repos-agents.md). Community audit prompt (not from TypeSafe; circulated by [@k2sbhai](https://x.com/k2sbhai/status/2101657436696547773), 2026-09-20). Read-only, so a safe first step on an existing codebase. With the Claude Code plugin the slash form is `/typesafe:typesafe-ai`, not `/typesafe-ai`. For the same audit without installing the skill, see [Consult guide: could Jev help this project?](https://jevwiki.ai/raw/wiki/ideas/consult.md). ```text Use /typesafe-ai to audit this project. Find every place where we make a slow or expensive LLM call that is really a yes or no decision, a ranking, or a classification. For each one, tell me what Jev would replace, what it would cost, and what would break if the answer is wrong. Then list 3 new features this project could add if judgments were instant and nearly free. Don't change any code yet. Show me the list first. ``` The docs suggest creating an API key at https://console.typesafe.ai/keys for the experiment prompt — [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) cites https://console.typesafe.ai/settings/keys instead. Use https://console.typesafe.ai and navigate to the API keys page; both paths are cited upstream and the console may redirect. See [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) and [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md). ## What SKILL.md tells the agent ### Read the live docs — and fetch them as Markdown > **The live TypeSafe docs are the source of truth. Read them as part of the task.** This skill gives direction; the docs carry current concepts, prompting guidance, API contracts, SDK usage, models, limits, and worked examples. Concrete rules it gives: - Start at the documentation index, https://docs.typesafe.ai/llms.txt, "to discover relevant pages and cookbooks. Use targeted reads rather than loading the entire site." - **Mintlify serves Markdown by appending `.md` to a page path** — for example https://docs.typesafe.ai/concepts/how-to-build-with-system-one.md. "Follow links from the index; convert extensionless documentation page links to `.md` when useful. Resolve relative links against `https://docs.typesafe.ai`." - "Before writing an integration, read the current API or chosen SDK page and the question guidance relevant to the design. For a new workflow, also inspect the closest cookbook: it often shows a better decomposition than a generic classifier." - Fallbacks: "If the index is unavailable, use the direct links below or the site's navigation. If Markdown fetching fails, try the normal page. If live access is unavailable, use available local docs or installed SDK types, state that limitation, and avoid inventing version-dependent details." The task → docs table, reproduced from SKILL.md (wiki equivalents added in the third column): | Task | Start here; follow the relevant details | Wiki equivalent | |---|---|---| | Understand the programming model | System One (`/concepts/system-one.md`), building guide (`/concepts/how-to-build-with-system-one.md`) | [System One Models](https://jevwiki.ai/raw/wiki/concepts/system-one.md), [How to build software with System One](https://jevwiki.ai/raw/wiki/concepts/how-to-build.md) | | Explore what to build | Use-case map (`/concepts/use-case-map.md`), then relevant cookbooks from the index | [Use-case map by industry](https://jevwiki.ai/raw/wiki/concepts/use-case-map.md), [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md) | | Prepare inputs and questions | State (`/concepts/state.md`), primitives (`/primitives.md`), then the chosen primitive's page | [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md), [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) | | Decide how to handle uncertainty | Confidence (`/confidence.md`) | [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md) | | Write API code | HTTP API (`/api.md`), Python SDK (`/sdk/python.md`), or JavaScript SDK (`/sdk/javascript.md`) | [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md), [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md), [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) | | Update an older integration | Migration guide (`/migrating-to-v1.md`) and the installed SDK's current reference | [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md) | ### Find the useful shape > Start from the behavior the user wants: what will the application show, select, change, or hand off? Work backward to the judgments it needs. Keep known rules, calculations, exact lookups, and execution in code. Preserve the user's chosen stack and scope; add TypeSafe where semantic understanding helps. > When brainstorming or choosing an architecture, consider more than classification. The patterns below are starting points: combine primitives around the user's goal, including ideas that do not fit an established recipe. The six directions it lists, with the cookbooks each points at: | Direction | What it means | Pointers | |---|---|---| | **Route and fill known arguments** | "A request can select a handler and its typed parameters. Ask useful branch-specific questions up front and consume only the relevant answers." | [Cookbook: Function calling](https://jevwiki.ai/raw/wiki/cookbooks/function-calling.md), [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md) | | **Select instead of generate** | "Find candidate values or source spans in code, use a judgment to select the intended one, then copy or normalize it. Code can also assemble source text into a formatted document or reading guide." | [Cookbook: Pre-parsed value extraction](https://jevwiki.ai/raw/wiki/cookbooks/pre-parsed-value-extraction.md), [Cookbook: Structure recovery (autoformat)](https://jevwiki.ai/raw/wiki/cookbooks/autoformat.md) | | **Find and judge evidence** | "Retrieve candidates, compare their relevance to a query, and select useful context." | [Cookbook: Re-ranking](https://jevwiki.ai/raw/wiki/cookbooks/rerank.md), [Cookbook: Hierarchical classification](https://jevwiki.ai/raw/wiki/cookbooks/hierarchical-classification.md) | | **Turn judgments into reusable data** | "Score dimensions once, then let code or user controls change weights, thresholds, rankings, and views. With labeled outcomes, those signals can become classical ML features." | [Composite scoring](https://jevwiki.ai/raw/wiki/patterns/composite-scoring.md), [Cookbook: Autoresearch feature discovery](https://jevwiki.ai/raw/wiki/cookbooks/autoresearch-feature-discovery.md) | | **Verify and escalate** | "Check specific claims or fields against their evidence; send uncertain or failing cases to a person or reasoning model." | [Cookbook: Double-checking citations](https://jevwiki.ai/raw/wiki/cookbooks/citation-check.md), [Cookbook: SDE cascade](https://jevwiki.ai/raw/wiki/cookbooks/sde-cascade.md) | | **Respond to changing state** | "Code can retain goals and observations while fresh judgments guide the next bounded step. Keep inferred state distinct from observed facts, and check freshness before applying a result to a changed situation." | [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) | > For open-ended requests, offer the few directions that best serve the user's goal and recommend a starting point. For a concrete request, choose the relevant pattern and build; a brainstorm is not a mandatory detour. ### Design the judgments The primitive-selection table, reproduced: | Need | Primitive | Important distinction | |---|---|---| | One of a defined set | [Choice](https://jevwiki.ai/raw/wiki/concepts/choice.md) | "Picks one option; its distribution compares competing options" | | Whether a condition holds | [Noul](https://jevwiki.ai/raw/wiki/concepts/noul.md) | "Probability of yes; no separate confidence; use one per label when several may apply" | | Degree along a described dimension | [Score](https://jevwiki.ai/raw/wiki/concepts/score.md) | "Probability-weighted position on ordered levels; use comparable per-item Scores for graded ranking" | Rules it gives agents about question construction: - "Give each question enough relevant **state** to answer: source text, identities, relationships, policies, and current facts. Prefer named JSON fields when context has several parts." - "Put the judgment in **instructions** and define its possible answers in **criteria**." - "Question IDs are for code and are not sent to the model; include complete meaning in the question." - "Reference nested state with backticked paths such as `` `ticket.messages[0].text` ``." - "Ask one narrow, coherent judgment per question. Split independently useful dimensions, without destroying the relationship being judged. A bounded action selection or contextual interpretation is valid; atomic does not mean literal fact extraction or a one-sentence limit." - "Strings work for simple questions. Use structured objects or arrays when definitions, contrasts, exclusions, or examples clarify instructions or criteria." See [Structured instructions, options, levels, criteria](https://jevwiki.ai/raw/wiki/concepts/advanced-structure.md). - "Score levels must describe concrete situations and stand on their own." - "Keep the needed answers available. Include a no-match outcome when nothing may fit; use a separate presence judgment when it is independently useful. For source-value selection, check candidate coverage: the model cannot choose an omitted value." ### Compose and verify - "**Ask independent questions over the same state together**, including useful speculative questions. They run in parallel and cannot see one another's answers. State each speculative premise explicitly; code consumes the applicable answers." See [Speculative fan-out](https://jevwiki.ai/raw/wiki/patterns/fan-out.md). - "A second request is warranted when an earlier answer is needed to fetch evidence, construct new state, or determine the next options. Extra questions still use tokens; measure actual request budgets, cost, and end-to-end latency." - "Use probabilities and confidence to guide behavior, with thresholds evaluated on the user's data and consequences. Choice/Score confidence summarizes distribution concentration, not overall workflow correctness or permission to act. A Noul near 0.5 means similar probability for yes and no, not medium intensity. Several acceptable alternatives can also spread probability; low confidence need not invalidate a harmless preference choice. Ignore uncertainty on unused branches." - "Keep policy explicit and raw judgments reusable. Weighted scores suit compensating preferences; an 'any serious violation' rule needs separate conditions. Changing a weight or display filter need not rerun inference when evidence and question meanings are unchanged." - "Typed output guarantees the interface, not truth. System One models are trained for calibrated decisions; validate their performance in the target domain." - "Test representative cases and the resulting application behavior. For failures, inspect the exact state, questions, candidates, answers, composition, and observed outcome. Separate missing evidence, model errors, code errors, and service failures." - "Treat cookbook thresholds and demo results as examples to evaluate, not universal rules or permanent model limitations." - "**Keep API credentials server-side in web apps.**" ## Good vibe coding principles The docs page's four rules for humans working with an agent that has the skill, verbatim: 1. "Talk it out with your agent, using the example prompts above as a starting point." 2. "Review the plan and ensure it makes sense before implementing it." 3. "Put the constants (questions and thresholds) in a single place so they're easy to review. Agents aren't great at writing questions, so expect to edit collaboratively with them." 4. "Don't take assertions at face value; encourage the agent to validate its assumptions." ## Common issues | Symptom | Fix (from `raw/docs/agent-skill.md`) | |---|---| | The agent isn't using the skill | "With the Claude Code plugin, invoke `/typesafe:typesafe-ai`. In other agents, ask to 'use the TypeSafe skill'. If it still does not load, confirm the installer targeted the agent you are using, then restart the agent." | | Routing isn't working like you expect | "Check the questions and thresholds. It's possible that your thresholds are either set too high (causing false negatives) or too low (causing false positives). You may also need to tweak your questions to be more specific." | | You're using confidence thresholds everywhere | "If all you care about is choosing the best option, you just need to choose the option with the highest confidence (rather than setting a confidence threshold). If you have a specific statistical algorithm in mind, you should probably be using probabilities instead of confidence." | | It's difficult to review TypeSafe code | "The most important thing for humans to review is the questions and any threshold constants used in your TypeSafe code. These should be defined in a single code file so that they're easy to find without too much spelunking." | | The agent invents request or response fields | "A stale skill can cause this. Update it using your installation method above and retry." | ## Version notes - Plugin `typesafe` version `0.5.7`, MIT, captured at repo commit `65a39f393687675ce170e6094757de20370365b9` (GitHub org listing puts the last push to `typesafe-ai/skills` at 2026-09-12). - SKILL.md carries no version field of its own; it is versioned with the plugin. - The skill deliberately hard-codes as little as possible — versioned details (models, limits, SDK signatures) are delegated to the live docs, which is why a stale skill mainly shows up as invented fields rather than wrong numbers. ## Related - [typesafe-ai GitHub organisation and repos](https://jevwiki.ai/raw/wiki/entities/github-repos.md) — the `typesafe-ai/skills` repo in context - [Playbook for LLM agents building with Jev](https://jevwiki.ai/raw/wiki/guides/agent-integration-playbook.md) — the wiki's own version of this guidance - [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) — "Vibe it: the agent skill" is step four of the quickstart - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — the three question types the skill routes you to - [Cookbooks overview](https://jevwiki.ai/raw/wiki/cookbooks/overview.md) — the cookbook index the skill tells agents to consult - [Patterns overview](https://jevwiki.ai/raw/wiki/patterns/overview.md) — the patterns the skill names as starting points - [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) — where the API key comes from ## Sources - raw/x/k2sbhai-2101657436696547773-image.md (https://x.com/k2sbhai/status/2101657436696547773) — community audit prompt - raw/docs/agent-skill.md (https://docs.typesafe.ai/agent-skill) - raw/github/skills/README.md (https://github.com/typesafe-ai/skills) - raw/github/skills/skills/typesafe-ai/SKILL.md (https://github.com/typesafe-ai/skills/blob/main/skills/typesafe-ai/SKILL.md) - raw/github/skills/.claude-plugin/plugin.json (https://github.com/typesafe-ai/skills) - raw/github/skills/.claude-plugin/marketplace.json (https://github.com/typesafe-ai/skills) --- title: "TYPESAFE_* environment variables across SDKs" type: reference tags: [environment-variables, configuration, python-sdk, javascript-sdk] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/sdk__python__api__constants.md - raw/docs/sdk__javascript__api__variables__ENV.md - raw/docs/sdk__javascript__api__type-aliases__EnvVar.md - raw/github/typesafe-sdk-python/src/typesafe_sdk/constants.py - raw/github/typesafe-sdk-js/src/env.ts jev_version: "jev-1.13.0" sdk_python: "0.6.0" sdk_js: "0.6.0" summary: "Exactly four TYPESAFE_* environment variables are read by the SDKs: API_KEY, BASE_URL, DEFAULT_MODEL, LOG_LEVEL — both SDKs read all four." --- # TYPESAFE_* environment variables across SDKs > **TL;DR** Four environment variables exist, and both SDKs read all four: `TYPESAFE_API_KEY`, `TYPESAFE_BASE_URL`, `TYPESAFE_DEFAULT_MODEL`, `TYPESAFE_LOG_LEVEL`. Explicit constructor options always take precedence. `TYPESAFE_MODEL`, `TYPESAFE_ENDPOINT`, `TYPESAFE_LABEL`, and `TYPESAFE_PRICE` are **not** SDK environment variables — see [Names that are not SDK env vars](#names-that-are-not-sdk-env-vars). ## The table | Variable | Read by | Default when unset | Meaning | |---|---|---|---| | `TYPESAFE_API_KEY` | Python SDK, JavaScript SDK | none — required | The API key, sent as `Authorization: Bearer `. Python: "Required API key; may be set via the `TYPESAFE_API_KEY` environment variable." JS: "Required API key; used when `apiKey` is omitted." | | `TYPESAFE_BASE_URL` | Python SDK, JavaScript SDK | `https://api.typesafe.ai` | API root. Python constant `DEFAULT_BASE_URL = 'https://api.typesafe.ai'`; JS: "API root; defaults to `https://api.typesafe.ai`." | | `TYPESAFE_DEFAULT_MODEL` | Python SDK, JavaScript SDK | `jev-latest` | Default model name used when a call does not pass `model`. Python constant `DEFAULT_MODEL = 'jev-latest'`; JS: "Default model name; defaults to `jev-latest`." | | `TYPESAFE_LOG_LEVEL` | Python SDK, JavaScript SDK | Python: not stated (the level is only applied "if it names a known level"). JS: `warn`. | Logging level for the SDK logger. Python: "set `TYPESAFE_LOG_LEVEL` (`debug`/`info`/...) and the level is applied" to the `typesafe_sdk` logger. JS: "Log level; defaults to `warn`." | Precedence, stated identically in both SDKs: **explicit options take precedence** over the environment (raw/docs/sdk__javascript__api__variables__ENV.md; `fromCodeOrEnv` in raw/github/typesafe-sdk-js/src/env.ts returns `fromCode ?? readEnv(envVar)`). The JS SDK also trims values and treats a blank string as unset: `process.env[name]?.trim() || undefined` (raw/github/typesafe-sdk-js/src/env.ts). No equivalent trimming is documented for Python. ## Where each name is defined | SDK | Symbol | Value | Source | |---|---|---|---| | Python | `typesafe_sdk.constants.API_KEY_ENV` | `'TYPESAFE_API_KEY'` | raw/docs/sdk__python__api__constants.md, raw/github/typesafe-sdk-python/src/typesafe_sdk/constants.py:3 | | Python | `typesafe_sdk.constants.BASE_URL_ENV` | `'TYPESAFE_BASE_URL'` | same, line 6 | | Python | `typesafe_sdk.constants.DEFAULT_MODEL_ENV` | `'TYPESAFE_DEFAULT_MODEL'` | same, line 9 | | Python | `typesafe_sdk.constants.LOG_LEVEL_ENV` | `'TYPESAFE_LOG_LEVEL'` | same, line 12 | | JavaScript | `ENV.apiKey` | `"TYPESAFE_API_KEY"` | raw/docs/sdk__javascript__api__variables__ENV.md, raw/github/typesafe-sdk-js/src/env.ts:4 | | JavaScript | `ENV.baseURL` | `"TYPESAFE_BASE_URL"` | same, line 6 | | JavaScript | `ENV.defaultModel` | `"TYPESAFE_DEFAULT_MODEL"` | same, line 8 | | JavaScript | `ENV.logLevel` | `"TYPESAFE_LOG_LEVEL"` | same, line 10 | The JS type alias `EnvVar` is `typeof ENV[keyof typeof ENV]` — i.e. the union of exactly those four string literals (raw/docs/sdk__javascript__api__type-aliases__EnvVar.md). Anything outside that union is not readable through the SDK's `readEnv`. ## Client defaults that are not environment variables | Python constant | Value | Meaning | |---|---|---| | `DEFAULT_BASE_URL` | `'https://api.typesafe.ai'` | Default API base URL. | | `DEFAULT_MODEL` | `'jev-latest'` | Default model name. | | `DEFAULT_TIMEOUT` | `10.0` | Default timeout in seconds for each HTTP operation. | The JS equivalent of the timeout is `DEFAULT_TIMEOUT_MS = 10_000` (raw/github/typesafe-sdk-js/src/retry.ts). Neither SDK exposes a timeout environment variable. ## Constructor equivalents | Environment variable | Python `TypeSafeClient(...)` / `AsyncTypeSafeClient(...)` argument | JS `new TypeSafeClient({...})` option | |---|---|---| | `TYPESAFE_API_KEY` | `api_key` | `apiKey` | | `TYPESAFE_BASE_URL` | `base_url` | `baseURL` | | `TYPESAFE_DEFAULT_MODEL` | `model` | `defaultModel` | | `TYPESAFE_LOG_LEVEL` | (logger configuration; the variable is a "quick default") | `logLevel` | Python argument names and docstrings from raw/github/typesafe-sdk-python/src/typesafe_sdk/_core/client/sync/client.py and .../aio/client.py; JS option names from raw/github/typesafe-sdk-js/src/types.ts (`TypeSafeClientConfig`), which documents the fallbacks as "falls back to `TYPESAFE_API_KEY`", "falls back to `TYPESAFE_BASE_URL`, then `https://api.typesafe.ai`", "falls back to `TYPESAFE_DEFAULT_MODEL`, then `jev-latest`", and "falls back to `TYPESAFE_LOG_LEVEL`, then `warn`". ## Usage ```bash export TYPESAFE_API_KEY="your-key-here" ``` ```python from typesafe_sdk import Noul, TypeSafeClient # api_key, base_url and model all come from the environment (or their defaults) with TypeSafeClient() as client: response = 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) ``` ```ts import { choice, TypeSafeClient } from "@typesafe-ai/sdk"; // apiKey, baseURL and defaultModel all come from the environment (or their defaults) const client = new TypeSafeClient(); const response = await client.systemOne({ state: { document: "I was charged twice. Please fix this ASAP." }, questions: { category: choice("What is this ticket about?", { billing: null, technical: null, other: null, }), }, }); console.log(response.answers.category.choice); ``` (Verbatim from raw/docs/sdk__javascript.md, which introduces it with "Set `TYPESAFE_API_KEY` in your environment, then create and use the client".) The direct HTTP equivalent reads the same variable from the shell (raw/docs/introduction__quickstart.md): ```bash curl https://api.typesafe.ai/v1/models \ -H "Authorization: Bearer $TYPESAFE_API_KEY" ``` ## Names that are not SDK env vars Four other `TYPESAFE_*` names appear across `raw/`. None of them is read by either SDK; do not set them expecting an effect. | Name | What it actually is | Where | Verdict | |---|---|---|---| | `TYPESAFE_MODEL` | A **module-level Python constant** in cookbook notebooks, e.g. `TYPESAFE_MODEL = "jev-latest"` and `TYPESAFE_MODEL = "jev-1.12"`, passed explicitly as `model=TYPESAFE_MODEL`. | raw/docs/cookbooks.md, raw/docs/cookbooks__citation_check.md, and ~15 other cookbook pages | Not an environment variable. The SDK variable for this purpose is `TYPESAFE_DEFAULT_MODEL`. | | `TYPESAFE_ENDPOINT` | A **cookbook convention**: `base_url=os.environ.get("TYPESAFE_ENDPOINT")` passed explicitly into `TypeSafeClient(...)`. Because it is passed as an explicit option, it overrides `TYPESAFE_BASE_URL`. | raw/docs/cookbooks__citation_check.md:93, cookbooks__classification_using_confidence.md:85, cookbooks__autoresearch_feature_discovery.md:101, cookbooks__classifying_rag_passages.md:117, cookbooks__entity_alignment.md:101, cookbooks__llm_guardrails.md:78, cookbooks__rerank_typesafe.md:227, cookbooks__skill_suggestion.md:144 | Read from the environment, but by the cookbook code, not the SDK. `TYPESAFE_BASE_URL` is the SDK-native name. Note `os.environ.get` returns `None` when unset, which the client treats as "use the default". | | `TYPESAFE_LABEL` | A Python constant naming a series in a benchmark chart: `TYPESAFE_LABEL = "typesafe_choice"`. | raw/docs/cookbooks__consistency_choice_cookbook.md:530 | Not an environment variable. | | `TYPESAFE_PRICE` | A Python constant holding a price tuple: `TYPESAFE_PRICE = (0.042, 0.00) # Historical TypeSafe rate, as of 2026-08` — dollars per 1M input and output tokens. | raw/docs/cookbooks.md:90, cookbooks__consistency_choice_cookbook.md:95, cookbooks__consistency_noul_cookbook.md | Not an environment variable. Current pricing lives in [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md). | Verified by grepping every `TYPESAFE_[A-Z_]+` occurrence across `raw/` (2026-09-17): only the eight names above appear anywhere, and only the four in [The table](#the-table) appear in `raw/github/typesafe-sdk-python/src` or `raw/github/typesafe-sdk-js/src` as environment-variable names. Non-TypeSafe variables that appear alongside them in cookbooks (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`) belong to those vendors' SDKs, not to TypeSafe. ## Gotchas - Cookbook code frequently uses `os.environ.get("TYPESAFE_API_KEY", "cache-only")` so a keyless kernel replays a JSON cache instead of calling the API. `"cache-only"` is a sentinel in the cookbook harness, not a real key (raw/docs/cookbooks__citation_check.md). - Setting `TYPESAFE_DEFAULT_MODEL` changes which model answers without changing your code; the response's `model` field reports the version that actually answered, so log it (raw/docs/models.md). - Setting `TYPESAFE_BASE_URL` redirects every request, including `GET /v1/models`. A wrong value typically surfaces as `404 Not Found` — see [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md). - The Python SDK marks `authorization`, `proxy-authorization`, `x-api-key`, `api-key`, `cookie`, and `set-cookie` as secret headers so debug logging does not print your key (raw/github/typesafe-sdk-python/src/typesafe_sdk/_core/constants.py). Turning `TYPESAFE_LOG_LEVEL=debug` on is therefore safe with respect to the key itself. ## Related - [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) — client construction and `system_one()` - [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) — client construction and `systemOne()` - [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md) — the other constants in `typesafe_sdk.constants` - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — what `Authorization` and the base URL do on the wire - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — what `jev-latest` resolves to - [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) — setting the key for the first call ## Sources - raw/docs/sdk__python__api__constants.md (https://docs.typesafe.ai/sdk/python/api/constants) - raw/docs/sdk__javascript__api__variables__ENV.md (https://docs.typesafe.ai/sdk/javascript/api/variables/ENV) - raw/docs/sdk__javascript__api__type-aliases__EnvVar.md (https://docs.typesafe.ai/sdk/javascript/api/type-aliases/EnvVar) - raw/github/typesafe-sdk-python/src/typesafe_sdk/constants.py, .../\_core/client/sync/client.py, .../\_core/client/aio/client.py, .../\_core/constants.py - raw/github/typesafe-sdk-js/src/env.ts, raw/github/typesafe-sdk-js/src/types.ts, raw/github/typesafe-sdk-js/src/retry.ts - raw/docs/cookbooks.md and the cookbook pages cited in the table above --- title: "HTTP API: POST /v1/systemone and GET /v1/models" type: reference tags: [http-api, reference, systemone, models, errors] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/api.md - raw/site/openapi.json - raw/docs/introduction__quickstart.md - raw/docs/models.md jev_version: "jev-1.13.0" summary: "Complete wire contract for POST https://api.typesafe.ai/v1/systemone and GET /v1/models: auth, request body, question and answer shapes, usage, errors." --- # HTTP API: POST /v1/systemone and GET /v1/models > **TL;DR** `POST https://api.typesafe.ai/v1/systemone` with `Authorization: Bearer `, `Content-Type: application/json`, and a body of `{state, model, questions}`. You get back `{model, answers, usage}` where `answers` is keyed by the question ids you chose. `GET /v1/models` lists the model names your key may send. ## Endpoints | Method | URL | Purpose | Request schema | 200 schema | 422 schema | |---|---|---|---|---|---| | `POST` | `https://api.typesafe.ai/v1/systemone` | Evaluate `state` against a map of typed questions | `SystemOneRequest` | `SystemOneResponse` | `HTTPValidationError` | | `GET` | `https://api.typesafe.ai/v1/models` | List models and aliases available to the account | — | `ModelMetadataList` | `HTTPValidationError` | OpenAPI `operationId`s: `systemone_v1_systemone_post`, `models_v1_v1_models_get` (raw/site/openapi.json). See [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md) for every component schema. ## Authentication | Header | Value | Required | Notes | |---|---|---|---| | `Authorization` | `Bearer ` | Yes | OpenAPI security scheme `HTTPBearer` (`type: http`, `scheme: bearer`) applies to both endpoints. A missing or invalid key returns `401 Unauthorized`. | | `Content-Type` | `application/json` | Yes for `POST` | The only request content type in the spec. | Get a key at `https://console.typesafe.ai/settings/keys` (raw/docs/introduction__quickstart.md). The SDKs read it from `TYPESAFE_API_KEY`; see [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md). Headers the official SDKs also send or read (raw/github/typesafe-sdk-python/src/typesafe_sdk/_core/constants.py, raw/github/typesafe-sdk-js/src/client.ts): request `User-Agent: typesafe-sdk/`, `Accept`, `X-TypeSafe-SDK`, `X-TypeSafe-Runtime`, `X-TypeSafe-Retry-Count`; response `x-typesafe-request-id` (surfaced as `request_id` / `requestId` on errors), `retry-after`, `retry-after-ms`. None of these are documented as required in raw/docs/api.md. ## Request body (`SystemOneRequest`) | Field | Type | Required | Constraints | Description | |---|---|---|---|---| | `state` | `string \| object \| array` | Yes | — | The content all questions in this request refer to. A plain string for text, or structured data (object/array) for chat logs, records, or application state. | | `model` | `string` | Yes | — | The model that handles the request. Use `"jev-latest"`. Names come from `GET /v1/models`; versioned IDs such as `jev-1.13.0` are also accepted. | | `questions` | `map` | Yes | `minProperties: 1` (raw/site/openapi.json) | A map of typed question objects. You choose each key; answers come back under the same keys. The key is not sent to the underlying model and is not used in inference (raw/docs/api.md). | `state` and the questions share one budget: 64k tokens per request, and 32k tokens for `state` plus the single longest question (raw/docs/models.md). See [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md). ### Minimal example request (verbatim, raw/docs/api.md) ```json { "state": "Help! My payouts have been failing for 3 days.", "model": "jev-latest", "questions": { "is_urgent": { "type": "noul", "instructions": "Does this convey urgency?" } } } ``` ## Question types A `Question` is one of three types, selected by its `type` field. All three share `type` and `instructions`; each adds its own `criteria`. The OpenAPI discriminator is `type` with mapping `noul → NoulQuestion`, `choice → ChoiceQuestion`, `score → ScoreQuestion`. ### Common fields | Field | Type | Required | Description | |---|---|---|---| | `type` | `"noul" \| "choice" \| "score"` | Yes (all three types) | Selects the question type; the answer carries the same `type`. | | `instructions` | `string \| object \| array \| null` | Marked **required** in raw/docs/api.md for all three types; **not** listed in `required` in raw/site/openapi.json (nullable there). See [Source disagreements](#source-disagreements). | What the model should decide, rate, or answer yes/no about. | ### Noul (`type: "noul"`) A yes/no question. Returns the probability the answer is yes. | Field | Type | Required | Description | |---|---|---|---| | `type` | `"noul"` | Yes | Identifies a yes/no question or statement. | | `instructions` | `string \| object \| array` | Yes (api.md) | The yes/no question or statement to evaluate. | | `criteria` | `NoulCriteria \| null` | No | Optional descriptions of what a yes and a no mean. | | `criteria.true` | `string \| object \| array \| null` | No | What a yes (value near 1) means. | | `criteria.false` | `string \| object \| array \| null` | No | What a no (value near 0) means. | ```json { "state": "Help! My payouts have been failing for 3 days.", "model": "jev-latest", "questions": { "is_urgent": { "type": "noul", "instructions": "Does this convey urgency?", "criteria": { "true": "Explicitly time-sensitive", "false": "No urgency expressed" } } } } ``` ### Choice (`type: "choice"`) Picks one option from a set you define. Returns the chosen option and the full probability distribution. | Field | Type | Required | Description | |---|---|---|---| | `type` | `"choice"` | Yes | Identifies a question that selects one of the choices in `criteria`. | | `instructions` | `string \| object \| array` | Yes (api.md) | What the model should decide. | | `criteria` | `map` | Yes | Option name → rubric description. Use `null` when an option needs no extra detail; a choice without a description is interpreted by its name alone. | ```json { "state": "Help! My payouts have been failing for 3 days.", "model": "jev-latest", "questions": { "department": { "type": "choice", "instructions": "Which team should handle this?", "criteria": { "billing": "Payments, invoicing, refunds", "technical": "Bugs, outages, integrations", "sales": "Pricing, upgrades, new accounts" } } } } ``` ### Score (`type: "score"`) Rates the state along a rubric you define. Returns a probability-weighted value across your levels. | Field | Type | Required | Constraints | Description | |---|---|---|---|---| | `type` | `"score"` | Yes | — | Identifies a question that rates the content using the levels in `criteria`. | | `instructions` | `string \| object \| array` | Yes (api.md) | — | What the model should rate. | | `criteria` | `array` | Yes | `minItems: 1` (raw/site/openapi.json); "at least two levels" (raw/docs/api.md) | Ordered descriptions of the score levels. Each description's position determines its score, starting at zero. | ```json { "state": "Help! My payouts have been failing for 3 days.", "model": "jev-latest", "questions": { "frustration": { "type": "score", "instructions": "How frustrated is the customer?", "criteria": ["Calm", "Frustrated", "Very angry"] } } } ``` ## Response body (`SystemOneResponse`) | Field | Type | Required | Constraints | Description | |---|---|---|---|---| | `model` | `string` | Yes | — | The model that performed the evaluation. May differ from the alias supplied in the request — log it to know which version answered. | | `answers` | `map` | Yes | `minProperties: 1` | One answer per question, keyed by the same ids you used in `questions`. Each answer's `type` matches its question's `type`. | | `usage` | `Usage` | Yes | — | Token usage for this evaluation. | | `usage.input_tokens` | `integer` | Yes | — | Billable input tokens used to evaluate the request. | | `usage.output_tokens` | `integer` | Yes | — | Output tokens used to answer. Output tokens are currently free of charge (raw/site/openapi.json, raw/docs/models.md). | ### Answer types Every answer carries a `type` matching its question. Choice and Score answers also carry a `confidence` between 0 and 1, derived from the answer's probability distribution (raw/docs/api.md). Discriminator mapping: `noul → NoulAnswer`, `choice → ChoiceAnswer`, `score → ScoreAnswer`. #### Noul answer | Field | Type | Required | Description | |---|---|---|---| | `type` | `"noul"` | Yes | Identifies a yes/no answer. | | `noul` | `number` | Yes | The yes/no answer on a scale from 0 (no) to 1 (yes). Near 0.5 indicates uncertainty. | A Noul answer carries **no** `confidence` field. #### Choice answer | Field | Type | Required | Description | |---|---|---|---| | `type` | `"choice"` | Yes | Identifies a selection from the requested choices. | | `choice` | `string` | Yes | The name of the highest-probability option among the question's `criteria`. | | `probabilities` | `map` | Yes | Every option mapped to its probability, 0 to 1; values sum to approximately 1. | | `confidence` | `number` | Yes | How certain the model is, from 0 to 1, derived from `probabilities`. | #### Score answer | Field | Type | Required | Description | |---|---|---|---| | `type` | `"score"` | Yes | Identifies a rating against the requested score levels. | | `score` | `number` | Yes | Probability-weighted average of the rubric levels; may fall between integer levels. | | `legend` | `map` | Yes | Each level number (string key) mapped back to its criteria description. | | `probabilities` | `map` | Yes | Each level (string key, same keys as `legend`) mapped to its probability; values sum to approximately 1. | | `confidence` | `number` | Yes | How certain the model is, from 0 to 1, derived from `probabilities`. | ### Verbatim example response (raw/docs/api.md) ```json { "model": "jev-latest", "answers": { "is_urgent": { "type": "noul", "noul": 0.92 } }, "usage": { "input_tokens": 312, "output_tokens": 48 } } ``` Choice answer (raw/docs/api.md): ```json { "model": "jev-latest", "answers": { "department": { "type": "choice", "choice": "technical", "probabilities": { "billing": 0.08, "technical": 0.85, "sales": 0.07 }, "confidence": 0.82 } }, "usage": { "input_tokens": 312, "output_tokens": 48 } } ``` Score answer (raw/docs/api.md): ```json { "model": "jev-latest", "answers": { "frustration": { "type": "score", "score": 1.6, "legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" }, "probabilities": { "0": 0.05, "1": 0.3, "2": 0.65 }, "confidence": 0.78 } }, "usage": { "input_tokens": 312, "output_tokens": 48 } } ``` ## cURL example (verbatim, raw/docs/introduction__quickstart.md) ```bash curl -X POST https://api.typesafe.ai/v1/systemone \ -H "Authorization: Bearer $TYPESAFE_API_KEY" \ -H "Content-Type: application/json" \ -d @- <<'EOF' { "state": "Hi, I've been trying to connect my Stripe account for 3 days and it keeps failing. I'm losing sales. Please help ASAP.", "model": "jev-latest", "questions": { "urgency": { "type": "noul", "instructions": "Does this message express urgency?" } } } EOF ``` ### Mixed-type request and response (verbatim, raw/docs/introduction__quickstart.md) ```json { "state": "Hi, I've been trying to connect my Stripe account for 3 days and it keeps failing. I'm losing sales. Please help ASAP.", "model": "jev-latest", "questions": { "department": { "type": "choice", "instructions": "Which team should handle this", "criteria": { "billing": "Payment or subscription issues", "technical": "Bugs or integration problems", "sales": "Pricing or account questions" } }, "frustration": { "type": "score", "instructions": "How frustrated the customer appears", "criteria": [ "Calm, just stating facts", "Frustrated but civil", "Very angry, strong language" ] }, "is_urgent": { "type": "noul", "instructions": "The message conveys urgency or time-sensitivity" } } } ``` ```json { "model": "jev-latest", "answers": { "department": { "type": "choice", "choice": "billing", "probabilities": { "billing": 0.84, "technical": 0.159, "sales": 0.001 }, "confidence": 0.596 }, "frustration": { "type": "score", "score": 1.035, "legend": { "0": "Calm, just stating facts", "1": "Frustrated but civil", "2": "Very angry, strong language" }, "confidence": 0.842 }, "is_urgent": { "type": "noul", "noul": 0.999 } }, "usage": { "input_tokens": 312, "output_tokens": 48 } } ``` Note: this quickstart response omits `probabilities` on the Score answer, although both raw/docs/api.md and raw/site/openapi.json mark it required. Treat the quickstart sample as abridged (inferred). ## GET /v1/models Returns the names your account can send in the `model` field, with a description and release date for each. It currently lists the aliases. Versioned IDs such as `jev-1.13.0` are accepted by the `model` field whether or not they appear in the list (raw/docs/models.md). ```bash curl https://api.typesafe.ai/v1/models \ -H "Authorization: Bearer $TYPESAFE_API_KEY" ``` Response (`ModelMetadataList`): | Field | Type | Required | Description | |---|---|---|---| | `models` | `array` | Yes | One entry per model or alias. | | `models[].name` | `string` | Yes | The model ID or alias, as accepted by the `model` field. | | `models[].description` | `string` | Yes | What the model is for. | | `models[].release_date` | `string` | Yes | Release date, formatted `YYYY-MM-DD`. | Example from the OpenAPI `examples` (raw/site/openapi.json): ```json { "models": [ { "name": "jev-latest", "description": "General-purpose system one model.", "release_date": "2026-09-15" } ] } ``` ## Errors Errors use standard HTTP status codes with a JSON body describing what went wrong (raw/docs/api.md). | Status | Meaning | |---|---| | `400 Bad Request` | The request was invalid. Not listed in raw/docs/api.md; both SDKs map it (`BadRequestError` / `TypeSafeBadRequestError`). Not retryable. | | `401 Unauthorized` | Missing or invalid API key. Check the `Authorization` header. | | `403 Forbidden` | Access was denied. Not listed in raw/docs/api.md; both SDKs map it (`PermissionDeniedError` / `TypeSafePermissionDeniedError`). Not retryable. | | `404 Not Found` | The resource was not found. Not listed in raw/docs/api.md; both SDKs map it (`NotFoundError` / `TypeSafeNotFoundError`). Check the path and `TYPESAFE_BASE_URL`. | | `408 Request Timeout` | Not described in the docs; present only in the SDK retry defaults (`http_statuses` / `httpStatuses` include `408`). Retryable. | | `422 Unprocessable Entity` | The request body failed validation — for example a missing required field or a malformed question. The body details the offending field (`HTTPValidationError`). | | `429 Too Many Requests` | You have exceeded your rate limit. Back off and retry after a short delay. | | `5xx` (`500`–`599`) | The server failed to process the request. Not listed as a range in raw/docs/api.md; both SDKs map the whole range to `InternalServerError` / `TypeSafeInternalServerError`. Retryable. | | `529 Overloaded` | TypeSafe is temporarily overloaded. Retry after a short delay. (Handled by the `5xx` branch in both SDKs; neither has a dedicated class.) | This list is **not exhaustive**; the SDK-level mapping incl. 400/403/404/408/5xx is in [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md). The 422 body is `{"detail": [ValidationError, ...]}`; each entry has `loc`, `msg`, `type`, and optionally `input` and `ctx`. Full shape in [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md). For the complete status → SDK exception → retry mapping see [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md). ### Handling rate limits Verbatim guidance (raw/docs/api.md): "When you receive a `429 Too Many Requests` or `529 Overloaded` response, retry the request with exponential backoff instead of retrying immediately. Our client SDKs handle this automatically, so no extra handling is needed if you use one of our SDKs with its default retry policy." Additional facts for direct HTTP callers: - Limits are 250,000 tokens per second and 1,200 requests per minute; exceeding **either** returns `429` (raw/docs/models.md). - The SDKs "honor the `retry-after` header when the response carries one" (raw/docs/models.md). The SDK implementations also read `retry-after-ms`, preferring it over `retry-after` (raw/github/typesafe-sdk-js/src/retry.ts, raw/github/typesafe-sdk-python/src/typesafe_sdk/_core/errors.py). If you implement your own client, read both. - Reference backoff, matching the SDK defaults: initial 500 ms, doubling, capped at 5,000 ms, 25% jitter, 2 retries after the initial attempt; cap any honored server delay at 60,000 ms before falling back to backoff (raw/github/typesafe-sdk-js/src/retry.ts). - Rate limits are stated to be "adjusting dynamically" and can change without notice; higher limits are on custom and enterprise plans via sales@typesafe.ai (raw/docs/models.md). ## Source disagreements | Point | raw/docs/api.md | raw/site/openapi.json | Guidance | |---|---|---|---| | `instructions` requiredness | Marked `required` on Noul, Choice, and Score questions | Not in any question's `required` list; typed `anyOf [string, object, array, null]` | Always send `instructions`; the server schema tolerates its absence but the docs treat it as mandatory. | | Score `criteria` minimum | "You must include at least two levels" | `minItems: 1` | Send at least two levels. | | Score answer `probabilities` | Required | Required | The quickstart example (raw/docs/introduction__quickstart.md) omits it; the two contract sources agree it is present. | ## Version notes - OpenAPI document version `0.2.0`, OpenAPI spec version `3.1.0` (raw/site/openapi.json). - This is the v1 API. The preview endpoint `POST /preview/evaluation` is replaced by `POST /v1/systemone`; field names changed. See [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md). - `document` is no longer accepted; a request with `document` fails validation (raw/docs/migrating-to-v1.md). ## Related - [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md) — every component schema, field by field - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — model IDs, aliases, price, limits, context - [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) — status → exception → retry table - [Migrating from /preview/evaluation to /v1/systemone](https://jevwiki.ai/raw/wiki/reference/migrating-to-v1.md) — what changed from `/preview/evaluation` - [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md) — `TYPESAFE_API_KEY` and friends - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — what Choice, Score, and Noul mean - [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) — the typed Python client over this wire format - [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) — the typed JS/TS client over this wire format - [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) — first call end to end ## Sources - raw/docs/api.md (https://docs.typesafe.ai/api) - raw/site/openapi.json (https://docs.typesafe.ai/openapi.json) - raw/docs/introduction__quickstart.md (https://docs.typesafe.ai/introduction/quickstart) - raw/docs/models.md (https://docs.typesafe.ai/models) - raw/docs/migrating-to-v1.md (https://docs.typesafe.ai/migrating-to-v1) - raw/github/typesafe-sdk-js/src/retry.ts, raw/github/typesafe-sdk-python/src/typesafe_sdk/_core/constants.py --- title: "JavaScript/TypeScript SDK: install, client, choice/score/noul" type: reference tags: [javascript, typescript, sdk, client, reference] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/sdk__javascript.md - raw/docs/sdk__javascript__api.md - raw/docs/sdk__javascript__api__classes__TypeSafeClient.md - raw/docs/sdk__javascript__api__classes__APIPromise.md - raw/docs/sdk__javascript__api__functions__choice.md - raw/docs/sdk__javascript__api__functions__score.md - raw/docs/sdk__javascript__api__functions__noul.md - raw/docs/sdk__javascript__api__interfaces__Models.md - raw/docs/sdk__javascript__api__interfaces__Logger.md - raw/docs/sdk__javascript__api__variables__VERSION.md - raw/docs/sdk__javascript__api__variables__LOG_LEVELS.md - raw/docs/sdk__javascript__api__variables__ENV.md - raw/github/typesafe-sdk-js/README.md - raw/github/typesafe-sdk-js/package.json - raw/github/typesafe-sdk-js/jsr.json - raw/github/typesafe-sdk-js/examples/demo.ts - raw/github/typesafe-sdk-js/src/index.ts - raw/github/typesafe-sdk-js/src/client.ts - raw/github/typesafe-sdk-js/src/questions.ts - raw/github/typesafe-sdk-js/src/api-promise.ts - raw/github/typesafe-sdk-js/src/logging.ts - raw/github/typesafe-sdk-js/src/env.ts - raw/github/typesafe-sdk-js/src/runtime.ts - raw/github/typesafe-sdk-js/src/version.ts - raw/github/typesafe-sdk-js/src/resources/models.ts jev_version: "jev-1.13.0" sdk_js: "0.6.0" summary: "@typesafe-ai/sdk 0.6.0: install, TypeSafeClient config and defaults, systemOne(), choice/score/noul builders, APIPromise, models.list(), logging." --- # JavaScript/TypeScript SDK: install, client, choice/score/noul > **TL;DR** `npm install @typesafe-ai/sdk` (Node >= 20), set `TYPESAFE_API_KEY`, then `new TypeSafeClient().systemOne({ state, questions })`. Build questions with `choice(instructions, {label: description})`, `score(instructions, [ ...ordered rubric ])`, and `noul(instructions?, criteria?)`. Answers are typed from the questions you passed; the call returns an `APIPromise>`, so `await` it for data or `.withResponse()` for data plus the raw `Response` and request ID. ## Package facts | Fact | Value | Source | |---|---|---| | npm name | `@typesafe-ai/sdk` | `package.json` | | version | `0.6.0` | `package.json`, `src/version.ts` (`VERSION`) | | description | "TypeScript SDK for the TypeSafe API" | `package.json` | | license | MIT | `package.json`, `jsr.json` | | author | `evinism` | `package.json` | | engines | `node >= 20` | `package.json`; docs say "Node.js 20 or newer" | | module type | `"type": "module"` (ESM-first) | `package.json` | | homepage | `https://docs.typesafe.ai/sdk/javascript` | `package.json` | | repository | `https://github.com/typesafe-ai/typesafe-sdk-js` | `package.json` | | issues | `https://github.com/typesafe-ai/typesafe-sdk-js/issues` | `package.json` | | published files | `dist`, `LICENSE`, `README.md` | `package.json` | | `sideEffects` | `false` (tree-shakeable) | `package.json` | | packageManager | `npm@11.19.0` | `package.json` | ### Install ```sh npm install @typesafe-ai/sdk ``` Then set the API key in the environment: ```sh export TYPESAFE_API_KEY="sk-..." # value format not documented in raw sources ``` ### Entry points (ESM + CJS + declarations) `package.json` declares dual exports. The README and docs both state: "The package includes ESM, CommonJS, and TypeScript declarations." | Condition | File | |---|---| | `import` → types | `./dist/index.d.mts` | | `import` → default | `./dist/index.mjs` | | `require` → types | `./dist/index.d.cts` | | `require` → default | `./dist/index.cjs` | | legacy `main` | `./dist/index.cjs` | | legacy `module` | `./dist/index.mjs` | | legacy `types` | `./dist/index.d.cts` | | subpath | `./package.json` only | ESM: ```ts import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk"; ``` CommonJS: ```js const { choice, noul, score, TypeSafeClient } = require("@typesafe-ai/sdk"); ``` There is no deep-import subpath: everything is exported from the package root (`src/index.ts` is the single entry). ### JSR The repo contains a `jsr.json` and npm scripts `push:jsr` / `push:jsr:dry`, so the package is set up for JSR publication: ```json { "name": "@typesafe-ai/sdk", "version": "0.6.0", "license": "MIT", "exports": "./src/index.ts", "publish": { "include": ["src/**/*.ts", "README.md", "LICENSE", "jsr.json"], "exclude": ["src/**/*.test.ts"] } } ``` Note that the JSR entry point is the TypeScript source (`./src/index.ts`), not `dist/`. Whether a JSR release actually exists on jsr.io is **not confirmed by any source in `raw/`** — only npm releases are recorded (see [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md)). ## What the package exports From `src/index.ts` (value exports unless marked *type-only*): | Export | Kind | Page | |---|---|---| | `TypeSafeClient` | class | this page | | `APIPromise` | class | this page | | `choice`, `score`, `noul` | functions | this page | | `ENV` | const object | this page, [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md) | | `LOG_LEVELS` | const array | this page | | `VERSION` | const string `"0.6.0"` | this page | | `TypeSafeError`, `APIError`, `APIConnectionError`, `APITimeoutError`, `APIUserAbortError`, `AuthenticationError`, `BadRequestError`, `InternalServerError`, `NotFoundError`, `PermissionDeniedError`, `RateLimitError`, `UnprocessableEntityError` | classes | [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) | | `WithResponse` | *type-only* | [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) | | `EnvVar` | *type-only* | [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) | | `Models` | *type-only* (`export type { Models }`) | this page | | everything in `src/types.ts` | *type-only* (`export type * from "./types"`) | [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) | `Models` is exported as a **type only**, so you cannot `new Models(...)` from the package; you reach it through `client.models`. (The published API reference lists it under "Interfaces"; in source it is a `class` — see the version notes at the bottom.) ## `TypeSafeClient` ```ts new TypeSafeClient(config?: TypeSafeClientConfig): TypeSafeClient; ``` "Client for the TypeSafe AI API." Explicit options take precedence over environment variables, then SDK defaults. Empty or whitespace-only environment values are ignored (`readEnv` trims and treats blank as absent). Throws `TypeSafeError` when the API key is missing, configuration is invalid, or the runtime is unsupported. ### Constructor config Full property table for `TypeSafeClientConfig` (all properties optional): | Property | Type | Required | Default | Description | |---|---|---|---|---| | `apiKey` | `string` | no (but required in effect) | `TYPESAFE_API_KEY` | Required API key; falls back to the env var. Missing → `TypeSafeError`. | | `baseURL` | `string` | no | `TYPESAFE_BASE_URL`, then `https://api.typesafe.ai` | API root. Trailing slashes are stripped. | | `defaultModel` | `string` | no | `TYPESAFE_DEFAULT_MODEL`, then `jev-latest` | Model used when a request omits `model`. | | `logLevel` | `LogLevel` | no | `TYPESAFE_LOG_LEVEL`, then `warn` | `info` logs request summaries; `debug` adds headers and bodies. Known credential headers are redacted; **bodies are not**. | | `logger` | `Logger` | no | prefixed `console` (`[typesafe-sdk]`) | Logger filtered to `logLevel` and above. | | `retry` | `Partial` | no | `DEFAULT_RETRY_POLICY` | Omitted fields use the `RetryPolicy` defaults. | | `timeout` | `number` (ms) | no | `10000` | Timeout **per attempt**; there is no total retry budget. Must be a positive finite number. | | `defaultHeaders` | `Record` | no | `{}` | Additional request headers; per-call headers take precedence. | | `dangerouslyAllowBrowser` | `boolean` | no | `false` | Allow browser use, exposing the API key to page users. | | `fetch` | `Fetch` | no | global `fetch` | Custom HTTP fetch implementation for transport configuration or tests. | Construction-time failures, all `TypeSafeError` (messages verbatim from `src/client.ts`): - Browser detected and `dangerouslyAllowBrowser` not set: "TypeSafeClient is running in a browser, which would expose your API key to anyone using the page. Call the API from a server instead, or pass `dangerouslyAllowBrowser: true` if you understand the risk." - No key: "No API key was provided. Pass `apiKey` to the TypeSafeClient constructor or set the TYPESAFE_API_KEY environment variable." - No global fetch and no `fetch` option: "No global `fetch` is available in this runtime. Pass a `fetch` implementation to the TypeSafeClient constructor." - Invalid `timeout`: "`timeout` must be a positive number of milliseconds, got X." ### Instance properties All are `readonly`. The API key is stored in a private field (`#apiKey`) and is not a public property. | Property | Type | Description | |---|---|---| | `baseURL` | `string` | API root with trailing slashes removed. | | `defaultModel` | `string` | Model used when a request omits `model`. | | `logLevel` | `LogLevel` | Configured log verbosity. | | `logger` | `Logger` | The configured logger, filtered to `logLevel`. | | `retry` | `RetryPolicy` | Retry settings with constructor overrides applied (fully resolved, not partial). | | `timeout` | `number` | Timeout per attempt in milliseconds. | | `defaultHeaders` | `Readonly>` | Additional headers sent with each request. | | `fetch` | `Fetch` | HTTP fetch implementation. | | `models` | `Models` | The models available to the account. | ### `systemOne()` ```ts systemOne( request: SystemOneRequest, options?: RequestOptions, ): APIPromise>; ``` "Answer named questions about text or structured state." | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `request` | `SystemOneRequest` | yes | — | State, questions, and an optional model override. | | `options` | `RequestOptions` | no | `{}` | Per-call timeout, retry, headers, and cancellation settings. | `request` fields: `state: EntryType` (required), `questions: Q` (required, nonempty), `model?: string` (override; omitted values inherit `defaultModel`). Additional properties on a request *variable* are forwarded, including `null` values. Wire behaviour: the SDK validates questions locally, then `POST`s `{...request, model: request.model ?? client.defaultModel}` (a `SystemOneRequestPayload`) to `POST /v1/systemone`. See [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md). Throws: | Error | When | |---|---| | `TypeSafeError` | Questions are empty, or score criteria are not a list of at least two entries (thrown synchronously, before any HTTP). | | `APIError` (or a subclass) | The server returns a non-2xx response after retries. | | `APIConnectionError` / `APITimeoutError` | The request cannot connect or times out after retries. | | `APIUserAbortError` | The caller aborts the request. | Upstream example: ```ts const { answers } = await client.systemOne({ state: "I was charged twice. Please help.", questions: { billing: noul("Is this about billing?") }, }); console.log(answers.billing.noul); ``` ### Headers the client sends Built in `fetchWithRetries`. User-supplied headers are merged first so they cannot clobber auth or the JSON content type; header matching is case-insensitive, last value wins. | Header | Value | |---|---| | `Authorization` | `Bearer ` | | `Accept` | `application/json` | | `User-Agent` | `typesafe-sdk/0.6.0` | | `X-TypeSafe-SDK` | `typesafe-sdk/0.6.0` | | `X-TypeSafe-Runtime` | e.g. `node/22.1.0 (darwin; arm64)`, `bun/`, `deno/`, `vercel-edge`, `cloudflare-workers`, `browser`, `unknown` | | `Content-Type` | `application/json` when there is a body; omitted otherwise | | `X-TypeSafe-Retry-Count` | absent on the first attempt; `"1"`, `"2"`, … on retries | The response request ID is read from `x-typesafe-request-id`. ## Question builders All three are plain functions that return a literal object; nothing is sent when you call them. ### `choice()` ```ts function choice( instructions: EntryType, criteria: T, ): ChoiceQuestion; ``` | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `instructions` | `EntryType` | yes | — | The question as text, a JSON object or array, or `null`. | | `criteria` | `T extends ChoiceCriteria` | yes | — | Labels mapped to descriptions, or `null` for undescribed labels. | Throws `TypeSafeError` "Choice criteria must be a map of labels to descriptions, not a list." if you pass an array. ### `score()` ```ts function score( instructions: EntryType, criteria: T, ): ScoreQuestion; ``` | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `instructions` | `EntryType` | yes | — | The question as text, a JSON object or array, or `null`. | | `criteria` | `T extends ScoreCriteria` | yes | — | At least two descriptions indexed by score from zero; entries may be `null`. | Throws `TypeSafeError` "Score criteria must be a list of descriptions indexed by score from zero, not a map." if you pass an object. In v0.6.0 the rubric is an **ordered sequence**, not an int-keyed map — see [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md). ### `noul()` ```ts function noul( instructions?: EntryType, criteria?: { true?: EntryType; false?: EntryType } | null, ): NoulQuestion; ``` | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `instructions` | `EntryType` | no | `null` | The question as text, a JSON object or array. | | `criteria` | `{ true?: EntryType; false?: EntryType } \| null` | no | `undefined` | Optional descriptions of the yes and no outcomes; `true` describes yes, `false` describes no. | ### Validation of the whole question set `systemOne()` calls `validateQuestions` before sending. It throws `TypeSafeError` for: - an empty object: "At least one question is required." - a `score` question whose `criteria` is not an array: `Score question "" has criteria that are not a list; score criteria must be a list of descriptions indexed by score from zero.` - a `score` question with fewer than two criteria: `Score question "" has N criteria; at least two scores are required.` `choice` and `noul` questions are not otherwise validated client-side. ## `SystemOneRequest` / `SystemOneResult` in practice `SystemOneResult` is `{ model: string; answers: { [K in keyof Q]: ResultFor }; usage: Usage }`. The mapping `ResultFor` is what makes answers typed by question: | Question | Answer type | Key fields | |---|---|---| | `NoulQuestion` | `NoulResponse` | `type: "noul"`, `noul: number` (probability of yes, 0–1) | | `ChoiceQuestion` | `ChoiceResponse` | `type: "choice"`, `choice: keyof T & string`, `confidence: number`, `probabilities: {[label in keyof T]: number}` | | `ScoreQuestion` | `ScoreResponse` | `type: "score"`, `score: number`, `confidence: number`, `legend: ScoreLegend`, `probabilities: {[score in ScoreOf]: number}` | `usage` is `{ input_tokens: number; output_tokens: number }` — snake_case, matching the wire format. TypeScript generics usage — the `const` type parameter is what preserves literal label and tuple types, so you get narrowed keys without any manual annotation: ```ts import { choice, score, TypeSafeClient } from "@typesafe-ai/sdk"; import type { ChoiceResponse, ScoreResponse, SystemOneResult } from "@typesafe-ai/sdk"; const client = new TypeSafeClient(); const questions = { tone: choice("What is the customer's tone?", { calm: null, angry: null }), urgency: score("How urgent is this?", ["can wait", "today", "right now"]), } as const; const result: SystemOneResult = await client.systemOne({ state: "My account is locked and I have a demo in ten minutes.", questions, }); // `tone.choice` is "calm" | "angry", not string: const tone: ChoiceResponse<{ calm: null; angry: null }> = result.answers.tone; if (tone.choice === "angry") console.log("escalate"); // `urgency.probabilities` is keyed "0" | "1" | "2": const urgency: ScoreResponse = result.answers.urgency; console.log(urgency.probabilities["2"], urgency.legend["2"]); ``` Writing questions inline in the `systemOne({ questions: { ... } })` call gives the same inference, because `systemOne` itself declares ``. ## `APIPromise` `systemOne()` and `models.list()` return `APIPromise`, a `Promise` subclass. "Non-2xx responses reject with an `APIError`, including through `asResponse()`." The body is parsed lazily and at most once; `then`/`catch`/`finally` are overridden to go through that single parse. | Method | Signature | Description | |---|---|---| | `asResponse()` | `(): Promise` | The raw `Response` without parsing the body. SDK requests buffer the full body under the request timeout before handoff; reading it afterwards is caller-owned. Don't also `await` the parsed result on the same promise. | | `withResponse()` | `(): Promise>` | `{ data, response, requestId }` — parsed result, HTTP response, and request ID from `x-typesafe-request-id`. | | `map(fn)` | `(fn: (data: T) => U): APIPromise` | Transform the parsed result, sharing the HTTP response and a single body parse. | | `then(onfulfilled?, onrejected?)` | overrides `Promise.then` | Parsed result. | | `catch(onrejected?)` | overrides `Promise.catch` | — | | `finally(onfinally?)` | overrides `Promise.finally` | — | Constructor (public but intended for internal use): `new APIPromise(responsePromise: Promise, parseResponse: (response: Response) => Promise)`. ```ts const { data, response, requestId } = await client .systemOne({ state: "…", questions: { ok: noul("Is this fine?") } }) .withResponse(); console.log(requestId, response.status, response.headers.get("x-typesafe-request-id")); console.log(data.answers.ok.noul); ``` ## `models` resource ```ts client.models.list(options?: RequestOptions): APIPromise ``` "List the models available to the account." Calls `GET /v1/models` and unwraps the `{ models: [...] }` envelope; a response of any other shape raises `TypeSafeError` "Unexpected response shape from GET /v1/models; expected { models: [...] }." `ModelCard`: `{ readonly name: string; readonly description: string; readonly release_date: string }`. Catalogue and pricing live in [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md). ```ts const models = await client.models.list(); console.log(models.map((m) => `${m.name} (${m.release_date})`).join("\n")); ``` ## Logging | Item | Value | |---|---| | `LOG_LEVELS` | `readonly LogLevel[]` = `["debug", "info", "warn", "error", "off"]`, most to least verbose | | `LogLevel` | `"debug" \| "info" \| "warn" \| "error" \| "off"` (`off` disables logging) | | default level | `warn` (`DEFAULT_LOG_LEVEL`) | | default logger | `console` with the prefix `[typesafe-sdk]` | | `Logger` | `{ debug, info, warn, error }`, each `(message: string, ...args: unknown[]) => void` — `console` satisfies it | What gets logged: `info` emits per-attempt summaries (`#3 POST /v1/systemone <- 200 in 412ms (request req_…)`, timeouts, aborts, retry waits). `debug` additionally logs outgoing URL + headers + body and the parsed response body. Redaction covers `authorization`, `proxy-authorization`, `x-api-key` (masked to `Bearer ***abcd`, keeping the scheme and the last four characters of secrets longer than eight) and `cookie` / `set-cookie` (`***`). **Request and response bodies are not redacted** — do not use `debug` on production traffic containing personal data. An invalid level from either the option or `TYPESAFE_LOG_LEVEL` throws `TypeSafeError`: `Invalid log level "X" from . Expected one of: debug, info, warn, error, off.` ```ts const client = new TypeSafeClient({ logLevel: "debug", logger: { debug: (m, ...a) => myLogger.trace({ a }, m), info: (m, ...a) => myLogger.info({ a }, m), warn: (m, ...a) => myLogger.warn({ a }, m), error: (m, ...a) => myLogger.error({ a }, m), }, }); ``` ## Environment variables and `VERSION` `ENV` maps config keys to env var names (see [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md)): | `ENV` key | Env var | Effect | |---|---|---| | `ENV.apiKey` | `TYPESAFE_API_KEY` | Required API key; used when `apiKey` is omitted. | | `ENV.baseURL` | `TYPESAFE_BASE_URL` | API root; defaults to `https://api.typesafe.ai`. | | `ENV.defaultModel` | `TYPESAFE_DEFAULT_MODEL` | Default model name; defaults to `jev-latest`. | | `ENV.logLevel` | `TYPESAFE_LOG_LEVEL` | Log level; defaults to `warn`. | `VERSION` is the string literal type `"0.6.0"`, kept in sync with `package.json` and checked by `npm run check:version`. ## End-to-end example `examples/demo.ts` verbatim from the repo (run with `npm run demo`, which invokes `tsx examples/demo.ts`; needs `TYPESAFE_API_KEY`). The only change you need outside the repo is importing from `"@typesafe-ai/sdk"` instead of `"../src"`: ```ts // Run with `npm run demo`. Needs TYPESAFE_API_KEY in the environment. import { APIError, choice, noul, score, TypeSafeClient } from "../src"; const client = new TypeSafeClient({ logLevel: "info" }); const models = await client.models.list(); console.log("Available models:", models.map((m) => m.name).join(", ")); const ticket = { subject: "Charged twice this month", body: "Hi, I see two charges of $49 on my card for August. I only have one account. Please fix this ASAP, I'm pretty frustrated.", }; try { const { answers, usage } = await client.systemOne({ state: ticket, questions: { isBilling: noul("Is this ticket about billing?"), sentiment: choice("What is the customer's tone?", { calm: null, frustrated: null, angry: null, }), urgency: score("How urgent is this ticket?", ["can wait", "this week", "today", "right now"]), refundRisk: score("How likely is the customer to demand a refund?", [ "unlikely", "possible", "likely", ]), }, }); // Every answer is typed by the question that produced it. const { isBilling, sentiment, urgency, refundRisk } = answers; console.log("billing? ", isBilling.noul.toFixed(2)); console.log( "tone ", sentiment.choice, `(${sentiment.probabilities[sentiment.choice].toFixed(2)})`, ); console.log("urgency ", urgency.score.toFixed(2), "on a 0-3 scale:", urgency.legend); console.log( "refund risk ", refundRisk.score.toFixed(2), `(${refundRisk.confidence.toFixed(2)} confidence)`, ); console.log("tokens ", usage.input_tokens, "in /", usage.output_tokens, "out"); } catch (err) { if (err instanceof APIError) { console.error(`API error ${err.status} (request ${err.requestId ?? "unknown"}):`, err.body); } else { throw err; } } ``` The file uses top-level `await`, so it must run as ESM. The CommonJS equivalent wraps the body in an async IIFE: ```js const { APIError, choice, noul, score, TypeSafeClient } = require("@typesafe-ai/sdk"); (async () => { const client = new TypeSafeClient({ logLevel: "info" }); try { const { answers, usage } = await client.systemOne({ state: { subject: "Charged twice this month", body: "Two $49 charges in August." }, questions: { isBilling: noul("Is this ticket about billing?"), sentiment: choice("What is the customer's tone?", { calm: null, frustrated: null, angry: null, }), urgency: score("How urgent is this ticket?", ["can wait", "this week", "today", "right now"]), }, }); console.log(answers.isBilling.noul, answers.sentiment.choice, answers.urgency.score); console.log(usage.input_tokens, usage.output_tokens); } catch (err) { if (err instanceof APIError) { console.error(`API error ${err.status} (request ${err.requestId ?? "unknown"}):`, err.body); } else { throw err; } } })(); ``` ## Gotchas - **Browser use is refused by default.** `isBrowser()` checks for `window.document` and `navigator`; if present and `dangerouslyAllowBrowser` is not `true`, the constructor throws. Call the API from a server. - **`timeout` is per attempt, not per call.** With `maxRetries: 2` and `timeout: 10000`, worst-case wall time is roughly three attempts plus backoff. - **The body is fully buffered before the promise resolves**, under the same timeout, so `asResponse()` hands you a response whose body is already readable — but don't consume both `asResponse()` and the parsed value on the same `APIPromise`. - **`score` criteria must be a list** in 0.6.0; an int-keyed object throws `TypeSafeError` at build time (`score()`) or at validation time (`systemOne()`). - **Response parsing is lenient**: bodies are `JSON.parse`d even when `content-type` is missing, falling back to the raw text, and an empty body parses to `undefined`. - **`defaultHeaders` cannot override auth**: `Authorization`, `Accept`, `User-Agent`, `X-TypeSafe-SDK`, `X-TypeSafe-Runtime`, and `Content-Type` are merged last and win. ## Version notes - This page describes `@typesafe-ai/sdk` 0.6.0 (repo commit `66880ccded6cb642dc1809620c2b108c33730214`, 2026-09-15). - **Doc-vs-source discrepancy:** the published API reference lists `Models` under *Interfaces* (`# Interface: Models`), but `src/resources/models.ts` declares `export class Models` with a constructor taking an internal `Transport`. Because `src/index.ts` re-exports it with `export type { Models }`, only the type is importable — the docs' classification is accurate from a consumer's point of view, but the source is a class. - The docs' `ChoiceCriteria` index signature renders as `[label: string]: EntryType`; source writes `[label: string]: Description`, and `Description = EntryType`, so they are the same type. ## Related - [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) — every interface and type alias in detail - [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) — error classes, `RetryPolicy`, `RequestOptions` - [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md) — release history - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — the wire contract behind `systemOne()` and `models.list()` - [TYPESAFE_* environment variables across SDKs](https://jevwiki.ai/raw/wiki/reference/environment-variables.md) — `TYPESAFE_*` across SDKs - [Python SDK: install, clients, system_one()](https://jevwiki.ai/raw/wiki/reference/python-sdk.md) — the Python equivalent - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — Choice, Score, Noul - [Quickstart: first call in HTTP, Python, JS](https://jevwiki.ai/raw/wiki/guides/quickstart.md) — first call in HTTP, Python, JS ## Sources - raw/docs/sdk__javascript.md (https://docs.typesafe.ai/sdk/javascript) - raw/docs/sdk__javascript__api.md (https://docs.typesafe.ai/sdk/javascript/api) - raw/docs/sdk__javascript__api__classes__TypeSafeClient.md (https://docs.typesafe.ai/sdk/javascript/api/classes/TypeSafeClient) - raw/docs/sdk__javascript__api__classes__APIPromise.md (https://docs.typesafe.ai/sdk/javascript/api/classes/APIPromise) - raw/docs/sdk__javascript__api__functions__choice.md, __score.md, __noul.md - raw/docs/sdk__javascript__api__interfaces__Models.md, __Logger.md - raw/docs/sdk__javascript__api__variables__VERSION.md, __LOG_LEVELS.md, __ENV.md - raw/github/typesafe-sdk-js (https://github.com/typesafe-ai/typesafe-sdk-js, commit 66880ccded6cb642dc1809620c2b108c33730214): README.md, package.json, jsr.json, examples/demo.ts, src/index.ts, src/client.ts, src/questions.ts, src/api-promise.ts, src/logging.ts, src/env.ts, src/runtime.ts, src/version.ts, src/resources/models.ts --- title: "JavaScript SDK changelog" type: reference tags: [javascript, sdk, changelog, versions, npm] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/sdk__javascript__changelog.md - raw/github/typesafe-sdk-js/docs/changelog.md - raw/github/typesafe-sdk-js/package.json - raw/github/typesafe-sdk-js/jsr.json - raw/github/typesafe-sdk-js/src/version.ts - raw/github/typesafe-sdk-js/src/questions.ts - raw/github/typesafe-sdk-js/src/types.ts - raw/MANIFEST.json jev_version: "jev-1.13.0" sdk_js: "0.6.0" summary: "@typesafe-ai/sdk releases: 0.5.7 initial public release, 0.6.0 (2026-09-15) makes Score.criteria an ordered sequence — the one breaking change." --- # JavaScript SDK changelog > **TL;DR** Two public releases. `0.5.7` was the initial public release; `0.6.0` (2026-09-15, the current version) has exactly one breaking change: `Score.criteria` is now an **ordered sequence** instead of a dictionary keyed by integers. If you are on 0.5.7, rewrite `score("...", {0: "low", 1: "high"})` as `score("...", ["low", "high"])`. ## Releases | Version | Changelog date | npm publish date | Nature | |---|---|---|---| | `0.0.0-bootstrap.0` | not in any changelog | 2026-09-12 | registry placeholder; not a usable release | | `0.5.7` | 2026-09-11 | 2026-09-12 | initial public release | | `0.6.0` | 2026-09-15 | 2026-09-15 | breaking: score criteria become an ordered sequence | The changelog dates come from the upstream changelog (identical in `raw/docs/sdk__javascript__changelog.md` and `raw/github/typesafe-sdk-js/docs/changelog.md`); the npm publish dates are from the registry listing recorded during ingestion. **The two disagree for 0.5.7**: the changelog says 2026-09-11, npm records the publish on 2026-09-12. Treat 2026-09-11 as the release-tag date and 2026-09-12 as the registry timestamp. `0.0.0-bootstrap.0` appears only in the npm version list; it has no changelog entry, no git tag in the ingested repository, and is the conventional placeholder used to claim a package name before the first real publish (inferred). ## v0.6.0 (2026-09-15) Upstream changelog, verbatim: > ### Breaking changes > > * accept `Score.criteria` as an ordered sequence instead of a dictionary keyed by integers That is the entire entry. Nothing else is listed as changed, added, or fixed. ### What it means in the JS SDK `ScoreCriteria` in 0.6.0 is a tuple type with a two-entry minimum: ```ts type ScoreCriteria = readonly [EntryType, EntryType, ...EntryType[]]; ``` and `score()` rejects a map at runtime: ```ts if (!Array.isArray(criteria)) { throw new TypeSafeError( "Score criteria must be a list of descriptions indexed by score from zero, not a map.", ); } ``` `validateQuestions`, which `systemOne()` runs before every request, repeats the check per question and also enforces the minimum length: - `Score question "" has criteria that are not a list; score criteria must be a list of descriptions indexed by score from zero.` - `Score question "" has N criteria; at least two scores are required.` Migration: ```ts // 0.5.7 — dictionary keyed by integers const urgency = score("How urgent is this ticket?", { 0: "can wait", 1: "this week", 2: "today", 3: "right now", }); // 0.6.0 — ordered sequence, index 0 first const urgency = score("How urgent is this ticket?", [ "can wait", "this week", "today", "right now", ]); ``` The score keys are unchanged — index 0 is still the lowest rubric level — so `ScoreResponse.score`, `.legend` and `.probabilities` keep the same meaning. What improves is inference: with a literal array and the `const` type parameter on `score()`, `ScoreOf` narrows to `"0" | "1" | "2" | "3"` instead of `number`, so `legend["3"]` and `probabilities["0"]` are typed. See [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md). Nothing else in the public surface is documented as changed. `VERSION` was bumped to `"0.6.0"` in `src/version.ts` (kept in sync with `package.json` and enforced by `npm run check:version`), and `jsr.json` carries the same `0.6.0`. ## v0.5.7 (2026-09-11) Upstream changelog, verbatim: > This is the initial public release of TypeSafe JavaScript and TypeScript SDK. Learn more in the [documentation](https://docs.typesafe.ai/sdk/javascript). No feature list is published for 0.5.7. Everything documented on [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) describes 0.6.0; the only 0.5.7 difference recorded anywhere in `raw/` is the score-criteria shape. The jump straight to `0.5.7` for a first public release (rather than `0.1.0`) is not explained in any source. ## Repository state | Fact | Value | |---|---| | Repo | `https://github.com/typesafe-ai/typesafe-sdk-js` | | Ingested commit | `66880ccded6cb642dc1809620c2b108c33730214` | | Commit date | 2026-09-15 | | Commit subject | `Release v0.6.0` | | `package.json` version | `0.6.0` | | `jsr.json` version | `0.6.0` | | `src/version.ts` | `export const VERSION = "0.6.0";` | | License | MIT | | Language | TypeScript | The ingested checkout contains a single commit (`Release v0.6.0`), so per-commit history before 0.6.0 is not available locally; the repository is listed as last pushed 2026-09-15. Changelogs are generated with `git-cliff` (pinned at `2.13.1` in `devDependencies`), which is why the docs site changelog and `docs/changelog.md` in the repo are byte-identical apart from bullet markers (`*` vs `-`). ## Version policy notes - `VERSION` is exported as a **literal type** (`const VERSION: "0.6.0" = "0.6.0"`), so a dependency bump changes the type, not just the value. - `npm run check:version` (`scripts/check-version.mjs`) is part of the `check` pipeline that runs on `prepublishOnly`, guarding against `src/version.ts` drifting from `package.json`. - The package is pre-1.0, and 0.6.0 already shipped a breaking change in a minor bump. Pin exactly (`"@typesafe-ai/sdk": "0.6.0"`) rather than with a caret if you care about stability. - The Python SDK ships the same version number `0.6.0` with the same `Score.criteria` breaking change — see [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md). The two SDKs are versioned in lockstep across the releases recorded here (inferred from the matching version numbers and identical breaking change). ## Related - [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) — the 0.6.0 API surface - [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) — `ScoreCriteria`, `ScoreOf`, `ScoreLegend` - [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) — errors thrown by the new validation - [Python SDK changelog](https://jevwiki.ai/raw/wiki/reference/python-sdk-changelog.md) — the parallel Python release history - [Versions and timeline (models, SDKs, API, company)](https://jevwiki.ai/raw/wiki/syntheses/version-timeline.md) — models, SDKs, API and company dates in one place - [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) — what an ordered rubric means to the model ## Sources - raw/docs/sdk__javascript__changelog.md (https://docs.typesafe.ai/sdk/javascript/changelog) - raw/github/typesafe-sdk-js/docs/changelog.md (https://github.com/typesafe-ai/typesafe-sdk-js) - raw/github/typesafe-sdk-js/package.json, jsr.json, src/version.ts, src/questions.ts, src/types.ts (commit 66880ccded6cb642dc1809620c2b108c33730214, 2026-09-15) - raw/MANIFEST.json (commit pin for raw/github/typesafe-sdk-js) - npm registry listing for `@typesafe-ai/sdk` recorded 2026-09-17: 0.0.0-bootstrap.0 and 0.5.7 published 2026-09-12, 0.6.0 published 2026-09-15 --- title: "JavaScript SDK error classes, RetryPolicy, RequestOptions" type: reference tags: [javascript, typescript, sdk, errors, retries] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/sdk__javascript__api__classes__TypeSafeError.md - raw/docs/sdk__javascript__api__classes__APIError.md - raw/docs/sdk__javascript__api__classes__APIConnectionError.md - raw/docs/sdk__javascript__api__classes__APITimeoutError.md - raw/docs/sdk__javascript__api__classes__APIUserAbortError.md - raw/docs/sdk__javascript__api__classes__AuthenticationError.md - raw/docs/sdk__javascript__api__classes__BadRequestError.md - raw/docs/sdk__javascript__api__classes__PermissionDeniedError.md - raw/docs/sdk__javascript__api__classes__NotFoundError.md - raw/docs/sdk__javascript__api__classes__UnprocessableEntityError.md - raw/docs/sdk__javascript__api__classes__RateLimitError.md - raw/docs/sdk__javascript__api__classes__InternalServerError.md - raw/docs/sdk__javascript__api__interfaces__RetryPolicy.md - raw/docs/sdk__javascript__api__interfaces__RequestOptions.md - raw/github/typesafe-sdk-js/src/errors.ts - raw/github/typesafe-sdk-js/src/retry.ts - raw/github/typesafe-sdk-js/src/client.ts - raw/github/typesafe-sdk-js/src/types.ts - raw/github/typesafe-sdk-js/examples/demo.ts jev_version: "jev-1.13.0" sdk_js: "0.6.0" summary: "Error hierarchy of @typesafe-ai/sdk 0.6.0, status-to-class mapping, RetryPolicy defaults (2 retries, 500ms/5s backoff, 0.25 jitter) and RequestOptions." --- # JavaScript SDK error classes, RetryPolicy, RequestOptions > **TL;DR** Every throw from `@typesafe-ai/sdk` 0.6.0 is a `TypeSafeError`. Catch `APIError` for HTTP failures (`.status`, `.headers`, `.body`, `.requestId`; `RateLimitError` adds `.retryAfterMs`), `APIConnectionError` for transport failures (`APITimeoutError` is a subclass carrying `.timeoutMs`), and `APIUserAbortError` for caller cancellation. By default the client retries 408/429/5xx plus connection errors and timeouts, twice, with 500 ms → 5 s exponential backoff and 25 % jitter, honouring `Retry-After` up to 60 s. ## Hierarchy ``` Error └── TypeSafeError base class for SDK errors ├── APIError an unsuccessful HTTP response │ ├── BadRequestError 400 │ ├── AuthenticationError 401 │ ├── PermissionDeniedError 403 │ ├── NotFoundError 404 │ ├── UnprocessableEntityError 422 │ ├── RateLimitError 429 (+ retryAfterMs) │ └── InternalServerError 5xx ├── APIConnectionError DNS/TLS/connection closed, interrupted body │ └── APITimeoutError timeout (+ timeoutMs) └── APIUserAbortError caller aborted via AbortSignal ``` All twelve classes are exported from the package root. `error.name` is set from `new.target.name` in the `TypeSafeError` constructor, so `err.name` is the concrete subclass name (`"RateLimitError"`, not `"Error"`). ## Class reference ### `TypeSafeError` "Base class for SDK errors." Extends `Error`. ```ts new TypeSafeError(message: string, options?: ErrorOptions): TypeSafeError ``` | Parameter | Type | Required | Description | |---|---|---|---| | `message` | `string` | yes | Error message. | | `options` | `ErrorOptions` | no | Standard `{ cause }`. | Properties: those of `Error` (`message`, `name`, `stack`, `cause`). `name` is set to the constructing subclass's name. Thrown directly (not as a subclass) for client-side problems: | Situation | Message | |---|---| | Missing API key | ``No API key was provided. Pass `apiKey` to the TypeSafeClient constructor or set the TYPESAFE_API_KEY environment variable.`` | | No global fetch | ``No global `fetch` is available in this runtime. Pass a `fetch` implementation to the TypeSafeClient constructor.`` | | Browser detected | ``TypeSafeClient is running in a browser, which would expose your API key to anyone using the page. Call the API from a server instead, or pass `dangerouslyAllowBrowser: true` if you understand the risk.`` | | Empty question set | `At least one question is required.` | | `score()` given an object | `Score criteria must be a list of descriptions indexed by score from zero, not a map.` | | `choice()` given an array | `Choice criteria must be a map of labels to descriptions, not a list.` | | Score question not a list | `Score question "" has criteria that are not a list; score criteria must be a list of descriptions indexed by score from zero.` | | Score question too short | `Score question "" has N criteria; at least two scores are required.` | | Invalid log level | `Invalid log level "X" from . Expected one of: debug, info, warn, error, off.` | | Bad `timeout` | ``` `timeout` must be a positive number of milliseconds, got X. ``` | | Bad `retry.maxRetries` | ``` `retry.maxRetries` must be a non-negative integer, got X. ``` | | Bad `retry.backoffInitialMs` / `backoffMaxMs` / `maxRetryAfterMs` | ``` `retry.` must be a non-negative number of milliseconds, got X. ``` | | Bad `retry.backoffJitter` | ``` `retry.backoffJitter` must be between 0 and 1, got X. ``` | | Bad `retry.httpStatuses` entry | ``` `retry.httpStatuses` must contain HTTP status codes, got X. ``` | | Unexpected `GET /v1/models` shape | `Unexpected response shape from GET /v1/models; expected { models: [...] }.` | ### `APIError` "An unsuccessful HTTP response from the API." Extends `TypeSafeError`. ```ts new APIError(status: number, body: unknown, headers: Headers, message?: string): APIError ``` | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `status` | `number` | yes | — | HTTP status code. | | `body` | `unknown` | yes | — | Parsed body. | | `headers` | `Headers` | yes | — | Response headers. | | `message` | `string` | no | derived (see below) | Overrides the derived message. | Properties (all `readonly`, inherited unchanged by every subclass): | Property | Type | Description | |---|---|---| | `status` | `number` | HTTP response status code. | | `headers` | `Headers` | HTTP response headers. | | `body` | `unknown` | Parsed JSON, response text, or `undefined` for an empty body. | | `requestId` | `string \| undefined` | Request ID from `x-typesafe-request-id`, or `undefined` when absent. | Static method: ```ts static fromResponse(status: number, body: unknown, headers: Headers): APIError ``` "Create the error subclass for an HTTP status code." This is what the client calls for every non-2xx response. **Derived message.** `APIError` builds `message` as `" "`, where `detail` is pulled from the body in this order: a plain string body; `body.error` when it is a string; `body.error.message`; `body.message`; `body.detail` when it is a string; `body.detail.message`; or, when `body.detail` is an array, FastAPI-style validation entries formatted as semicolon-separated `path: message` pairs (with a leading `body` segment in `loc` dropped). If nothing matches: `" status code (no body)"` for an empty body, otherwise the raw body (JSON-stringified if needed), truncated to 200 characters with an ellipsis. ### Status → class mapping Exactly as implemented in `APIError.fromResponse`: | HTTP status | Class | Doc description | |---|---|---| | 400 | `BadRequestError` | HTTP 400: the request is invalid. | | 401 | `AuthenticationError` | HTTP 401: authentication failed. | | 403 | `PermissionDeniedError` | HTTP 403: access is denied. | | 404 | `NotFoundError` | HTTP 404: the resource was not found. | | 422 | `UnprocessableEntityError` | HTTP 422: request validation failed. | | 429 | `RateLimitError` | HTTP 429: the rate limit was exceeded. | | ≥ 500 | `InternalServerError` | HTTP 5xx: the server failed to handle the request. | | any other non-2xx (e.g. 402, 405, 408, 409, 418) | `APIError` | base class, no subclass | Note the gaps: **408 has no dedicated class** even though it is retried by default, and 402/409 fall through to plain `APIError`. `BadRequestError`, `AuthenticationError`, `PermissionDeniedError`, `NotFoundError`, `UnprocessableEntityError` and `InternalServerError` add no properties or methods of their own — they exist purely so you can branch with `instanceof`. ### `RateLimitError` Extends `APIError`; everything above plus: | Property | Type | Description | |---|---|---| | `retryAfterMs` | `number \| undefined` | Server retry delay in milliseconds, or `undefined` when absent or invalid. | Computed at construction from the response headers by `parseRetryAfter`, which prefers `retry-after-ms` (a finite non-negative number) and otherwise parses `Retry-After` either as seconds (converted to ms; negative → `undefined`) or as an HTTP date (converted to a non-negative delta from now). ### `APIConnectionError` "The request or response-body delivery failed (DNS, TLS, connection closed, etc.)." Extends `TypeSafeError`. ```ts new APIConnectionError(message?: string, options?: ErrorOptions): APIConnectionError ``` | Parameter | Type | Required | Default | |---|---|---|---| | `message` | `string` | no | `"Connection error."` | | `options` | `ErrorOptions` | no | — | No extra properties. In practice the client constructs it with `` `Connection error: ${err.message}` `` and `{ cause: err }`, so the original `TypeError`/`fetch` failure is on `.cause`. ### `APITimeoutError` "The full response did not arrive within the timeout. A kind of `APIConnectionError`." Extends `APIConnectionError`. ```ts new APITimeoutError(timeoutMs: number, options?: ErrorOptions): APITimeoutError ``` | Parameter / Property | Type | Required | Description | |---|---|---|---| | `timeoutMs` (param) | `number` | yes | The configured timeout. | | `timeoutMs` (property, `readonly`) | `number` | — | Configured timeout in milliseconds. | | `options` | `ErrorOptions` | no | — | Message: `Request timed out after ms.` Because it extends `APIConnectionError`, `catch (e) { if (e instanceof APIConnectionError) … }` also catches timeouts — check `APITimeoutError` **first** if you need to tell them apart. The timeout covers the whole round trip *including body delivery*: the client buffers the full response body under the same abort controller before resolving. ### `APIUserAbortError` "The caller cancelled the request through an `AbortSignal`." Extends `TypeSafeError`. ```ts new APIUserAbortError(message?: string, options?: ErrorOptions): APIUserAbortError ``` | Parameter | Type | Required | Default | |---|---|---|---| | `message` | `string` | no | `"Request was aborted."` | | `options` | `ErrorOptions` | no | — | Raised both when the signal fires during an attempt and when it fires while waiting to retry. It is **never retried**, regardless of policy. ## `RetryPolicy` "Retry configuration. Partial overrides inherit unset fields from the client or SDK defaults." All fields are `readonly` and required on the full interface; you pass `Partial` to the client or to a call. | Property | Type | Required (in `Partial`) | Default | Description | |---|---|---|---|---| | `maxRetries` | `number` | no | `2` | Maximum retries after the initial attempt; `0` disables retries. Must be a non-negative integer. | | `backoffInitialMs` | `number` | no | `500` | First backoff delay in milliseconds, doubled up to `backoffMaxMs`. Must be non-negative and finite. | | `backoffMaxMs` | `number` | no | `5000` | Maximum backoff delay in milliseconds. Must be non-negative and finite. | | `backoffJitter` | `number` | no | `0.25` | Fraction of each backoff delay randomly subtracted, from 0 to 1. | | `httpStatuses` | `ReadonlySet` | no | `new Set([408, 429, 500…599])` | HTTP status codes to retry. Entries must be integers in 100–999. | | `respectRetryAfter` | `boolean` | no | `true` | Honor `Retry-After` and `retry-after-ms` up to `maxRetryAfterMs`. | | `maxRetryAfterMs` | `number` | no | `60000` | Maximum server retry delay in milliseconds; longer delays use backoff. | | `apiConnectionError` | `boolean` | no | `true` | Retry connection failures, including interrupted response bodies (`APIConnectionError`). | | `apiTimeoutError` | `boolean` | no | `true` | Whether to retry `APITimeoutError`. | The defaults come from `DEFAULT_RETRY_POLICY` in `src/retry.ts`; `DEFAULT_MAX_RETRIES` is exported internally as `2` but is not part of the public package surface. `DEFAULT_TIMEOUT_MS` is `10_000`. ### How a delay is computed `retryDelayMs(attempt, headers, policy)` (zero-based `attempt`): 1. If `respectRetryAfter` and response headers are present, parse `retry-after-ms` / `Retry-After`; if the value is defined and `<= maxRetryAfterMs`, **use it as-is** (no jitter). 2. Otherwise: `exponential = min(backoffInitialMs * 2 ** attempt, backoffMaxMs)`, then `round(exponential * (1 - random() * backoffJitter))`. With the defaults that is roughly 375–500 ms before the first retry and 750–1000 ms before the second. ### What is retried | Failure | Retried by default? | Governed by | |---|---|---| | HTTP 408, 429, 500–599 | yes | `httpStatuses` | | Other non-2xx (400, 401, 403, 404, 422, …) | no | `httpStatuses` | | `APIConnectionError` | yes | `apiConnectionError` | | `APITimeoutError` | yes | `apiTimeoutError` (checked before `apiConnectionError`, despite the subclass relationship) | | `APIUserAbortError` | **never** | — | | Client-side `TypeSafeError` (validation, config) | never (thrown before any HTTP) | — | Retries are counted with an `X-TypeSafe-Retry-Count` header (`"1"`, `"2"`, …; absent on the first attempt). Each retry logs at `info`: `#N POST /v1/systemone retrying in 412ms (retry 1/2) after 429`. Overrides are merged field by field: a call's `retry` inherits unset fields from the client's resolved policy, which itself inherits from `DEFAULT_RETRY_POLICY`. The status set is copied on merge, so mutating a `Set` you passed in afterwards has no effect. ## `RequestOptions` "Per-call options that override client settings." All optional; accepted as the second argument of `client.systemOne()` and the first of `client.models.list()`. | Property | Type | Required | Default | Description | |---|---|---|---|---| | `signal` | `AbortSignal` | no | — | Cancellation signal for the request **and pending retries**. | | `timeout` | `number` | no | client `timeout` (`10000`) | Timeout per attempt in milliseconds; there is no total retry budget. Must be a positive finite number. | | `retry` | `Partial` | no | client `retry` | Retry overrides for this call; omitted fields inherit client settings. | | `headers` | `Record` | no | — | Additional headers, merged over `defaultHeaders`. | Header merging is case-insensitive and last-value-wins; the SDK's own auth and protocol headers are applied *after* yours, so they cannot be overridden (see [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md)). There is no `maxRetries` shorthand — write `{ retry: { maxRetries: 0 } }`. ## Example: try/catch with the full hierarchy ```ts import { APIConnectionError, APIError, APITimeoutError, APIUserAbortError, AuthenticationError, BadRequestError, InternalServerError, NotFoundError, PermissionDeniedError, RateLimitError, TypeSafeClient, TypeSafeError, UnprocessableEntityError, choice, } from "@typesafe-ai/sdk"; const client = new TypeSafeClient({ timeout: 15_000, retry: { maxRetries: 3, backoffInitialMs: 250, maxRetryAfterMs: 30_000 }, }); const controller = new AbortController(); setTimeout(() => controller.abort(), 30_000); // hard ceiling across all attempts try { const { answers } = await client.systemOne( { state: { ticket: "I was charged twice." }, questions: { category: choice("What is this ticket about?", { billing: null, technical: null, other: null, }), }, }, { signal: controller.signal, timeout: 8_000, retry: { httpStatuses: new Set([429, 500, 502, 503, 504]) }, headers: { "X-Correlation-Id": "abc-123" }, }, ); console.log(answers.category.choice); } catch (err) { // Order matters: subclasses before their bases. if (err instanceof RateLimitError) { console.error(`rate limited; retry after ${err.retryAfterMs ?? "unknown"}ms`, err.requestId); } else if (err instanceof AuthenticationError || err instanceof PermissionDeniedError) { console.error(`auth problem ${err.status}:`, err.body); // do not retry } else if (err instanceof BadRequestError || err instanceof UnprocessableEntityError) { console.error(`bad request ${err.status}:`, err.message); // fix the payload } else if (err instanceof NotFoundError) { console.error("wrong baseURL or model?", err.status); } else if (err instanceof InternalServerError) { console.error(`server error ${err.status} (request ${err.requestId ?? "unknown"})`); } else if (err instanceof APIError) { // 402, 405, 409, 418, ... land here console.error(`API error ${err.status}:`, err.body, err.headers.get("x-typesafe-request-id")); } else if (err instanceof APITimeoutError) { console.error(`timed out after ${err.timeoutMs}ms`, err.cause); } else if (err instanceof APIConnectionError) { console.error("transport failure:", err.message, err.cause); } else if (err instanceof APIUserAbortError) { console.error("cancelled by caller"); } else if (err instanceof TypeSafeError) { console.error("client-side problem:", err.message); // validation or config } else { throw err; } } ``` CommonJS is identical apart from the import: ```js const { APIError, RateLimitError, TypeSafeClient, choice } = require("@typesafe-ai/sdk"); ``` The minimal upstream form, from `examples/demo.ts`: ```ts try { // ... client.systemOne(...) } catch (err) { if (err instanceof APIError) { console.error(`API error ${err.status} (request ${err.requestId ?? "unknown"}):`, err.body); } else { throw err; } } ``` ## Gotchas - **`APITimeoutError extends APIConnectionError`**, so a bare `instanceof APIConnectionError` branch swallows timeouts. Check the more specific class first. - **No total retry budget.** `timeout` is per attempt; with `maxRetries: 3` a hung endpoint can consume 4 × `timeout` plus backoff. Use an `AbortSignal` for a wall-clock ceiling — it cancels pending retries too. - **`Retry-After` is used verbatim** when `<= maxRetryAfterMs`, with no jitter, so a fleet retrying together will retry together. Lower `maxRetryAfterMs` or set `respectRetryAfter: false` if that matters. - **408 is retried but has no subclass** — it surfaces as a plain `APIError` with `status === 408`. - **`body` is `unknown`.** Narrow it before use; it may be a parsed object, a raw string, or `undefined`. - **Aborting mid-body-read** raises `APIUserAbortError`, not `APIConnectionError`, because the body buffer shares the caller's signal. - **`err.requestId` is the thing to log.** It comes from `x-typesafe-request-id` and is what TypeSafe support will ask for. ## Version notes Described for `@typesafe-ai/sdk` 0.6.0 (repo commit `66880ccded6cb642dc1809620c2b108c33730214`, 2026-09-15). Docs and source agree on every class, property and default listed here; the published per-class pages simply omit the message-derivation logic and the `TypeSafeError` message catalogue, which come from `src/errors.ts` and `src/client.ts`. ## Related - [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) — client construction, defaults, headers - [JavaScript SDK interfaces and type aliases](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-types.md) — `RetryPolicy` and `RequestOptions` in the wider type map - [HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md) — HTTP status semantics across all clients - [Python SDK retries, exceptions, constants](https://jevwiki.ai/raw/wiki/reference/python-sdk-retries-errors.md) — the Python equivalents - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — status codes as the API defines them ## Sources - raw/docs/sdk__javascript__api__classes__TypeSafeError.md, __APIError.md, __APIConnectionError.md, __APITimeoutError.md, __APIUserAbortError.md, __BadRequestError.md, __AuthenticationError.md, __PermissionDeniedError.md, __NotFoundError.md, __UnprocessableEntityError.md, __RateLimitError.md, __InternalServerError.md (https://docs.typesafe.ai/sdk/javascript/api/classes/*) - raw/docs/sdk__javascript__api__interfaces__RetryPolicy.md (https://docs.typesafe.ai/sdk/javascript/api/interfaces/RetryPolicy) - raw/docs/sdk__javascript__api__interfaces__RequestOptions.md (https://docs.typesafe.ai/sdk/javascript/api/interfaces/RequestOptions) - raw/github/typesafe-sdk-js/src/errors.ts, src/retry.ts, src/client.ts, src/types.ts, examples/demo.ts (commit 66880ccded6cb642dc1809620c2b108c33730214) --- title: "JavaScript SDK interfaces and type aliases" type: reference tags: [javascript, typescript, sdk, types, reference] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/sdk__javascript__api.md - raw/docs/sdk__javascript__api__interfaces__ChoiceQuestion.md - raw/docs/sdk__javascript__api__interfaces__ChoiceResponse.md - raw/docs/sdk__javascript__api__interfaces__ScoreQuestion.md - raw/docs/sdk__javascript__api__interfaces__ScoreResponse.md - raw/docs/sdk__javascript__api__interfaces__NoulQuestion.md - raw/docs/sdk__javascript__api__interfaces__NoulResponse.md - raw/docs/sdk__javascript__api__interfaces__Questions.md - raw/docs/sdk__javascript__api__interfaces__SystemOneRequest.md - raw/docs/sdk__javascript__api__interfaces__SystemOneRequestPayload.md - raw/docs/sdk__javascript__api__interfaces__SystemOneResult.md - raw/docs/sdk__javascript__api__interfaces__Usage.md - raw/docs/sdk__javascript__api__interfaces__ModelCard.md - raw/docs/sdk__javascript__api__interfaces__Models.md - raw/docs/sdk__javascript__api__interfaces__WithResponse.md - raw/docs/sdk__javascript__api__interfaces__TypeSafeClientConfig.md - raw/docs/sdk__javascript__api__interfaces__Logger.md - raw/docs/sdk__javascript__api__type-aliases__ChoiceCriteria.md - raw/docs/sdk__javascript__api__type-aliases__ScoreCriteria.md - raw/docs/sdk__javascript__api__type-aliases__ScoreLegend.md - raw/docs/sdk__javascript__api__type-aliases__ScoreOf.md - raw/docs/sdk__javascript__api__type-aliases__ResultFor.md - raw/docs/sdk__javascript__api__type-aliases__Question.md - raw/docs/sdk__javascript__api__type-aliases__Description.md - raw/docs/sdk__javascript__api__type-aliases__EntryType.md - raw/docs/sdk__javascript__api__type-aliases__JsonValue.md - raw/docs/sdk__javascript__api__type-aliases__Fetch.md - raw/docs/sdk__javascript__api__type-aliases__EnvVar.md - raw/docs/sdk__javascript__api__type-aliases__LogLevel.md - raw/docs/sdk__javascript__api__variables__ENV.md - raw/docs/sdk__javascript__api__variables__LOG_LEVELS.md - raw/github/typesafe-sdk-js/src/types.ts - raw/github/typesafe-sdk-js/src/env.ts - raw/github/typesafe-sdk-js/src/logging.ts - raw/github/typesafe-sdk-js/src/api-promise.ts - raw/github/typesafe-sdk-js/src/resources/models.ts jev_version: "jev-1.13.0" sdk_js: "0.6.0" summary: "Every interface, type alias and exported variable in @typesafe-ai/sdk 0.6.0, with per-property type/required/default tables and generics examples." --- # JavaScript SDK interfaces and type aliases > **TL;DR** Everything under `export type * from "./types"` in `@typesafe-ai/sdk` 0.6.0, plus `WithResponse`, `EnvVar`, `Models`, and the two exported constants `ENV` and `LOG_LEVELS`. Question types carry a `const` generic over their criteria, and `ResultFor` maps each question type to its answer type — that is the whole reason `answers.x.choice` is a literal union rather than `string`. ## Type map | Type | Kind | Generic | Purpose | |---|---|---|---| | `JsonValue` | alias | — | Any JSON-compatible value | | `EntryType` | alias | — | The shape accepted for `state`, `instructions`, criteria entries | | `Description` | alias | — | A criterion description (`= EntryType`) | | `NoulQuestion` | interface | — | Yes/no question | | `ChoiceQuestion` | interface | `T extends ChoiceCriteria = ChoiceCriteria` | Named-alternative question | | `ScoreQuestion` | interface | `T extends ScoreCriteria = ScoreCriteria` | Ordered-rubric question | | `ChoiceCriteria` | alias | — | Label → description map | | `ScoreCriteria` | alias | — | Ordered rubric tuple, length ≥ 2 | | `Question` | alias | — | Union of the three question interfaces | | `Questions` | interface | — | `{ [name: string]: Question }` | | `NoulResponse` | interface | — | Yes/no answer | | `ChoiceResponse` | interface | `T extends ChoiceCriteria = ChoiceCriteria` | Selected label + probabilities | | `ScoreResponse` | interface | `T extends ScoreCriteria = ScoreCriteria` | Expected score + legend + probabilities | | `ScoreOf` | alias | `T extends ScoreCriteria` | Score keys inferred from the rubric | | `ScoreLegend` | alias | `T extends ScoreCriteria` | Rubric descriptions keyed by score | | `ResultFor` | alias | `T extends Question` | Question type → answer type | | `Usage` | interface | — | Token usage | | `SystemOneRequest` | interface | `Q extends Questions = Questions` | What you pass to `systemOne()` | | `SystemOneRequestPayload` | interface | — | The wire body, model resolved | | `SystemOneResult` | interface | `Q extends Questions` | What `systemOne()` resolves to | | `ModelCard` | interface | — | One model in `models.list()` | | `Models` | interface (docs) / class (source) | — | The `client.models` resource | | `WithResponse` | interface | `T` | `.withResponse()` return shape | | `TypeSafeClientConfig` | interface | — | Constructor options | | `RetryPolicy` | interface | — | Retry configuration → [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) | | `RequestOptions` | interface | — | Per-call options → [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) | | `Fetch` | alias | — | Pluggable fetch | | `Logger` | interface | — | Log sink | | `LogLevel` | alias | — | Verbosity union | | `EnvVar` | alias | — | Union of the `ENV` values | | `ENV` | const | — | Config key → env var name | | `LOG_LEVELS` | const | — | Ordered level list | `RetryPolicy` and `RequestOptions` also live in `src/types.ts`, but are documented on [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) alongside the failure modes they govern. ## Primitive value types ### `JsonValue` ```ts type JsonValue = | string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue }; ``` "A JSON-compatible value." Recursive; used only as the element type inside `EntryType`. ### `EntryType` ```ts type EntryType = string | { [key: string]: JsonValue } | JsonValue[] | null; ``` "Text, a JSON object or array, or `null` for state, instructions, and criteria." Note it is *not* `JsonValue`: a bare `number` or `boolean` is not an `EntryType`. ### `Description` ```ts type Description = EntryType; ``` "A criterion description; `null` leaves the label undescribed." A readability alias over `EntryType`, used in `ChoiceCriteria`. ## Questions ### `NoulQuestion` | Property | Type | Required | Default | Description | |---|---|---|---|---| | `type` | `"noul"` | yes | — | Discriminant. | | `instructions` | `EntryType` | no | `null` when built with `noul()` | The question as text, a JSON object, or an array; optional or `null`. | | `criteria` | `{ true?: EntryType; false?: EntryType } \| null` | no | `undefined` | Optional descriptions of the yes and no outcomes. | Nested `criteria` members: | Member | Type | Required | Description | |---|---|---|---| | `true` | `EntryType` | no | Description of the yes outcome. | | `false` | `EntryType` | no | Description of the no outcome. | ### `ChoiceQuestion` | Property | Type | Required | Default | Description | |---|---|---|---|---| | `type` | `"choice"` | yes | — | Discriminant. | | `instructions` | `EntryType` | no | — | The question as text, a JSON object, or an array; optional or `null`. | | `criteria` | `T` | **yes** | — | Descriptions of the available outcomes. | ### `ScoreQuestion` | Property | Type | Required | Default | Description | |---|---|---|---|---| | `type` | `"score"` | yes | — | Discriminant. | | `instructions` | `EntryType` | no | — | The question as text, a JSON object, or an array; optional or `null`. | | `criteria` | `T` | **yes** | — | Descriptions of the available outcomes (ordered rubric, length ≥ 2). | ### `ChoiceCriteria` ```ts type ChoiceCriteria = { [label: string]: Description }; ``` "Labels mapped to descriptions, or `null` for undescribed labels." The published docs render the index signature as `[label: string]: EntryType`; since `Description = EntryType`, the two spellings are identical. ### `ScoreCriteria` ```ts type ScoreCriteria = readonly [EntryType, EntryType, ...EntryType[]]; ``` "At least two descriptions indexed by score from zero; `null` leaves a score undescribed." The tuple prefix is what enforces the two-entry minimum at compile time; `validateQuestions` re-checks it at runtime. ### `Question` ```ts type Question = NoulQuestion | ScoreQuestion | ChoiceQuestion; ``` "A question identified by its `type` field." The union members use their *default* generic arguments, so a `Question`-typed value has widened criteria. ### `Questions` ```ts interface Questions { [name: string]: Question; } ``` "Questions keyed by the names used to identify their answers." Must be nonempty at call time — `systemOne()` throws `TypeSafeError` "At least one question is required." for `{}`. ## Responses ### `NoulResponse` | Property | Type | Readonly | Description | |---|---|---|---| | `type` | `"noul"` | yes | Discriminant. | | `noul` | `number` | yes | Probability of a yes answer, from zero to one. | ### `ChoiceResponse` | Property | Type | Readonly | Description | |---|---|---|---| | `type` | `"choice"` | yes | Discriminant. | | `choice` | `keyof T & string` | yes | The selected label. | | `confidence` | `number` | yes | Reported confidence in the selected label. | | `probabilities` | `{ readonly [label in keyof T]: number }` | yes | Probabilities keyed by label. | (The generated docs print `probabilities` as `{ readonly [label in string | number | symbol]: number }` — that is typedoc expanding `keyof T` for the default generic argument, not a different type.) ### `ScoreResponse` | Property | Type | Readonly | Description | |---|---|---|---| | `type` | `"score"` | yes | Discriminant. | | `score` | `number` | yes | Expected score, which may fall between integer rubric levels. | | `confidence` | `number` | yes | Reported confidence in the score. | | `legend` | `ScoreLegend` | yes | Rubric descriptions keyed by score. | | `probabilities` | `{ readonly [score in ScoreOf]: number }` | yes | Probabilities keyed by score. | (Docs print `probabilities` as `{ readonly [score in number | \`${number}\`]: number }` — again the expansion for the default generic argument.) Because `score` is an *expectation*, it is generally not an integer: a 0–3 rubric can return `2.41`. See [Score questions](https://jevwiki.ai/raw/wiki/concepts/score.md) and [Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md). ### `ScoreOf` ```ts type ScoreOf = number extends T["length"] ? number : Extract; ``` "Score keys inferred from the rubric; a fixed-length tuple yields its indices, otherwise `number`." With `score("…", ["a", "b", "c"] as const)` you get `"0" | "1" | "2"`; with a `readonly EntryType[]` of unknown length you get `number`. ### `ScoreLegend` ```ts type ScoreLegend = { readonly [score in ScoreOf]: T[score] }; ``` "Rubric descriptions keyed by score." This is the server echoing back your rubric keyed by index, so `legend["2"]` is the literal description you supplied. ### `ResultFor` ```ts type ResultFor = T extends NoulQuestion ? NoulResponse : T extends ScoreQuestion ? ScoreResponse : T extends ChoiceQuestion ? ChoiceResponse : never; ``` "The answer type for a question, preserving its criteria keys." Order matters: `NoulQuestion` is tested first, then `ScoreQuestion`, then `ChoiceQuestion`; anything else resolves to `never`. ### `Usage` | Property | Type | Readonly | Description | |---|---|---|---| | `input_tokens` | `number` | yes | Number of input tokens used. | | `output_tokens` | `number` | yes | Number of output tokens used. | Snake_case, matching the wire format in [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md). ## Requests and results ### `SystemOneRequest` "State and named questions for `systemOne`. Additional properties on a request variable are forwarded, including `null` values." | Property | Type | Required | Default | Description | |---|---|---|---|---| | `state` | `EntryType` | **yes** | — | Text, a JSON object or array, or `null` to evaluate. | | `questions` | `Q` | **yes** | — | Nonempty questions keyed by the names used to identify their answers. | | `model` | `string` | no | client `defaultModel` (`jev-latest` unless overridden) | Model override. | The "additional properties are forwarded" note is a consequence of TypeScript's excess-property check applying only to object *literals*: pass a pre-declared variable with extra keys and the SDK spreads them into the request body. Treat that as a way to send fields the SDK does not model yet, and as a footgun otherwise. ### `SystemOneRequestPayload` `extends SystemOneRequest` (with the default `Questions`), overriding `model`: | Property | Type | Required | Description | |---|---|---|---| | `state` | `EntryType` | yes | Inherited. | | `questions` | `Questions` | yes | Inherited. | | `model` | `string` | **yes** | Model resolved by the client; no longer optional. | "Request body for `POST /v1/systemone`, with the model resolved." You rarely construct one — `systemOne()` builds it as `{...request, model: request.model ?? this.defaultModel}` — but it is the exact JSON shape that goes on the wire. ### `SystemOneResult` | Property | Type | Readonly | Description | |---|---|---|---| | `model` | `string` | yes | The model used to answer the request (resolved alias, e.g. `jev-1.13.0`). | | `answers` | `{ readonly [K in keyof Q]: ResultFor }` | yes | Answers with types inferred from the supplied questions. | | `usage` | `Usage` | yes | Token usage for the request. | Note that `Q` has **no default** here, unlike `SystemOneRequest` — you always write `SystemOneResult` or let inference supply it. ### `ModelCard` | Property | Type | Readonly | Description | |---|---|---|---| | `name` | `string` | yes | (undocumented in the source docstring) Model name. | | `description` | `string` | yes | (undocumented in the source docstring) | | `release_date` | `string` | yes | (undocumented in the source docstring) ISO date (inferred). | "Metadata for an available model." The three fields carry no per-field docstrings in either docs or source. ### `Models` | Method | Signature | Description | |---|---|---| | `list` | `list(options?: RequestOptions): APIPromise` | List the models available to the account. `options` defaults to `{}`. | "Access to the Models API resource." Reached as `client.models`; exported as a type only. ### `WithResponse` | Property | Type | Readonly | Description | |---|---|---|---| | `data` | `T` | no | The parsed response body. | | `response` | `Response` | no | The HTTP response, with its body consumed by parsing. | | `requestId` | `string \| undefined` | no | Request ID from `x-typesafe-request-id`, or `undefined` when absent. | Returned by `APIPromise#withResponse()`; exported from `src/api-promise.ts`, not `src/types.ts`. ## Configuration types ### `TypeSafeClientConfig` "Client options. Explicit values take precedence over environment variables, then SDK defaults." Every property is optional. | Property | Type | Required | Default | Description | |---|---|---|---|---| | `apiKey` | `string` | no | `TYPESAFE_API_KEY` | Required API key; falls back to the env var. | | `baseURL` | `string` | no | `TYPESAFE_BASE_URL`, then `https://api.typesafe.ai` | API root. | | `defaultModel` | `string` | no | `TYPESAFE_DEFAULT_MODEL`, then `jev-latest` | Default model. | | `logLevel` | `LogLevel` | no | `TYPESAFE_LOG_LEVEL`, then `warn` | `info` logs request summaries; `debug` adds headers and bodies. Known credential headers are redacted; bodies are not. | | `logger` | `Logger` | no | prefixed `console` | Logger filtered to `logLevel` and above. | | `retry` | `Partial` | no | `RetryPolicy` defaults | Retry overrides. | | `timeout` | `number` | no | `10000` | Timeout per attempt in milliseconds, without a total retry budget. | | `defaultHeaders` | `Record` | no | `{}` | Additional request headers; per-call headers take precedence. | | `dangerouslyAllowBrowser` | `boolean` | no | `false` | Allow browser use, exposing the API key to page users. | | `fetch` | `Fetch` | no | global `fetch` | Custom HTTP fetch implementation for transport configuration or tests. | ### `Fetch` ```ts type Fetch = (input: string, init?: RequestInit) => Promise; ``` "HTTP fetch implementation compatible with the global `fetch`." Narrower than the DOM `fetch`: `input` is a `string`, not `RequestInfo | URL`. ### `Logger` "Log methods accepting a message and structured values; compatible with `console`." All four methods are required. | Method | Signature | Returns | |---|---|---| | `debug` | `(message: string, ...args: unknown[]) => void` | `void` | | `info` | `(message: string, ...args: unknown[]) => void` | `void` | | `warn` | `(message: string, ...args: unknown[]) => void` | `void` | | `error` | `(message: string, ...args: unknown[]) => void` | `void` | ### `LogLevel` ```ts type LogLevel = "debug" | "info" | "warn" | "error" | "off"; ``` "Log verbosity; `off` disables logging." Default `warn`. ### `EnvVar` ```ts type EnvVar = (typeof ENV)[keyof typeof ENV]; ``` Resolves to `"TYPESAFE_API_KEY" | "TYPESAFE_BASE_URL" | "TYPESAFE_DEFAULT_MODEL" | "TYPESAFE_LOG_LEVEL"`. The generated docs give it no description. ## Exported variables ### `ENV` ```ts const ENV: { readonly apiKey: "TYPESAFE_API_KEY"; readonly baseURL: "TYPESAFE_BASE_URL"; readonly defaultModel: "TYPESAFE_DEFAULT_MODEL"; readonly logLevel: "TYPESAFE_LOG_LEVEL"; }; ``` "Environment variable names for client configuration. Explicit options take precedence." | Key | Literal value | Documented effect | |---|---|---| | `apiKey` | `"TYPESAFE_API_KEY"` | Required API key; used when `apiKey` is omitted. | | `baseURL` | `"TYPESAFE_BASE_URL"` | API root; defaults to `https://api.typesafe.ai`. | | `defaultModel` | `"TYPESAFE_DEFAULT_MODEL"` | Default model name; defaults to `jev-latest`. | | `logLevel` | `"TYPESAFE_LOG_LEVEL"` | Log level; defaults to `warn`. | ### `LOG_LEVELS` ```ts const LOG_LEVELS: readonly LogLevel[]; ``` "Supported log levels, from most to least verbose." Source value: `["debug", "info", "warn", "error", "off"]`. The published docs give the type but not the value; the value comes from `src/logging.ts`. ### `VERSION` ```ts const VERSION: "0.6.0" = "0.6.0"; ``` A literal type, not a widened `string`. See [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md). ## Runnable example: generics end to end ESM, TypeScript. Nothing here is annotated except to *prove* the inferred types: ```ts import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk"; import type { ChoiceResponse, NoulResponse, Question, Questions, ResultFor, ScoreResponse, SystemOneRequest, SystemOneResult, } from "@typesafe-ai/sdk"; const client = new TypeSafeClient(); const questions = { isBilling: noul("Is this ticket about billing?"), tone: choice("What is the customer's tone?", { calm: null, frustrated: null, angry: null }), urgency: score("How urgent is this ticket?", ["can wait", "this week", "today", "right now"]), } satisfies Questions; const request: SystemOneRequest = { state: { subject: "Charged twice", body: "Two $49 charges in August." }, questions, model: "jev-latest", }; const result: SystemOneResult = await client.systemOne(request); // ResultFor picks the answer type per question: const billing: NoulResponse = result.answers.isBilling; const tone: ChoiceResponse<{ calm: null; frustrated: null; angry: null }> = result.answers.tone; const urgency: ScoreResponse = result.answers.urgency; console.log(billing.noul); // number, 0..1 console.log(tone.choice); // "calm" | "frustrated" | "angry" console.log(tone.probabilities.angry); // number console.log(urgency.score, urgency.legend["3"]); // number, "right now" console.log(urgency.probabilities["0"]); // number console.log(result.model, result.usage.input_tokens, result.usage.output_tokens); // Writing a generic helper: keep the `const` parameter to preserve literals. async function ask(state: unknown, qs: Q) { const { answers } = await client.systemOne({ state: state as never, questions: qs }); return answers; } // `ResultFor` is usable directly for a single question: type ToneAnswer = ResultFor<(typeof questions)["tone"]>; // ChoiceResponse<{...}> // A widened `Question` loses the literal keys — this is why you should not annotate: const widened: Question = questions.tone; type Widened = ResultFor; // ChoiceResponse, `choice` is `string` ``` CommonJS gets the same runtime behaviour but no type parameters at the call site unless you use `// @ts-check` with JSDoc: ```js const { choice, TypeSafeClient } = require("@typesafe-ai/sdk"); /** @type {import("@typesafe-ai/sdk").Questions} */ const questions = { tone: choice("Tone?", { calm: null, angry: null }) }; ``` ## Gotchas - **Annotating kills inference.** `const q: Questions = {...}` widens every criteria object; `answers.x.choice` becomes `string`. Use `satisfies Questions` or no annotation at all. - **`ScoreOf` degrades to `number`** for arrays whose length TypeScript cannot see (e.g. `string[]`), which silently removes the literal keys from `legend` and `probabilities`. - **`ChoiceResponse.choice` is `keyof T & string`**, so a criteria map built from a `Record` yields `string`. - **`EntryType` excludes bare numbers and booleans.** `state: 42` does not type-check; wrap it (`state: { value: 42 }`) or stringify it. - **`Usage` uses snake_case** while everything else in the SDK is camelCase — it mirrors the HTTP response. ## Version notes - Types described for `@typesafe-ai/sdk` 0.6.0 (repo commit `66880ccded6cb642dc1809620c2b108c33730214`, 2026-09-15). - `ScoreCriteria` became a `readonly` tuple in 0.6.0; in 0.5.7 score criteria were a dictionary keyed by integers. See [JavaScript SDK changelog](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-changelog.md). - **Doc-vs-source:** `Models` is published under "Interfaces" but declared `export class Models` in `src/resources/models.ts` (re-exported as `export type { Models }`, so only the type is public). - **Doc-vs-source (cosmetic):** the docs render `ChoiceCriteria`'s index signature as `EntryType` where source writes `Description`, and expand the mapped-type keys of `ChoiceResponse.probabilities` / `ScoreResponse.probabilities` to `string | number | symbol` and `number | \`${number}\`` respectively. These are typedoc expansions of the same types. ## Related - [JavaScript/TypeScript SDK: install, client, choice/score/noul](https://jevwiki.ai/raw/wiki/reference/javascript-sdk.md) — client, builders, examples - [JavaScript SDK error classes, RetryPolicy, RequestOptions](https://jevwiki.ai/raw/wiki/reference/javascript-sdk-errors.md) — `RetryPolicy`, `RequestOptions`, error classes - [OpenAPI component schemas](https://jevwiki.ai/raw/wiki/reference/openapi-schemas.md) — the same shapes on the wire - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — `POST /v1/systemone`, `GET /v1/models` - [Primitives: Choice, Score, Noul](https://jevwiki.ai/raw/wiki/concepts/primitives.md) — what Choice, Score and Noul mean - [Python SDK question types (Noul, Choice, Score)](https://jevwiki.ai/raw/wiki/reference/python-sdk-questions.md) — Python counterparts ## Sources - raw/docs/sdk__javascript__api.md (https://docs.typesafe.ai/sdk/javascript/api) - raw/docs/sdk__javascript__api__interfaces__*.md (https://docs.typesafe.ai/sdk/javascript/api/interfaces/*) - raw/docs/sdk__javascript__api__type-aliases__*.md (https://docs.typesafe.ai/sdk/javascript/api/type-aliases/*) - raw/docs/sdk__javascript__api__variables__ENV.md, __LOG_LEVELS.md, __VERSION.md - raw/github/typesafe-sdk-js/src/types.ts, src/env.ts, src/logging.ts, src/api-promise.ts, src/resources/models.ts (commit 66880ccded6cb642dc1809620c2b108c33730214) --- title: "Legal: MCA, DPA, privacy, data retention" type: reference tags: [legal, privacy, data-retention, dpa, acceptable-use] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/legal.md - raw/site/typesafe-ai-legal_mca.txt - raw/site/typesafe-ai-legal_data-processing.txt - raw/site/typesafe-ai-legal_privacy-policy.txt jev_version: "jev-1.13.0" summary: "Developer-facing summary of TypeSafe's MCA, DPA, and Privacy Policy: no training on Input, telemetry carve-out, retention, sub-processors, acceptable use, no uptime SLA." --- # Legal: MCA, DPA, privacy, data retention > **TL;DR** TypeSafe states it does not train on customer Input (Privacy Policy; MCA §4.1 qualifies this with "without Customer's prior consent"), but **Telemetry** — logs, hashes, summary statistics, classifications, metrics — may be processed without restriction (MCA §4.3). There is **no uptime SLA or service credit**, only a "performs materially as described in its Documentation" warranty (MCA §9.1). TypeSafe has **no obligation to retain your data** and may delete it at any time (MCA §10.3). Sub-processors are not enumerated in the DPA; they live at `https://trust.typesafe.ai/subprocessors`. **This page is not legal advice.** It summarises what the documents say, with section citations, so an engineer can decide what to send and what to ask legal about. Read the originals before relying on any of it. ## The documents | Document | URL | "Last updated" | Captured file | |---|---|---|---| | Master Customer Agreement (MCA) | https://typesafe.ai/legal/mca | Aug 27, 2026 | raw/site/typesafe-ai-legal_mca.txt | | Data Processing Addendum (DPA) | https://typesafe.ai/legal/data-processing | Apr 24, 2026 | raw/site/typesafe-ai-legal_data-processing.txt | | Privacy Policy | https://typesafe.ai/legal/privacy-policy | Nov 19, 2025 | raw/site/typesafe-ai-legal_privacy-policy.txt | Naming note: raw/docs/legal.md calls the second document a "Data Processing **Agreement**"; the document itself is titled "Data processing **addendum**" and defines itself as "DPA". Same URL. The DPA "forms part of the Agreement" and is incorporated into the MCA by reference (MCA §4.4). Where the DPA and the rest of the Agreement conflict, **the DPA controls** (DPA §1.3). Where the MCA body and the Order conflict, **the Order controls** (MCA §15.14). Entity: TypeSafe AI, Inc. Notices address: 255 California St, Suite 1300, San Francisco, CA 94117, or sales@typesafe.ai (MCA §15.5). ## What is covered: Services, Web Interface, API MCA §1 (Overview) defines the **Web Interface** as "the TypeSafe-hosted web interface available at **https://console.typesafe.ai**" and the **API** as "the TypeSafe-hosted application programming interface"; together they are the **Services**. That console URL is the one named in the MCA. See [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md). Key defined terms (MCA §4.1, §4.3): | Term | Definition | |---|---| | **Input** | "any data, files, queries, and other materials that Customer (including Customer Users or End Users) inputs or makes available to TypeSafe" — your `state` and `questions`. | | **Output** | outputs generated from the Service and delivered to Customer — your `answers`. | | **Customer Data** | Input + Output. | | **Telemetry** | "information generated in connection with the Services, such as technical logs, hashes, summary statistics and classifications, metrics, and learnings related to Customer's use of the Services." | ## Training on customer data | Source | Statement | |---|---| | MCA §4.1 | The license to process Customer Data "does not grant TypeSafe the right to, and TypeSafe will not, include Customer Data in a dataset used to train (i.e., to modify the model weights of) any artificial intelligence or machine learning models **without Customer's prior consent**." | | Privacy Policy, "Services" | "We will not train or fine tune any artificial intelligence or machine learning models on your prompts or other Input." | | Privacy Policy, "How We Use…" | "We (1) will not train or fine tune any artificial intelligence or machine learning models on Input, and (2) will not disclose any Input to a third party other than our service providers." | | raw/docs/models.md | "Jev is not trained on customer requests or responses." Also: "Jev is not fine-tuned or LoRA-adapted with customer data… the same weights serve every account." | **Tension to note:** the MCA leaves a consent-gated path open ("without Customer's prior consent"), while the Privacy Policy and the docs state the commitment flatly. Both are cited above; the MCA is the contract. **The Telemetry carve-out is the practical caveat.** MCA §4.3: "TypeSafe may Process Telemetry without restriction, including to improve the Services or TypeSafe's other products and services." Telemetry explicitly includes "summary statistics and classifications" and "learnings" derived from your use. MCA §4.1 also grants the right to use Customer Data "to derive and generate Telemetry". Telemetry survives termination (MCA §10.4). Ownership: TypeSafe "does not claim ownership of Input and… disclaims ownership of Output," and assigns to Customer any right it has in Output (MCA §4.2). Customer retains IP in Input (MCA §11). Feedback and bug reports you send may be used "without restriction or obligation" (MCA §11). ## Data retention | Rule | Source | |---|---| | "TypeSafe will be under no obligation to store or retain Customer Data and may delete Customer Data at any time in its sole discretion" — both during the Term and after it ends. | MCA §10.3 | | Confidential Information "may be retained in TypeSafe's standard backups notwithstanding any obligation to delete," still subject to confidentiality. | MCA §10.3 | | Customer Personal Data "will be retained for as long as necessary taking into account the purpose of the Processing, and in compliance with applicable laws." | DPA Schedule I §8 | | "We retain personal data about you for as long as reasonably necessary to provide you with the Services, or otherwise in support of our business or commercial purposes." Deletion on request unless law requires retention. | Privacy Policy, "Retention" | | **Zero data retention (ZDR)** is offered "for enterprise customers"; contact **privacy@typesafe.ai**. | raw/docs/legal.md; raw/docs/models.md | Neither the MCA nor the DPA states a default retention **period** for Input or Output. If you need a number, ZDR or an Order term is the lever (inferred). ## Sub-processors | Point | Detail | |---|---| | Authorization | Customer gives **general authorization** for TypeSafe to engage sub-processors (DPA §3.1). | | List | Not enumerated in the DPA. Published at **https://trust.typesafe.ai/subprocessors**. That page is not captured in `raw/`, so this wiki cannot list the sub-processors. | | Flow-down | TypeSafe contracts each sub-processor to "substantially as protective" obligations and remains responsible for their acts and omissions, subject to the MCA liability cap (DPA §3.1). | | New sub-processors | "Reasonable advance notice" before granting access; Customer may object within **15 days** on reasonable privacy or security grounds, and the parties "work together in good faith" (DPA §3.2). No termination right is granted for an unresolved objection. | | Subcontracting generally | MCA §15.10 permits subcontractors; MCA §14.2 allows disclosure of Confidential Information to them. | The Privacy Policy separately names **Google Analytics** as an analytics partner for the website/Services and mentions a third-party payment processor for payment data. ## Security, incidents, audits | Topic | Commitment | Source | |---|---|---| | Security measures | "Reasonable and appropriate technical and organization security measures"; may be updated provided they do not "materially decrease the overall security". Described on the Trust Center at https://trust.typesafe.ai/. | DPA §5.1, Schedule I §11 | | Security incident notice | "Without undue delay and in any case **within 72 hours** after becoming aware" of accidental or unauthorized access to, disclosure or use of Customer Personal Data. | DPA §5.2 | | Audit rights | On written request, **no more than once every 12 months**, at Customer's sole cost, during business hours, under mutually agreed scope; results usable only for regulatory audit or DPA-compliance purposes. | DPA §5.3 | | Credentials | API key (API) and username/password (Web Interface) are "Access Credentials"; Customer must keep them confidential, is responsible for everything done with them, and must notify TypeSafe of any compromise. | MCA §2.4 | | Security disclaimer | "Because no electronic transmission or storage of data can be entirely secure, we can make no guarantees as to the security or privacy of your data." | Privacy Policy, "Security" | ## Roles, transfers, and jurisdiction (DPA) | Item | Value | |---|---| | Roles | Customer is controller/business; TypeSafe is processor/service provider (DPA §1.1). | | CCPA | TypeSafe will not "sell" or "share" Customer Personal Data, and will not retain, use, or disclose it outside the direct business relationship or combine it with third-party personal data (DPA §2.2). | | Data subject requests | Forwarded to Customer; data subjects directed to Customer; reasonable assistance provided (DPA §4.1). TypeSafe may charge a reasonable fee for DPIA/regulator-consultation assistance (DPA §4.2). | | EU transfers | EU SCCs Module 2 (controller-to-processor), plus Module 3 where Customer is itself a processor; docking clause in, Clause 11(a) redress option struck; **governing law Ireland, courts of Dublin** (DPA §6.2). | | UK transfers | UK Addendum (ICO Version B1.0, in force 21 March 2022) (DPA §6.3). | | Swiss transfers | Swiss courts for Swiss-law disputes; Swiss-resident data subjects may sue in Switzerland (DPA §6.2). | | Supervisory authorities | Ireland (EEA), UK Information Commissioner (UK), Swiss FDPIC (Switzerland) (DPA Schedule I §10). | | Hosting location | "The Services are hosted in the United States" (Privacy Policy, "International Visitors"). | | Sensitive data | Schedule I §4 records sensitive data transferred as **N/A** — the DPA schedule does not contemplate special-category data. Plan accordingly before sending it as `state`. | | Data subjects / categories | "Customer and Customer's users"; content of the personal data "is determined and controlled by Customer"; transfers happen "on a continuous basis" (Schedule I §§2, 3, 5). | ## Acceptable use (MCA §2.3 License Restrictions) Customer will not, and will not let its Customer Applications or personnel: | # | Restriction (condensed; MCA §2.3) | |---|---| | (a) | Sell, lease, loan, distribute, sublicense, or otherwise offer the Services as a standalone service. | | (b) | Use the Services or any Output to **perform model distillation, train a model to imitate the output of the Services**, or develop a similar or competing product. | | (c) | Reverse engineer, decompile, disassemble, or derive source code, underlying data, ideas, algorithms, or structure. | | (d) | Modify or create derivative works of the Services. | | (e) | Remove or obscure proprietary notices. | | (f) | **Publish benchmarks or performance information about the Services.** | | (g) | Interfere with the operation of the Services. | | (h) | Bypass access restrictions or software protection mechanisms, or run security or vulnerability tests. | | (i) | Transmit viruses or other harmful materials. | | (j) | Take any action that risks harm to others or to the security, availability, or integrity of the Services. | | (k) | **Exceed any Usage Limits** (the limits set in the Order). | | (l) | Access the Services other than as expressly permitted, in accordance with the Documentation. | | (m) | Use the Services or Output in violation of law or third-party rights, or contrary to the Agreement or Documentation. | Two of these bite developers directly: **(f)** means publishing your own Jev benchmark numbers is a contractual breach absent permission — relevant when writing up evaluations, and worth contrasting with TypeSafe publishing its own workflow evals ([Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md)). **(k)** ties the documented rate limits ([Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md)) to the contract; exceeding Usage Limits is also a suspension trigger and an "Excluded Claim" that escapes the liability cap (MCA §§6, 12.3). Other obligations: only employees or independent contractors may use the Web Interface (MCA §2.4); Customer is responsible for Input's content and accuracy and for all necessary rights, consents, and notices (MCA §5); export controls apply and ITAR-controlled information must not be submitted (MCA §15.12). **Suspension** (MCA §6): immediate suspension is permitted for breaches of §2.3, §2.4, §5, or the Promotional Credits terms; payments 30+ days overdue; legal changes; or actions risking harm to other customers or the Services. Prior notice "where practicable"; access is restored once the issue is resolved. ## SLA, uptime, and warranties **There is no uptime SLA, availability percentage, or service-credit mechanism in any of the three documents.** What exists instead: | Item | Detail | |---|---| | Service Warranty (§9.1) | "The Services will perform materially as described in its Documentation." Excludes misuse, third-party platforms, and use contrary to the Documentation. | | Remedy (§9.2) | Written claim within 30 days of discovery; TypeSafe uses reasonable efforts to correct; if not corrected within 30 days of the claim, either party may terminate and TypeSafe refunds pre-paid unused Fees. This is the **exclusive remedy**. | | Disclaimer (§9.3) | Services are "AS IS" and "AS AVAILABLE"; TypeSafe "does not warrant that Customer's use of the Services will be uninterrupted or error-free," nor that it will maintain Customer Data without loss; no liability for outages arising from the internet or from Customer's own violations or Usage Limit enforcement. Also: Output "may be inaccurate or erroneous," Customer is responsible for independently evaluating Output, and Output may be identical to other customers'. | | Support (§3) | "Commercially reasonable efforts" per TypeSafe's standard support policies. Request support at **support@typesafe.ai**. No response-time commitment. | | Updates (§2.5) | TypeSafe may update the Services, possibly breaking your integration; "commercially reasonable efforts to provide advance notice" of materially adverse API updates. | Design consequence for agents and services built on Jev: treat `529 Overloaded` and `429` as expected, not exceptional ([HTTP status codes, rate limits, retry semantics](https://jevwiki.ai/raw/wiki/reference/rate-limits-and-errors.md)), and independently validate Output before acting on it ([Confidence vs probability](https://jevwiki.ai/raw/wiki/concepts/confidence.md)). ## Commercial terms worth knowing | Item | Detail (MCA) | |---|---| | Credits | Usage consumes TypeSafe-managed Credits; consumption rate "may vary based on account settings, including the model used". Credits are not refundable, transferable, or legal tender. Balance visible in your account (§8.2). | | Purchased Credits | Expire at the earlier of end of Term or **12 months after purchase**. With auto-refill opted in, the balance tops up automatically; without it, TypeSafe "may decline to generate Output" once Credits run out (§8.2(a)). | | Promotional Credits | Discretionary; consumed before Purchased Credits; creating multiple accounts to farm them is prohibited (§8.2(b)). | | Payment | US dollars; due within 30 days of invoice; 1.5%/month late charge; taxes excluded (§§8.1, 8.3, 8.4). | | Liability cap | Greater of 12 months of Fees paid, or **$50 USD**, except for Excluded Claims (§12.2, §12.3). Consequential damages waived (§12.1). | | IP indemnity | TypeSafe defends US patent/copyright/trademark/trade-secret claims against the Services as delivered — but **explicitly not Output** (§13.1, §13.5(e)). | | Governing law | Delaware; state and federal courts in Delaware (§15.2). Note this differs from the SCC governing law (Ireland) in the DPA. | | Amendments | TypeSafe may notify of updates; an updated MCA takes effect "at least 60 days after" notice, going forward (§15.7). | | Publicity | TypeSafe may name and logo you as a customer, and will stop on written request (§15.4). | | Term/termination | Runs with the Order; either party may terminate for uncured material breach after 30 days' notice, cessation of operations, or insolvency (§§10.1, 10.2). No refund of unconsumed prepaid amounts (§10.3). | ## Privacy Policy specifics (individuals, not just accounts) | Topic | Detail | |---|---| | Scope | typesafe.ai, the Playground ("web-based interface(s)"), the APIs, and linked services. | | Collected | Account info (name, email); Input; contact and communications data (including email open/click tracking pixels); job applications; payment data via a third-party processor; location inferred from IP; device info; usage info; cookies. | | Not done | No "sale" of personal data; no "sharing" for cross-contextual behavioral advertising; no training on Input; no disclosure of Input to third parties other than service providers. | | Disclosed to | Affiliates; vendors and service providers; analytics partners (Google Analytics); as required by law or legal process; in a merger or asset transfer; with consent. | | Do Not Track | Not honored ("there is no accepted standard"). | | Children | No knowing collection from anyone **under 18**; report to **privacy@typesafe.ai**. | | Changes | Revisions are effective when posted; no advance-notice commitment. | | Contact | The captured page's contact line reads "please email us at ." — the address is missing in the capture (raw/site/typesafe-ai-legal_privacy-policy.txt line 82-83). Use privacy@typesafe.ai (named for children's privacy) or hello@typesafe.ai (site footer). | Staleness note: the Privacy Policy is dated **Nov 19, 2025**, roughly ten months before the MCA (Aug 27, 2026) and before Jev's 2026-09-15 launch. It predates the current product surface. ## Quick answers for developers | Question | Answer | Cite | |---|---|---| | Will my prompts train the model? | No, per the Privacy Policy and raw/docs/models.md; the MCA phrases it as "not without Customer's prior consent". | Privacy Policy; MCA §4.1 | | Can TypeSafe learn from my usage anyway? | Yes — Telemetry (logs, hashes, summary statistics, classifications, metrics, "learnings") may be processed without restriction. | MCA §4.3 | | How long is my data kept? | No stated period; TypeSafe has no retention obligation and may delete at any time. ZDR is an enterprise option. | MCA §10.3; raw/docs/legal.md | | Who are the sub-processors? | Not listed in the DPA; see https://trust.typesafe.ai/subprocessors (not captured in `raw/`). | DPA §3.1 | | Is there an uptime SLA? | No. Only a "performs materially as documented" warranty with a correct-or-refund remedy. | MCA §§9.1–9.3 | | Can I publish my benchmark of Jev? | Not under the MCA as written — §2.3(f) prohibits publishing benchmarks or performance information about the Services. | MCA §2.3(f) | | Can I use Output to train my own model? | No — §2.3(b) prohibits distillation, imitation training, and building a competing product. | MCA §2.3(b) | | Can I send special-category personal data? | The DPA schedule records sensitive data as N/A; get contractual coverage first. | DPA Schedule I §4 | | Who do I contact? | support@typesafe.ai (support), sales@typesafe.ai (notices, higher limits), privacy@typesafe.ai (ZDR, privacy), hello@typesafe.ai (general). | MCA §§3, 15.5; raw/docs/legal.md | ## Related - [Models, aliases, pricing, rate limits, context](https://jevwiki.ai/raw/wiki/reference/models-and-pricing.md) — rate limits, credits-relevant pricing, ZDR pointer - [HTTP API: POST /v1/systemone and GET /v1/models](https://jevwiki.ai/raw/wiki/reference/http-api.md) — what actually leaves your process as Input - [State: what you send Jev](https://jevwiki.ai/raw/wiki/concepts/state.md) — deciding what to put in `state` - [console.typesafe.ai (console + playground)](https://jevwiki.ai/raw/wiki/entities/typesafe-console.md) — the Web Interface named in MCA §1 - [TypeSafe AI (company)](https://jevwiki.ai/raw/wiki/entities/typesafe-ai.md) — the company - [Workflow evals: how TypeSafe measures Jev](https://jevwiki.ai/raw/wiki/concepts/workflow-evals.md) — TypeSafe's own published benchmarks ## Sources - raw/docs/legal.md (https://docs.typesafe.ai/legal) - raw/site/typesafe-ai-legal_mca.txt (https://typesafe.ai/legal/mca), last updated Aug 27, 2026 - raw/site/typesafe-ai-legal_data-processing.txt (https://typesafe.ai/legal/data-processing), last updated Apr 24, 2026 - raw/site/typesafe-ai-legal_privacy-policy.txt (https://typesafe.ai/legal/privacy-policy), last updated Nov 19, 2025 - raw/docs/models.md (https://docs.typesafe.ai/models) — "Data handling" section --- title: "Migrating from /preview/evaluation to /v1/systemone" type: reference tags: [migration, v1, breaking-changes, http-api, python-sdk] created: 2026-09-17 updated: 2026-09-17 confidence: high sources: - raw/docs/migrating-to-v1.md jev_version: "jev-1.13.0" sdk_python: "0.6.0" summary: "Every delta between the preview evaluation endpoint and the stable v1 API, with before/after examples, plus the typesafe-client to typesafe-sdk rename table." --- # Migrating from /preview/evaluation to /v1/systemone > **TL;DR** `POST /preview/evaluation` is replaced by `POST /v1/systemone`. Auth is unchanged. `document` → `state`, the `prompts` array → a `questions` map, `options`/`levels` → a unified `criteria` per type, the `responses` array → an `answers` map, and the answer value fields are renamed (`probability` → `noul`, `chosen` → `choice`, `expectation` → `score`). `confidence` is computed differently, so re-tune any thresholds. This is a **breaking change**: the endpoint, the request shape, and the response shape all changed (raw/docs/migrating-to-v1.md). Auth is unchanged — keep sending `Authorization: Bearer ` and `Content-Type: application/json`. ## At a glance | Area | Preview | v1 | |---|---|---| | Endpoint | `POST /preview/evaluation` | `POST /v1/systemone` | | Questions | `prompts` array (each carries a `key`) | `questions` map (the key is the id) | | Descriptors | per-type: `criteria`, `options`, `levels` | unified `criteria` per type | | Answers | `responses` array (same order) | `answers` map (keyed by your id) | | noul value | `probability` | `noul` | | choice value | `chosen` | `choice` | | score value | `expectation` | `score` | | choice `probabilities` | array of `{ option, probability }` | map of `option → probability` | | score `probabilities` | — (not returned) | map over levels (new in v1) | | Confidence | old computation | new computation | | Usage | `usage.billing_units` placeholder | `usage.input_tokens` / `usage.output_tokens` | | Input field | `document` | `state` | | Python SDK | `typesafe-client` | `typesafe-sdk` (new package) | (Table reproduced from raw/docs/migrating-to-v1.md.) ## 1. Endpoint rename `evaluation` became `systemone`. ```diff - POST https://api.typesafe.ai/preview/evaluation + POST https://api.typesafe.ai/v1/systemone ``` ## 2. `prompts` array becomes a `questions` map In preview, you sent a `prompts` **array** where each item carried its own `key`, and answers came back in the same order. In v1, you send a `questions` **map**: the map key is an id of your choice, and answers come back mapped to the same id. ```jsonc // preview — POST /preview/evaluation { "model": "jev-latest", "document": "Sample document", "prompts": [ { "key": "test_noul", "type": "noul", "instructions": "Test instructions" } ] } ``` ```jsonc // v1 — POST /v1/systemone { "model": "jev-latest", "state": "Sample document", "questions": { "test_noul": { "type": "noul", "instructions": "Test instructions" } } } ``` Migration consequence: any code that relied on positional ordering of `responses` must switch to key lookup. The keys are yours and are "not sent to the underlying model" (raw/docs/api.md). ## 3. Unified `criteria` per question type Every question type now describes itself with a field named `criteria`. The shape differs by type: | Type | Preview field | v1 `criteria` shape | Notes (verbatim where quoted) | |---|---|---|---| | Noul | none | `criteria?: { true?, false? }` | An optional object describing the two outcomes. "New feature in v1!" | | Choice | `options`: array of `{ option, description? }` | `criteria: {