
Context Engineering for AI Systems: Architecture, Security, and Evals
How to build a small, trustworthy model context from policy, task state, evidence, memory, and tools—and test it under conflict, noise, and attack.
Read MoreA developer's reading of TypeSafe's Jev docs: request anatomy, choosing Choice, Score, or Noul, fan-out and composite scoring, confidence routing, failure modes, and evaluation.

Jev, TypeSafe's first System One model, is easy to call and easy to misuse. The API is one endpoint that takes a block of state and a set of typed questions. The hard part is architectural: deciding which judgments belong to the model, which belong to code, and what the system does when the model is unsure.
This guide follows the official TypeSafe documentation for jev-1.13.0 and turns it into a design method. If you have not met Jev before, start with our plain-language introduction and launch analysis.
Evidence status: API shapes, limits, and cookbook results below come from TypeSafe's documentation as reviewed on September 22, 2026. We did not call the API. TypeSafe's terms bar use from US-embargoed countries, including Iran, so the final section explains how to apply the same design with models a team can legally use.
The documentation contrasts three architectures. Traditional software is a large decision tree built from simple, reliable primitives. An LLM agent reads instructions and chooses its own next step, which works while a person watches but gives every loop another chance to go off the rails. In what TypeSafe calls AI-powered software, code owns the control flow and deterministic work, and the model is invoked only where the system needs common-sense judgment about unstructured input.
Jev is designed for the third shape. The build guide reduces it to a few rules: do in code everything code can do exactly; split the input into named parts; split each fuzzy judgment into narrow questions; ask many questions at once; combine the answers in code; and route on uncertainty. The rest of this guide expands those rules.
The benefit is testability. Each question is a unit you can evaluate on its own, each threshold is a number in version control, and the overall decision is ordinary code a reviewer can read.
Every call goes to POST https://api.typesafe.ai/v1/systemone with a bearer token. The body carries a model, a state, and a questions map. Each question has an ID you choose, a type, instructions, and for Choice and Score the criteria that define the allowed answers.
{
"model": "jev-1.13.0",
"state": "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP.",
"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"
}
},
"is_urgent": {
"type": "noul",
"instructions": "The message conveys urgency or time-sensitivity"
}
}
}
The response returns the versioned model that answered, one typed answer per question ID, and token usage. In TypeSafe's quick-start run, department came back as technical with probabilities of 0.85 for technical and 0.15 for billing and a confidence of 0.78, and is_urgent came back as a Noul of 1.0. Input tokens are billed at $0.042 per million; output tokens are free.
Two operational details matter from day one. First, the jev-latest alias moves when TypeSafe ships a new version, so once you have tuned thresholds, pin jev-1.13.0 and log the model field of every response. Second, rate limits (250,000 tokens per second and 1,200 requests per minute at review time) are adjusting with demand, and the official SDKs retry 429 responses with backoff.
The primitives reference gives a simple rule: pick the type whose answer your code can act on directly.
other or none of the above option when inputs might not fit. A Choice is relative: it tells you which option is best, not whether any option is good.A trap worth knowing before you build: Jev does not preserve logical identities across questions. TypeSafe's own example shows a Noul for "asking for a refund" and its negation summing to 1.19, and a Noul and a yes/no Choice on the same question disagreeing. Ask each decision one way, and do not carry a threshold tuned on one question type to another.
State is the material Jev judges. It can be a string, but TypeSafe recommends a JSON object with descriptive field names whenever the decision compares parts, for example a ticket, the order behind it, and the policy that applies.
Questions can point at parts of the state by path, written in backticks inside the instructions, such as asking whether refund_policy supports the refund requested in ticket.messages[0].text, given order.charges. Explicit paths reduce ambiguity and make wrong answers easier to trace.
Keep the state small and relevant. Accuracy falls as unrelated material grows, a failure mode TypeSafe calls context rot. Retrieve and filter in code first, or use a cheap Noul to screen passages for relevance before the real question. The hard limits are 64,000 tokens for the whole request and 32,000 for the state plus the longest single question. Input is text only: images, audio, and video must be converted to text or structured fields upstream.
Because every question is evaluated independently and in parallel against the same state, one request with many questions costs little more than one with a single question: the state is paid for once. TypeSafe recommends asking every question your code might need, including ones that matter only for some inputs, and letting code ignore the irrelevant answers.
The parallel-questions cookbook tests this on a compliance briefing over the roughly 54,000-character Wikipedia article on the GDPR, with 13 questions (8 Nouls, 2 Choices, and 3 Scores). Batching all 13 into one request was 12.2 times cheaper and 10.0 times faster than 13 separate calls, and the answers did not change; most were identical across all five repeats. (The primitives page quotes 11.5 and 9.6 times from a different run.)
The same independence has a design consequence: one question's answer never becomes context for another in the same request. Make a second request only when code genuinely cannot build it until the first answer arrives, for example when the first answer decides which documents to fetch next.
Every Choice and Score answer carries confidence, a number from 0 to 1 derived from how concentrated the probability distribution is. The confidence-routing pattern treats it as a second axis: the answer says what, the confidence says whether to act.
from typesafe_sdk import Choice, TypeSafeClient
client = TypeSafeClient(model="jev-1.13.0")
response = client.system_one(
state=voice_command_transcript,
questions={
"intent": Choice(
instructions="What is the user asking the bank to do?",
criteria={
"check_balance": "Hear the current account balance",
"approve_transfer": "Approve the pending transfer",
"other": "Anything else",
},
),
},
)
intent = response.answers["intent"]
if intent.confidence < 0.6 or intent.choice == "other":
route_to_support_agent()
elif intent.choice == "check_balance":
read_balance() # low stakes: 0.6 is enough
elif intent.confidence > 0.85:
approve_transfer() # high stakes, high confidence
else:
ask_user_to_confirm_transfer() # high stakes, moderate confidence
The thresholds come from TypeSafe's voice-banking example and are starting points, not recommendations for your data. The principle is that thresholds scale with the cost of a wrong action: a misread balance request is recoverable, a wrongly approved transfer is not. Our article on abstention and risk-coverage contracts covers how to choose these operating points from measured error rates.
TypeSafe's chart of how RLHF narrows a base model's output distribution, the "mode dropping" that makes self-reported LLM confidence unreliable.
TypeSafe's reason for trusting these numbers more than an LLM's self-reported confidence is its training objective. The company argues that preference training narrows a model's distribution toward confident, pleasing answers, while RLCD rewards probabilities that match observed accuracy. That is a claim to verify on your own data, not to assume.
When a judgment depends on several independent factors, ask one question per factor and combine the answers yourself. TypeSafe's resume-screening example scores Python depth, team leadership, system design, and breadth as four Score questions in one request, normalizes each to the range 0 to 1, and then applies different weights per role: 40% design and 40% Python for a senior engineer, 40% leadership for an engineering manager.
The payoff is control. When the ranking disagrees with what the team would decide, you change a coefficient rather than rewriting a prompt, and you can see exactly which dimension drove each result. The probabilities can also feed a classical model: one cookbook uses Jev's answers as features for a gradient-boosted regressor.
Jev's speed and price make it a natural first stage. In the intent-routing pattern it classifies each customer message and its complexity in one call, then code sends order-status questions to deterministic lookups, product and returns questions to specialist LLMs, and complex complaints or low-confidence cases to people. The expensive resources run only when needed. Our guide to routing by cost and quality covers how to measure whether such a cascade actually saves money.
Several cookbooks show the same idea in other domains. A guardrail pipeline screens every message into and out of an LLM application with Noul questions for specific hazards and a Score for severity, then thresholds them to pass, review, block, or route. A re-ranking cookbook takes 30-passage keyword shortlists for 40 legal queries and asks one question per query and passage, raising top-1 accuracy from 5% to 18% and top-10 accuracy from 38% to 62%. A structured-extraction cascade uses a small model to extract, Jev to verify, and a reasoning model only for what fails verification.
TypeSafe's security-incident workflow: triage readings, a code-based disposition, eleven containment readings, and a playbook that picks the strongest action whose conditions hold.
The security-incident workflow from TypeSafe's launch evaluation shows the full shape: three readings decide whether an alert is unauthorized activity, code turns them into close, queue, or act, eleven more readings describe the incident, and a playbook written in code chooses the response. The model never picks the action directly; it supplies the facts the policy needs.
TypeSafe's jaggedness page for Jev 1.13 is the most useful document for an engineer, because it states where the model breaks.
| Failure mode | What happens | Design response |
|---|---|---|
| Literal reading | Answers the words, not the intent | State exact conditions; put boundary cases in the criteria |
| Math and counting | Does not calculate or count reliably | Compute in code; ask one question per item and sum |
| Dates | Treats dates as text | Extract parts with Choice questions; compare in code |
| Indirection | Multi-hop questions lose accuracy | Name the relevant field; reduce hops |
| Irrelevant state | Distractors lower accuracy | Filter before calling; screen with a Noul |
| Adversarial content | Injected text can move answers | Tight criteria; test hostile inputs before launch |
| Contradictory wording | Instructions and criteria disagree | Make criteria extend the instruction |
| Structural invariants | Related questions need not agree | Ask each decision one way |
| Generation | Not trained to produce text | Use a generative model and let Jev choose among candidates |
Language belongs on this list too. The model documentation says English is the primary training language and other languages are handled "but not equally well"; it names CJK scripts and says nothing about Persian.
TypeSafe publishes no public benchmark scores and asks users to build their own evaluations, which is sound advice for any model. A minimal plan has four steps.
First, label a few hundred real inputs per question with the answer your team would accept, including hard and hostile cases. Second, measure accuracy and calibration: group answers by reported probability and check that each group's observed accuracy is close to its probability. Third, choose thresholds from the measured trade-off between the share of cases handled automatically and the error rate on those cases. Fourth, pin the model version, log every response's model and confidence, and re-run the evaluation before moving to a new version.
For decisions a team will depend on, keep a sample of automated decisions under human review after launch. Calibration measured on last month's data does not guarantee calibration on next month's inputs.
TypeSafe's customer agreement requires customers not to be located in, or nationals of, US-embargoed countries, which excludes teams in Iran. The architecture does not depend on Jev, and most of it transfers to models a team can legally use.
Keep control flow, arithmetic, and dates in code. Split each judgment into narrow questions with enumerated answers, and enforce the answer types at the boundary, as our guide to structured-output contract validation describes. Where a model exposes token probabilities, use them as a raw score and calibrate it on labeled data rather than trusting a number the model writes in text. For high-volume, stable questions, a small fine-tuned classifier with calibrated outputs is often cheaper than any hosted model. And gate every consequential action on a measured confidence threshold, with a human or a stronger model behind it.
What you give up without Jev is the guarantee that answers are always in-schema, the parallel evaluation of many questions at a single price, and the speed. What you keep is the part that makes the system reliable: decisions small enough to test, and code that decides what to do when the model is unsure.

How to build a small, trustworthy model context from policy, task state, evidence, memory, and tools—and test it under conflict, noise, and attack.
Read More
Document AI can copy every digit and still misread a table. Preserve header relationships, units and notes before letting extracted numbers drive a report or action.
Read More
An assistant can return no matches before its search is finished. Check scope, continuation, partial failures and time before allowing a negative answer to close a task.
Read MoreIf this note maps to a real system in your organisation, start with the services page or a shipped case study.