Agents: read the raw Markdown of this page, or start at llms.txt.
Playbook for LLM agents building with Jev
TL;DR Jev answers narrow, typed questions about one
state: a Noul returns one probability (noul); a Choice or Score returns itschoice/scoreplusprobabilitiesandconfidence. It never generates text, does arithmetic, or picks its own next action. Decompose the job into atomic questions, filter the state to what they need, ask them all in onePOST /v1/systemone, and branch in code on the values and onconfidence. Everything deterministic stays in code. No TypeSafe key yet? Direct signup reopened on 2026-09-27, with no free credits for new signups; Step 4 also gives the gateway route. Links written[[dir/slug]]resolve tohttps://jevwiki.ai/raw/wiki/dir/slug.md. Longer than most guides on purpose: it is the one-stop entry page for coding agents.
Official skill. Building inside a codebase? Also give your coding agent TypeSafe's agent skill (Claude Code:
claude plugin marketplace add typesafe-ai/skills, thenclaude plugin install typesafe@typesafe-ai; other agents:npx skills add typesafe-ai/skills --skill typesafe-ai). It points the agent at TypeSafe's live docs, which win any conflict; this wiki adds the contracts in one place, community evidence and the consult. Ask the user before installing anything into their project (The typesafe-ai agent skill and Claude Code plugin).
Step 0 — Is Jev the right tool?
Start from the behavior wanted: what will the app show, select, change, or hand off? (The typesafe-ai agent skill and Claude Code plugin). Place each decision below; #n = failure mode n of nine in Jev 1.13 jaggedness: known failure modes.
| Task shape | Verdict | Why |
|---|---|---|
| Classify into known categories | Jev (Choice questions) | Known answer space; code consumes it (System One Models) |
| Detect whether a property holds | Jev (Noul (yes/no) questions) | The probability is the signal |
| Rate on a rubric describable level by level | Jev (Score questions) | Ordered, thresholdable, comparable |
| Route to a handler, queue, or model | Jev + code | Intent routing, Confidence-gated routing |
| Rank or shortlist on several dimensions | Jev + code | Composite scoring; weights live in code |
| Verify another model's output, citations, tool calls | Jev | "Universal Verification" (Use-case map by industry); Cookbook: Double-checking citations |
| Remember facts across calls (per customer, account, device) | Jev gate + code store | A Noul decides what to save; code adds saved items to later state (Cookbook: Simple memory system) |
| Select a value already in the text | Jev, Choice over candidates | Extraction becomes selection (Cookbook: Pre-parsed value extraction) |
| Score millions of records cheaply | Jev | $0.042/Mtok input, output free (Models, aliases, pricing, rate limits, context) |
| Write a reply, summary, explanation, or code | LLM | "jev-1.13 is not trained to generate text" (#9) |
| Decide its own next action in a loop | LLM agent | System One "does not generate code or choose its own next action" (How to build software with System One) |
| Power the coding agent writing this integration | LLM | Not a drop-in (Jev with coding agents: not a drop-in for the LLM behind Claude Code, Cursor, Copilot); install the skill instead |
| Multi-hop reasoning over inferred facts | LLM, or decompose | Indirection costs accuracy (#4) |
| Arithmetic, sums, counting, percentages | Code | "Jev is not a calculator" (#2) |
| Date ordering, durations, windows, weekdays | Code | Dates read as text (#3); extract parts, compare in code (Cookbook: Date extraction) |
| Exact lookups, regex matches, status checks, thresholds | Code | "Use code when you can" (How to build software with System One step 1) |
| Audio, video | Pre-process to text | Not supported (State: what you send Jev) |
| Images: what is shown, does it match, where is it | Pre-process to text for production; Jev images or box only for prototypes |
Images (both versions) and box (Jev 1.14 only, per raw/docs/images.md) are experimental behind TypeSafe-Danger-Zone-Images: true; TypeSafe: "aren't yet up to our standards to call ready for production" (raw/docs/images.md; Images and assets (experimental), Box questions (experimental)). Tell the user it is experimental before proposing it |
state over the 64k / 32k limits |
Filter or split | Long context (TypeSafe-Danger-Zone-Long-Context: true, 262k) is experimental and "slower and less accurate" (Models, aliases, pricing, rate limits, context) |
Also avoid: reconstructing an exact number by interpolating between Score levels; double negatives; a huge state of material the question does not need (#5). When a rule, embedding, trained classifier or chat model beats Jev: When not to use Jev: rules, embeddings, trained classifiers, small and frontier LLMs; measured comparisons against small, fast and local models: Head-to-head: Jev vs small, fast and local models; other vendors' decision models: Rival decision models: Clef, Liquid d1, GLiDE, Drex and other non-Jev System One models; reports where Jev was given the wrong job or options that did not fit: Failure reports: wrong role, or options that don't fit (all community tier). Non-English (incl. CJK) is accepted but less accurate (Models, aliases, pricing, rate limits, context).
Already on Zapier, n8n, LangChain, Spring AI, the Vercel AI SDK, Mastra, LiteLLM, BAML, DSPy, Cloudflare Workers AI, Netlify, Vercel, OpenRouter, Fly.io, OpenCode Zen or Pydantic AI? Read Framework integrations: Pydantic AI, LangChain, Spring AI, Vercel AI SDK, eve, LiteLLM, BAML, TanStack AI, DSPy, Langfuse and other framework-shipped Jev support (frameworks), Apps with a built-in Jev option (apps such as n8n, Langfuse, MLflow with a built-in Jev option) or Platforms and gateways: Zapier, Cloudflare, Netlify, Vercel AI Gateway, OpenRouter, Pydantic AI Gateway, Opper, Fly.io, OpenCode Zen and other hosted routes to Jev (hosted routes) before writing a client: the platform may already wrap Jev, with its own key, billing and deviations from TypeSafe's docs (community tier: vendor pages checked against the docs; TypeSafe's docs win). Community MCP servers, skills and connectors: Tools and integrations hub: MCP servers, plugins and connectors (hub); unofficial SDKs by language: Community SDKs and libraries.
Adding Jev to an agent as a gate or router? Wire it with Jev inside your agent harness: hooks, tools and fail-safes (which hook in Claude Code, Codex, Cursor, Pi or opencode; a complete gate in Python and TypeScript; deadlines and fail direction). Read the community evidence before you promise a better agent (community tier): whole-agent A/B tests mostly cut cost or context without raising task success (Head-to-head: Jev inside agents, routers and tool gates); the builds and their measured results (Builds: permission gates, approvals and model routers for agents); the safety-gate pattern, never the sole control (Patterns: agent internals, routing, gates, context and memory P03); existing gates, hooks and injection screens with their fail modes (Tools: guardrails for agents (tool-call gates, permission hooks, injection screens, rule checks)).
Step 1 — Decompose the job into questions
"Probably the most important concept" (How to build software with System One step 4).
- List the decisions. Each is a code rule or a judgment; control flow, rules, and side effects stay in code.
- Split each judgment until it tests one property you can name. "Rate this startup pitch" becomes market size, technical feasibility, differentiation, weighted in code (Primitives: Choice, Score, Noul).
- Pick a primitive (Choosing between Choice, Score, Noul): unordered options → Choice; described spectrum → Score; clean yes/no → Noul; a count → one Noul per item plus
sum()in code; free text → candidates proposed in code, a Choice picks one. - Ask each decision one way. Structural invariants are not guaranteed: a Noul and a yes/no Choice on the same text returned
0.22vsprobabilities["yes"] = 0.01; a question plus its negation summed to1.19(TypeSafe's jaggedness page until 2026-10-02). Within one Noul, "no" is 1 −noul; never swap in a differently worded question's result (such as a negation) for it, or reuse a Noul threshold on a Choice. Enforce identities, totals, mutual exclusion in code. - Add speculative questions. Parallel, near-free in latency (Speculative fan-out); state each premise explicitly, ignore answers on branches not taken.
Step 2 — Shape the state
state is the single input every question in the request sees (State: what you send Jev).
- Shapes: string, JSON object, or array of text values only. Prefer an object with descriptive keys.
- Budgets: 64k tokens for
stateplus all questions; 32k forstateplus the single longest question. Under 64k does not imply under 32k (Models, aliases, pricing, rate limits, context). - Filter first. Irrelevant detail lowers accuracy and hides why answers are wrong (#5). Filter in code, else with a relevance Noul (Cookbook: Classifying RAG passages).
- Pre-parse numbers and dates into a value or named bucket; semantic beats numeric representations (Writing instructions and criteria that Jev reads correctly).
- Point at fields with backticked paths, backticks included:
`ticket.messages[0].text`. - Extra questions are cheap; extra state is not.
Step 3 — Write instructions and criteria
Full guide: Writing instructions and criteria that Jev reads correctly. Key rules:
- Literal reading. Jev answers what you wrote, not what you meant; any "but I meant…" belongs in
instructionsor a criteria boundary case. - Question ids are never sent to the model; write the complete question (HTTP API: POST /v1/systemone and GET /v1/models).
- Choice: full option list (up to 255 per Choice, stated in the API reference and the Choice page: HTTP API: POST /v1/systemone and GET /v1/models, Choice questions; ~240 practical per Cookbook: Classification using confidence). Add
other/none of the aboveif coverage is uncertain; confusable options can take an object instead of a string; names such aswhat/not_for/examplesare a convention you choose, not API fields (Structured instructions, options, levels, criteria). - Score:
criteriais an ordered array, low to high, 2 to 10 levels, each a concrete situation, not a degree (Score questions). The docs say a Score should have at least two levels; the Python SDK (0.7.3 and later) accepts one, the JS SDK rejects fewer than two (0.7.0: a literal list of fewer than two is a type error, a list built at runtime makessystemOne()reject; 0.6.0 threw; raw/github/typesafe-sdk-js/src/questions.ts), and the OpenAPI schema setsminItems: 1. Use two or more.["0","1","2"]with "rate 0 to 2" scored 0.57 at confidence 0.35; described levels scored 0.0 at 1.0. One dimension per Score. - Noul: keep
truemeaning yes; an inverted Noul performs worse (#7). Rewrite double negatives positively. - Align criteria with the instruction; contradiction is its own failure mode.
Step 4 — Call it
Access (signup state as of 2026-09-27, the last change on record).
- Official docs: create a key in the console at
https://console.typesafe.ai/keys(the quickstart and agent-skill pages agree on this path since 2026-09-21). - Direct signup is open again, without free credits: TypeSafe said on X on 2026-09-27 that "signups are open" (closed since at least 2026-09-24) and that "new signups no longer get free credits" (console.typesafe.ai (console + playground)). Tell the builder the first call is billed.
- No TypeSafe account? Use a gateway key and point the SDK at the gateway with
base_url(Python),baseURL(JS) orTYPESAFE_BASE_URL. The Python usage guide documents OpenRouter (https://openrouter.ai/api, model~typesafe/jev-latest, OpenRouter key) Vercel AI Gateway (https://ai-gateway.vercel.sh/typesafe, modeltypesafe-ai/jev,AI_GATEWAY_API_KEY) and, since 2026-09-29, Pydantic AI Gateway (https://gateway-us.pydantic.dev/proxy/typesafe, modeljev-latest,PYDANTIC_AI_GATEWAY_API_KEY; bring your own key, so it still needs a TypeSafe key held in the Gateway, per Pydantic's article): Python SDK internals: headers, key validation, gateways and base URLs, logging, forward compatibility, dependencies, migration notes "AI gateways"; the same values from JS are inferred, untested (JavaScript SDK internals: constructor options, headers, retries and timeouts, env vars, logging, gateways, forward compatibility, migration notes). One vendor documents its own SDK-compatible base URL that TypeSafe's docs do not list: Opper (https://api.opper.ai/v3/compat, Opper key, paid plan, no TypeSafe account needed; Python SDK internals: headers, key validation, gateways and base URLs, logging, forward compatibility, dependencies, migration notes). Other hosted routes, each with its own key, billing, limits and data terms: Platforms and gateways: Zapier, Cloudflare, Netlify, Vercel AI Gateway, OpenRouter, Pydantic AI Gateway, Opper, Fly.io, OpenCode Zen and other hosted routes to Jev (community tier). The wiki's exclusion policy: a free or keyless "Jev API" run on someone else's key is not a route, unless it is a vendor gateway whose own docs list Jev with its endpoint, price and data terms (OpenCode Zen, free tier included); the Warnings block on Warnings: not-Jev services, key safety, look-alikes and install names lists the ones found. - Model IDs differ per gateway, and not every route can pin a version. OpenRouter routes
jev-1.13astypesafe/jev-1.13andjev-latestas~typesafe/jev-latest; Cloudflare Workers AI takes onlystateandquestions, so it has no version pin. On a gateway, log the responsemodelto see what answered.
Environment variables read by both SDKs (TYPESAFE_* environment variables across SDKs):
| Variable | Default | Effect |
|---|---|---|
TYPESAFE_API_KEY |
none, required | Sent as Authorization: Bearer <key> |
TYPESAFE_BASE_URL |
https://api.typesafe.ai |
API root |
TYPESAFE_DEFAULT_MODEL |
jev-latest |
Used when a call omits model |
TYPESAFE_LOG_LEVEL |
JS warn; Python unset |
debug logs request and response bodies, unredacted |
GET /v1/models (client.models.list() in both SDKs) lists the model names and aliases your key may send (HTTP API: POST /v1/systemone and GET /v1/models). Since the 2026-10-24 capture both jev-latest (the SDK default) and jev-preview point to jev-1.14.0 (released 2026-10-14); jev-latest pointed to jev-1.13.0 until the 2026-10-21 capture, so unpinned code changed model with no deploy (Blog: Jev 1.14 (2026-10-14)). Both versions have the same price and default limits. Pin a versioned ID (jev-1.13.0 or jev-1.14.0; jev-1.13.0 keeps the pre-move model) if thresholds are tuned (direct API and SDKs; on a gateway, its own versioned ID where one exists); response model shows the version that answered (Models, aliases, pricing, rate limits, context).
Bind base URL, key and model ID together (one config entry per environment), and log the returned model on every call. Open replicas and "Jev-compatible" servers copy the wire shape; several accept jev-latest (some also jev-preview) and answer locally with no error, and the response model is whatever that server writes (inferred), so a pinned model ID alone does not prove you reached Jev. Changing only the base URL can send your TypeSafe key to another operator. Revalidate thresholds and confidence semantics per endpoint: most replicas compute confidence their own way (Open replicas and Jev-compatible servers, community tier). TypeSafe's captured docs mention no on-premises or self-hosted deployment (FAQ for agents and developers Q43).
curl
export TYPESAFE_API_KEY="..." # from console.typesafe.ai
curl -X POST https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<'EOF'
{
"state": {
"ticket_message": "I was charged twice for order A-104. Please refund the duplicate.",
"refund_policy": "Duplicate charges are eligible for a refund."
},
"model": "jev-latest",
"questions": {
"refund_requested": {
"type": "noul",
"instructions": "Does `ticket_message` request a refund?"
},
"department": {
"type": "choice",
"instructions": "Which team should handle `ticket_message`?",
"criteria": {
"billing": "Charges, invoices, refunds, subscriptions",
"technical": "Bugs, outages, integrations",
"other": "Anything else"
}
},
"frustration": {
"type": "score",
"instructions": "How frustrated does the customer appear in `ticket_message`?",
"criteria": [
"Calm, just stating facts",
"Frustrated but civil",
"Very angry, strong language"
]
}
}
}
EOF
The response is {model, answers, usage}, with answers keyed by your question ids. TypeSafe's own example of a Score answer, from the API reference (your numbers will differ):
{
"model": "jev-1.13.0",
"answers": {
"frustration": {
"type": "score",
"score": 1.05,
"legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" },
"probabilities": { "0": 0.0, "1": 0.95, "2": 0.05 },
"confidence": 0.92
}
},
"usage": { "input_tokens": 304, "output_tokens": 18 }
}
A Noul answer is {"type": "noul", "noul": 0.95}; a Choice answer carries choice, probabilities keyed by option name, and confidence (same reference). Score legend and probabilities keys are strings on the wire ("0", "1"); the Python SDK turns them into int keys (legend[0]); the JS SDK keeps the wire's keys and, for a fixed rubric, types them as "0", "1", ... (HTTP API: POST /v1/systemone and GET /v1/models, Python SDK responses, answers, usage, models).
Python — typesafe-sdk 0.7.x, sync (written for 0.7.4; 0.7.5 only adds default zstd compression underneath it)
# pip install typesafe-sdk (import name: typesafe_sdk; requires Python >= 3.10)
from typesafe_sdk import Choice, Noul, Score, TypeSafeAPIError, TypeSafeClient
STATE = {
"ticket_message": "I was charged twice for order A-104. Please refund the duplicate.",
"refund_policy": "Duplicate charges are eligible for a refund.",
}
QUESTIONS = {
"refund_requested": Noul(instructions="Does `ticket_message` request a refund?"),
"department": Choice(
instructions="Which team should handle `ticket_message`?",
criteria={
"billing": "Charges, invoices, refunds, subscriptions",
"technical": "Bugs, outages, integrations",
"other": "Anything else",
},
),
"frustration": Score(
instructions="How frustrated does the customer appear in `ticket_message`?",
criteria=[
"Calm, just stating facts",
"Frustrated but civil",
"Very angry, strong language",
],
),
}
try:
with TypeSafeClient() as client: # reads TYPESAFE_API_KEY; defaults to jev-latest
response = client.system_one(state=STATE, questions=QUESTIONS, model="jev-1.13.0")
except TypeSafeAPIError as error: # HTTP error after the SDK's retries
print(f"API error {error.status} (request {error.request_id}):", error.body)
raise
print(response.model, response.usage.input_tokens)
print(response.answers["refund_requested"].noul)
print(response.answers["department"].choice, response.answers["department"].confidence)
print(response.answers["frustration"].score, response.answers["frustration"].legend)
Python — async
import asyncio
from typesafe_sdk import AsyncTypeSafeClient, Noul
async def main() -> None:
async with AsyncTypeSafeClient() as client: # await client.aclose() if not using `async with`
response = await client.system_one(
state="Help! My payouts have been failing for 3 days.",
questions={"is_urgent": Noul(instructions="Does this convey urgency?")},
)
print(response.answers["is_urgent"].noul)
asyncio.run(main())
Build one client per process and reuse it (Python SDK: install, clients, system_one()).
TypeScript — @typesafe-ai/sdk 0.7.0
// npm install @typesafe-ai/sdk (Node >= 22 since 0.7.0; server-side only unless you opt into
// dangerouslyAllowBrowser, which exposes your key). Uses top-level await, so run it as an
// ES module (.mts, or "type": "module" in package.json).
import { APIError, choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient(); // reads TYPESAFE_API_KEY, TYPESAFE_BASE_URL, TYPESAFE_DEFAULT_MODEL
try {
const { answers, usage, model } = await client.systemOne({
state: {
ticketMessage: "I was charged twice for order A-104. Please refund the duplicate.",
refundPolicy: "Duplicate charges are eligible for a refund.",
},
model: "jev-1.13.0",
questions: {
refundRequested: noul("Does `ticketMessage` request a refund?"),
department: choice("Which team should handle `ticketMessage`?", {
billing: "Charges, invoices, refunds, subscriptions",
technical: "Bugs, outages, integrations",
other: "Anything else",
}),
frustration: score("How frustrated does the customer appear in `ticketMessage`?", [
"Calm, just stating facts",
"Frustrated but civil",
"Very angry, strong language",
]),
},
});
console.log(model, usage.input_tokens);
console.log(answers.refundRequested.noul);
console.log(answers.department.choice, answers.department.confidence);
console.log(answers.frustration.score, answers.frustration.legend);
} catch (err) {
if (err instanceof APIError) {
console.error(`API error ${err.status} (request ${err.requestId ?? "unknown"}):`, err.body);
} else {
throw err;
}
}
Answer types are inferred from the questions: answers.department.choice narrows to "billing" | "technical" | "other" (JavaScript/TypeScript SDK quick contract: install, client, choice/score/noul, answers, errors (the page a builder reads)). Since 0.7.0, usage.input_tokens and usage.output_tokens are typed number | null ("null when the API did not report it"); guard before summing them for cost. 0.7.0 also "stop[s] exporting request payload types": SystemOneRequestPayload is gone from src/types.ts, so code that imported it no longer compiles (raw/github/typesafe-sdk-js/src/types.ts at b844cd1). Both SDKs now zstd-compress bodies of 1 KiB or more by default; against a gateway or replica that rejects them, pass compression: false / compression=False (Running Jev in production: versioning, caching, retries, monitoring and fallbacks §4).
Step 5 — Use the answers
| Type | Read | Notes |
|---|---|---|
| Choice | choice, probabilities, confidence |
probabilities maps every option to 0–1, summing to ~1 |
| Score | score, legend, probabilities, confidence |
score may fall between levels; normalize score / (len(criteria) - 1) before combining rubrics of different lengths. Need one discrete level? Take the most probable level from probabilities (inferred): rounding score can land on a level neither peak supports (0.5 on level 0 and 0.5 on level 2 rounds to 1) |
| Noul | noul |
P(yes). No confidence field. 0.5 = equally likely, not "medium" |
Python: response.answers[...] is the mixed map; response.nouls / response.choices / response.scores are per-type views (Python SDK responses, answers, usage, models).
Confidence gating. Check the confidence floor before branching, then size each action's threshold to the cost of being wrong (Confidence-gated routing). Examples from the sources, not defaults:
< 0.5: route to a human, any action (Confidence vs probability).< 0.6: floor in the voice-banking example (Confidence-gated routing).>= 0.7: trust a Score before acting on its value (Confidence vs probability).< 0.75/< 0.8: route a topic Choice to human review (How to build software with System One).> 0.85: auto-approve a money transfer in the voice-banking example; below it, ask the user to confirm (Confidence-gated routing).> 0.9: on a high-stakes transfer, proceed with confirmation (confirm_then_execute); below it, ask the user to verify first (Confidence vs probability).>= 0.9: report the fine label, else fall back to the coarser one (Cookbook: Classification using confidence).
Tune on your labelled data (Testing and evaluating a Jev workflow); keep questions and thresholds in one reviewable file (The typesafe-ai agent skill and Claude Code plugin). Which signal gates best is per task: the docs leave room for other measures computed from probabilities (Confidence vs probability), and builders found cases where a stock confidence cut misfired (Failure reports: confidence misread and calibration, community tier).
Failure check, mandatory for a consequential gate (one that blocks, pays, deletes or sends): before building it, read Failure reports: confidence misread and calibration (on JevBench v1.4.2's sealed hard set, Jev's highest-confidence answers were right less than half the time: Eval boards: JevBench by version, Jevals.com, typed-decisions and other independent suites) and validate the cut on your own labels. Any other gate: check its threshold on your own labels before copying it.
Two cuts on a Noul gate. Noul has no confidence: act above a high cut, pass below a low one, and send the band between to review. The docs' starting point (since the 2026-10-24 capture) is 0.7 for yes and 0.3 for no, values between to a person, moved by the cost of a false yes or a missed yes, and "Avoid fitting thresholds closely to a handful of test cases" (Noul (yes/no) questions; raw/docs/primitives__noul.md). Cookbook: Guardrails for LLMs has the complete version (review_threshold and action_threshold per policy, in its routing code). To gate Nouls and Choices with the same code, the docs' confidence-style stand-in for a Noul is |2p − 1| (0 at noul = 0.5, 1 at 0 or 1; the Choice formula applied to a yes/no Choice) (Confidence vs probability).
Fan-out. One request for every question the decision tree could need: batching 13 questions about a 54k-character document was 12.2x cheaper and 10.0x faster than 13 single-question calls, answers unchanged (Cookbook: Parallel questions, Speculative fan-out).
Composite scoring. Normalize Scores to 0–1, weight in code; re-rank by changing a coefficient, not re-running inference. Weighted sums suit compensating preferences; an "any serious violation" rule needs separate conditions (Composite scoring).
State and question wording from the spam example in How to build software with System One; the weights are that page's.
from typesafe_sdk import Noul, TypeSafeClient
STATE = {
"message": {
"sender": {"display_name": "Acme Payroll", "email": "rewards@claim-bonus.example"},
"subject": "Urgent: claim your employee bonus",
"body": "You have been selected for a $1,000 bonus. Confirm your payroll password today to receive it.",
"links": [{"text": "Claim bonus", "url": "http://claim-bonus.example/acme"}],
}
}
QUESTIONS = {
"requests_credentials": Noul(
instructions="Does `message.body` ask the recipient to provide a password or other login credential?"
),
"sender_identity_mismatch": Noul(
instructions="Does the organization named in `message.sender.display_name` conflict with the domain in `message.sender.email`?"
),
"offers_unexpected_reward": Noul(
instructions="Does `message.body` claim the recipient received an unexpected prize, payment, or reward?"
),
}
with TypeSafeClient() as client:
response = client.system_one(state=STATE, questions=QUESTIONS, model="jev-1.13.0")
answers = response.answers
spam_risk = (
0.45 * answers["requests_credentials"].noul
+ 0.30 * answers["sender_identity_mismatch"].noul
+ 0.25 * answers["offers_unexpected_reward"].noul
)
print(f"spam_risk = {spam_risk:.2f}") # thresholds on this live in code; tune them on labelled mail
Step 6 — Handle errors and limits
| Status | Retry? | Action |
|---|---|---|
400 |
No | Since 2026-10-14 in the API reference: the body breaks a request rule (invalid UTF-8 or a BOM, more than 64 nesting levels, NaN/Infinity/1e400, a malformed compressed body), or max_tokens_exceeded (below). Images add their own 400 causes, including a missing images header (HTTP API: POST /v1/systemone and GET /v1/models) |
403, 404 (SDK error classes; not in the API reference's status table) |
No | Fix the key's access or TYPESAFE_BASE_URL |
413, 415 |
No | 413: body over 32 MiB; 415: unsupported Content-Encoding or two compression layers (raw/docs/api__errors.md) |
401 |
No | Check TYPESAFE_API_KEY and the Bearer prefix |
422 |
No | Body is {"detail": [{loc, msg, type, ...}]}; fix the field at loc |
400 with {"detail":{"error_type":"max_tokens_exceeded"}} |
No | Input over the context length (64k per request; 32k for state plus any one question). The status and max_tokens_exceeded are in TypeSafe's docs since 2026-10-14 ("With max_tokens_exceeded, the request is longer than the model's context length"; raw/docs/api__errors.md); the body shape is community-observed (unverified). Shorten or split state; a byte count is no safe proxy for tokens (Request mechanics: billing, limits, latency, calibration and stability, HTTP status codes, rate limits, retry semantics) |
408 (in the SDKs' retry set), 429, 5xx (incl. 529 Overloaded) |
Yes | Exponential backoff; honor retry-after-ms, then retry-after |
| Connection error / timeout | Yes | Retry; raise the client timeout if it recurs |
Both SDKs already retry {408, 429, 500–599} (2 retries, 500 ms backoff doubling to a 5,000 ms cap, 25% jitter) with a 10 s per-attempt timeout; details in HTTP status codes, rate limits, retry semantics. Python also has a 30 s total retry budget per call (RetryPolicy.timeout = 30.0; None disables it), checked before each retry: a retry whose delay would reach the budget is not attempted and the last error is raised, but an attempt already running is not cut, so it is no wall-clock cap (Python SDK retries, exceptions, constants; for a hard deadline see Jev inside your agent harness: hooks, tools and fail-safes Step 3). JS has no total retry budget: its timeout is per attempt, so pass an AbortSignal (signal in the per-call options) for a wall-clock ceiling; it cancels pending retries too (JavaScript SDK error classes, RetryPolicy, RequestOptions). Log x-typesafe-request-id (response.request_id / err.requestId) on every failure.
Limits and cost (Models, aliases, pricing, rate limits, context): rate limits are "set per organization" and shown in the console (console.typesafe.ai/rate-limits); either breach (tokens or requests per second) returns 429. Until the 2026-10-14 docs refresh the docs published 100K tokens/second and 80 requests/second for everyone (since 2026-10-02; 40/s from 2026-09-30; previously 250,000 tokens/second and 1,200 requests/minute). Treat 429 as normal; do not hardcode a client budget. Request body at most 32 MiB. Price: $42 per Btok / $0.042 per Mtok, input tokens only; output free. No uptime SLA (Legal: MCA, DPA, privacy, data retention). Every response carries usage.input_tokens: meter it for cost, and log it against the 64k / 32k budgets to see how close a growing state is getting.
Many calls at once. Cap requests in flight in your own code and let the SDK's retries absorb occasional 429s. A bounded-concurrency sketch with the async client (the cap is yours to choose, not a TypeSafe number):
import asyncio
from typesafe_sdk import AsyncTypeSafeClient, Noul
MAX_IN_FLIGHT = 8 # your choice; lower it if 429s persist
QUESTIONS = {"is_urgent": Noul(instructions="Does this convey urgency?")}
async def classify_all(texts: list[str]) -> list[float]:
gate = asyncio.Semaphore(MAX_IN_FLIGHT)
async with AsyncTypeSafeClient() as client:
async def one(text: str) -> float:
async with gate:
response = await client.system_one(state=text, questions=QUESTIONS, model="jev-1.13.0")
return response.answers["is_urgent"].noul
return await asyncio.gather(*(one(text) for text in texts))
print(asyncio.run(classify_all(["Help! My payouts have been failing for 3 days.", "Thanks, all sorted now."])))
Python errors subclass TypeSafeError; HTTP failures after retries raise TypeSafeAPIError (status, request_id), 429 raises TypeSafeRateLimitError (adds retry_after_ms), network failures raise TypeSafeAPIConnectionError / TypeSafeAPITimeoutError. Hierarchy and a complete catch block: Python SDK retries, exceptions, constants. JS: APIError (status, requestId, body), RateLimitError on 429 (adds retryAfterMs), APIConnectionError / APITimeoutError, APIUserAbortError when your signal fires (JavaScript SDK error classes, RetryPolicy, RequestOptions).
Step 7 — Test before shipping
- Consistency. Not deterministic: across 15 repeats one Noul's answers spanned
0.43to0.53, crossing 0.5 (Cookbook: Self-consistency — nouls); 2 of 8 Choice questions changed top label (Cookbook: Self-consistency — choices). - Held-out cases. Tune on one set, validate on another (Writing instructions and criteria that Jev reads correctly).
- Jaggedness edge cases. Regression-test literal reading, negation, numbers, dates, adversarial content, and Choice option order: reorder the options and check the answer holds (#8) (Jev 1.13 jaggedness: known failure modes). Put untrusted text in
state, not spliced into the instruction string (inferred; untested as an injection defence); community injection results and screens (none proves a defence): Head-to-head benchmarks: security (phishing, spam, injection, vulnerable code), Tools: guardrails for agents (tool-call gates, permission hooks, injection screens, rule checks). - Baseline against an LLM on the same code. system-one-adapter: LLM-backed drop-in for TypeSafeClient answers the same
typesafe_sdkquestions with an OpenAI, Anthropic or Gemini model, so you can compare cost, speed and accuracy without rewriting the integration. - Method, harness, legal caveat: Testing and evaluating a Jev workflow. Before real users (versioning, caching, retries, monitoring, fallbacks): Running Jev in production: versioning, caching, retries, monitoring and fallbacks.
Copy-paste checklist
- Rules, sums, date comparisons, exact lookups in code.
- Each question tests one named property.
- Each decision asked one way; invariants enforced in code.
-
stateis an object with descriptive keys, filtered, under 64k / 32k tokens. - Questions point at state with backticked paths (
`ticket.messages[0].text`). - Choice has a
none/otheroption; Score has 2–10 situation levels, one dimension; Noultruemeans yes. - All questions for one state in one request (a second only if it depends on an answer).
- Access route checked: an existing TypeSafe key, or a gateway key plus
TYPESAFE_BASE_URL(direct signup open since 2026-09-27, no free credits; console.typesafe.ai (console + playground)). -
TYPESAFE_API_KEYset; key never shipped to a browser. - A versioned ID (
jev-1.13.0orjev-1.14.0) pinned if thresholds tuned (or the gateway's versioned ID; Cloudflare Workers AI cannot pin); base URL, key and model ID bound together;response.modellogged (a replica can answer to Jev's IDs: Open replicas and Jev-compatible servers). - Confidential or regulated data: read Legal: MCA, DPA, privacy, data retention first (no default retention period stated; ZDR for enterprise customers via sales@typesafe.ai; a gateway adds its own data terms).
-
confidence(or another measure fromprobabilities, chosen per task) checked before branching onchoice/score; Noul gated onnoulwith two cuts (Cookbook: Guardrails for LLMs); cases where a stock cut misfired: Failure reports: confidence misread and calibration. - Consequential gate (blocks, pays, deletes or sends)? Failure check done: Failure reports: confidence misread and calibration read and the cut validated on your own labels; Jev is never the sole safety control (Patterns: agent internals, routing, gates, context and memory P03). Other gates: threshold checked on your own labels.
- Claiming the agent got better? Measure the whole agent with and without Jev, not the decision alone (Head-to-head: Jev inside agents, routers and tool gates).
- Questions and thresholds in one reviewable file.
-
429/529retried with backoff;401/422and over-limit400s never retried;x-typesafe-request-idlogged. -
usage.input_tokensmetered against $0.042/Mtok. - Repeatability, held-out accuracy, adversarial inputs and reordered Choice options tested.
-
TYPESAFE_LOG_LEVEL=debugoff in production (bodies not redacted). - Use fits the Acceptable Use Policy, binding via MCA §2.3(l) since 2026-09-23: no misleading people about AI-generated content, no spam or unsolicited messaging, no scraping, probing or vulnerability-testing TypeSafe, no designs pushing minors into compulsive use (Legal: MCA, DPA, privacy, data retention).
Common mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| One broad question hiding several judgments | Confident, wrong, unexplainable | Decompose; the tool-call example finds the unit mismatch only as nine questions (How to build software with System One) |
Acting on choice without confidence |
0.61/0.35 treated like 1.00/0.00 | Gate on confidence first (Confidence-gated routing); tune the cut per task (Failure reports: confidence misread and calibration) |
.confidence on a Noul |
Attribute error / undefined | Threshold noul, or compute the docs' stand-in from Step 5 (Confidence vs probability) |
Treating noul = 0.5 as "medium" |
Mid-range read as moderate intensity | Use a Score for magnitude (Choosing between Choice, Score, Noul) |
| Asking for a count, sum, or date comparison | Errors grow with size | One Noul per item plus sum(); extract date parts as Choices, compare in code (Jev 1.13 jaggedness: known failure modes) |
Numeric Score levels ("0", "1", "2") |
Low confidence, mid-drift | Describe a situation per level (Writing instructions and criteria that Jev reads correctly) |
No other option on a Choice |
Mass lands on the least-wrong option | Add a catch-all (Choosing between Choice, Score, Noul) |
Whole record in state |
Accuracy drops; wrong answers hard to localize | Filter in code first (State: what you send Jev) |
Asking X and 1 - not_X, expecting agreement |
Probabilities summing to 1.19 | Ask the one question you want (TypeSafe's jaggedness page until 2026-10-02) |
| Trusting one option order | The first option wins more than it should | Reorder the options in evals and check the answer holds (#8 since 2026-10-02) |
| Serial single-question calls | ~12x cost, ~10x latency | Batch into one request (Cookbook: Parallel questions) |
Thresholds tuned against jev-latest |
Silent shift when the alias moves (it moved to jev-1.14.0 between the 2026-10-21 and 2026-10-24 captures) |
Pin the version you tuned on, log response.model (Models, aliases, pricing, rate limits, context) |
| Swapping only the base URL | Key sent to another operator; a replica answers under Jev's model name | Bind base URL, key and model ID together (Open replicas and Jev-compatible servers) |
Retrying 401 or 422 |
Repeat failures, wasted quota | Retry only 408/429/5xx (HTTP status codes, rate limits, retry semantics) |
Expecting Score.criteria as an int-keyed dict |
TypeSafeError at build or validation |
Both SDKs take an ordered sequence (Python SDK: install, clients, system_one(), JavaScript/TypeScript SDK quick contract: install, client, choice/score/noul, answers, errors (the page a builder reads)) |
| Trusting a cookbook's demo threshold | Wrong in your domain | "Treat cookbook thresholds and demo results as examples to evaluate" (The typesafe-ai agent skill and Claude Code plugin) |
Where to look next
- What is this model? System One Models, Jev (model)
- Which question type? Choosing between Choice, Score, Noul, Primitives: Choice, Score, Noul
- How to phrase it? Writing instructions and criteria that Jev reads correctly, Structured instructions, options, levels, criteria
- What goes in
state? What isconfidence? State: what you send Jev, Confidence vs probability - Wire format: HTTP API: POST /v1/systemone and GET /v1/models, OpenAPI component schemas
- SDK signatures: Python SDK: install, clients, system_one(), Python SDK question types (Noul, Choice, Score), Python SDK responses, answers, usage, models, JavaScript/TypeScript SDK quick contract: install, client, choice/score/noul, answers, errors (the page a builder reads), JavaScript SDK interfaces and type aliases
- Already on Pydantic AI? Pydantic AI TypeSafeModel: running Pydantic AI agents on Jev: Pydantic's official
TypeSafeModelturns anoutput_typeinto Jev questions (partner docs; TypeSafe's docs win on Jev). Since the 2026-09-25 docs it is aDecisionModel: settings renamed todecision_*,typesafe_tool_call_thresholdignored; see that page's upgrade table. Other frameworks: Framework integrations: Pydantic AI, LangChain, Spring AI, Vercel AI SDK, eve, LiteLLM, BAML, TanStack AI, DSPy, Langfuse and other framework-shipped Jev support; hosted routes: Platforms and gateways: Zapier, Cloudflare, Netlify, Vercel AI Gateway, OpenRouter, Pydantic AI Gateway, Opper, Fly.io, OpenCode Zen and other hosted routes to Jev - Getting access without a TypeSafe account; pointing the SDK at a gateway: console.typesafe.ai (console + playground), Python SDK internals: headers, key validation, gateways and base URLs, logging, forward compatibility, dependencies, migration notes, JavaScript SDK internals: constructor options, headers, retries and timeouts, env vars, logging, gateways, forward compatibility, migration notes
- Errors, retries, limits: HTTP status codes, rate limits, retry semantics, Python SDK retries, exceptions, constants, JavaScript SDK error classes, RetryPolicy, RequestOptions
- Price, aliases, context window: Models, aliases, pricing, rate limits, context
- Old integration: Migrating from /preview/evaluation to /v1/systemone
- Sending customer or confidential data; data retention and ZDR; acceptable use; training on outputs; publishing measurements: Legal: MCA, DPA, privacy, data retention
- Community probes of the request itself (overhead,
max_tokens_exceeded, batching): Request mechanics: billing, limits, latency, calibration and stability (community tier) - First call; evaluation: Quickstart: first call in HTTP, Python, JS; Testing and evaluating a Jev workflow
- FAQ, terminology, history: FAQ for agents and developers, Glossary, Versions and timeline (models, SDKs, API, company)
- Jev vs an LLM in JSON mode: Jev vs LLM JSON mode / structured outputs
Closest recipe by task:
- Routing / intent: Intent routing, Cookbook: Self-consistency — choices
- Extraction: Cookbook: Pre-parsed value extraction, Cookbook: Date extraction, Cookbook: SDE cascade
- Ranking / reranking: Cookbook: Re-ranking, Composite scoring; benchmark runs (BEIR, ESCI, screening): Head-to-head benchmarks: retrieval, reranking, screening and judging (community tier)
- Guardrails: Cookbook: Guardrails for LLMs, Cookbook: Classifying RAG passages
- Dedup / record matching: Cookbook: Knowledge graph entity alignment
- Classification with confidence: Cookbook: Classification using confidence, Cookbook: Hierarchical classification
- Function calling / tool use: Cookbook: Function calling
- Search inside a document: Cookbook: Line-by-line search
- Verifying an LLM's claims: Cookbook: Double-checking citations; Jev as an LLM judge, measured: Head-to-head benchmarks: retrieval, reranking, screening and judging (community tier)
- Support, sales, recruiting, finance ops: community builds with their numbers on Builds: business ops and markets (community tier)
- Agent context management: Cookbook: Skill suggestion
- Document structure: Cookbook: Structure recovery (autoformat)
- Features for a classical ML model: Cookbook: Autoresearch feature discovery
- Cost and batching evidence: Cookbook: Parallel questions
- Everything else: Cookbooks overview, Use-case map by industry
Related
- Consult guide: could Jev help this project? — unsure Jev fits at all? Consult first (community tier)
- When not to use Jev: rules, embeddings, trained classifiers, small and frontier LLMs — rules, embeddings, classifiers or an LLM instead
- Running Jev in production: versioning, caching, retries, monitoring and fallbacks — running for real users
- Images and assets (experimental), Box questions (experimental) — experimental image input and Box questions (prototypes only)
- How to build software with System One — the seven-step design workflow
- Patterns overview — the four architectural patterns
- The typesafe-ai agent skill and Claude Code plugin — TypeSafe's own instructions to coding agents
- Jev inside your agent harness: hooks, tools and fail-safes — Jev inside an agent harness: hooks, tools, timeouts, fail direction
- Workflow evals: how TypeSafe measures Jev — evidence for the workflow shape
- AI primer: why calibrated decision models — why the probabilities are calibrated
- Smart home assistant demo walkthrough — fan-out plus LLM fallback, running
Sources
- wiki/concepts/system-one.md, wiki/concepts/primitives.md, wiki/concepts/state.md, wiki/concepts/confidence.md, wiki/concepts/how-to-build.md, wiki/concepts/jaggedness-jev-1-13.md, wiki/concepts/use-case-map.md, wiki/concepts/workflow-evals.md
- wiki/reference/http-api.md, wiki/reference/models-and-pricing.md, wiki/reference/rate-limits-and-errors.md, wiki/reference/python-sdk.md, wiki/reference/python-sdk-responses.md, wiki/reference/javascript-sdk.md, wiki/reference/environment-variables.md, wiki/reference/agent-skill.md, wiki/reference/legal-and-data.md, wiki/reference/python-sdk-retries-errors.md
- wiki/patterns/overview.md, wiki/patterns/fan-out.md, wiki/patterns/confidence-routing.md, wiki/patterns/composite-scoring.md
- wiki/cookbooks/overview.md, wiki/cookbooks/parallel-questions.md, wiki/cookbooks/classification-using-confidence.md, wiki/cookbooks/consistency-choice.md, wiki/cookbooks/consistency-noul.md
- wiki/guides/quickstart.md, wiki/guides/choosing-a-primitive.md, wiki/guides/writing-instructions-and-criteria.md, wiki/guides/jev-in-agent-harnesses.md
- wiki/entities/typesafe-console.md, wiki/reference/python-sdk-internals.md, wiki/reference/javascript-sdk-internals.md, wiki/reference/javascript-sdk-errors.md, wiki/reference/pydantic-ai.md, wiki/reference/system-one-adapter.md, wiki/cookbooks/llm-guardrails.md, wiki/syntheses/faq.md
- Community-tier wiki pages: wiki/ideas/platforms-and-gateways.md, wiki/ideas/framework-integrations.md, wiki/ideas/request-mechanics.md, wiki/ideas/failure-reports-confidence.md, wiki/ideas/head-to-head-agents.md, wiki/ideas/open-replicas.md
- raw/docs/models.md (https://docs.typesafe.ai/models) — limits, price, aliases; raw/docs/model-jaggedness__jev-1.13.md (https://docs.typesafe.ai/model-jaggedness/jev-1.13) — failure modes, #8 option order
- raw/docs/confidence.md (https://docs.typesafe.ai/confidence) —
> 0.9proceeds with confirmation (confirm_then_execute), 0.5 floor, |2p − 1| Noul stand-in; raw/docs/patterns__confidence-routing.md (https://docs.typesafe.ai/patterns/confidence-routing) —> 0.85auto-approve, 0.6 floor - raw/docs/concepts__how-to-build-with-system-one.md (https://docs.typesafe.ai/concepts/how-to-build-with-system-one) — spam example state, questions and weights; raw/docs/cookbooks__consistency_noul_cookbook.md —
coveredspans 0.43 to 0.53 - SDK source: raw/github/typesafe-sdk-python/src/typesafe_sdk/_core/questions.py (a one-level Score accepted), response_types.py (
intScore keys), errors.py; raw/github/typesafe-sdk-js/src/questions.ts (throws below two levels), types.ts (string-index Score keys, per-attempttimeout,signal), errors.ts (RateLimitError.retryAfterMs) - raw/docs/introduction__quickstart.md (https://docs.typesafe.ai/introduction/quickstart) — console key URL
- raw/docs/agent-skill.md (https://docs.typesafe.ai/agent-skill) — console key URL (same
/keyspath since 2026-09-21) - raw/docs/api__errors.md (https://docs.typesafe.ai/api/errors) — request rules, compression, status codes, rate-limit handling (since 2026-10-20; the same text was on raw/docs/api.md before)
- raw/docs/primitives__noul.md (https://docs.typesafe.ai/primitives/noul) — Noul starting thresholds 0.7/0.3 (2026-10-24 capture)
- raw/docs/api.md, raw/docs/primitives__choice.md (https://docs.typesafe.ai/api, https://docs.typesafe.ai/primitives/choice) — 255 options per Choice; response examples and string Score keys (api.md); option-object field names are your choice (primitives__choice.md)
- raw/docs/legal.md (https://docs.typesafe.ai/legal) — ZDR for enterprise customers via sales@typesafe.ai
- raw/docs/sdk__python__usage.md (https://docs.typesafe.ai/sdk/python/usage) — OpenRouter, Vercel AI Gateway and Pydantic AI Gateway base URLs and model IDs
- First-party: raw/x/typesafeai-2103196683932983335.md (https://x.com/typesafeai/status/2103196683932983335) — signups closed, 2026-09-24
- First-party: raw/x/typesafeai-2104337822350221795.md (https://x.com/typesafeai/status/2104337822350221795) — signups open, 2026-09-27
- First-party: raw/x/typesafeai-2104337824292220981.md (https://x.com/typesafeai/status/2104337824292220981) — no free credits for new signups, 2026-09-27
- Partner docs: raw/partner/openrouter__docs__guides__community__typesafe-sdk.md (https://openrouter.ai/docs/guides/community/typesafe-sdk) — OpenRouter model IDs; raw/partner/cloudflare__ai__models__typesafe__jev.md (https://developers.cloudflare.com/ai/models/typesafe/jev/) —
stateandquestionsinputs only; raw/partner/pydantic-ai__models__typesafe.md (https://pydantic.dev/docs/ai/models/typesafe.md) —DecisionModel; raw/partner/pydantic-dev__articles__jev-pydantic-ai-gateway.md (https://pydantic.dev/articles/jev-pydantic-ai-gateway) — Pydantic AI Gateway base URL, bring your own key; raw/partner/opper-docs__build__gateway__evaluations.md (https://docs.opper.ai/build/gateway/evaluations) — Opper base URL - Community: raw/x-repos/fstandhartinger__jevbench__results-v1-4-2.md (JevBench v1.4.2 sealed hard set, via wiki/ideas/failure-reports-confidence.md)
- Community: raw/x-repos/tyler-dot-earth__patdown__docs-jev-input-limits.md (patdown, tyler-dot-earth) — HTTP 400
max_tokens_exceededon the direct API, 2026-09-18