Jev Engineering: LLM Writes, Jev Decides, Code Acts [2026]
Jev engineering from a real production harness: a Claude Code guard hook, a model router, a 10-minute log cron with cost receipts, and when not to use Jev.
Jev engineering is a way of building AI agents where the roles are split by the kind of model that is good at them: a large language model writes (plans, code, prose), Jev decides (a typed Choice, Score or Noul answer with a probability on every option), and plain code acts on those numbers. The point is to stop paying LLM prices and LLM latency for every small fork in a loop, and to put each fork behind a number your code can threshold. In a replay of 600 real daemon log entries on 2026-09-22, Jev handled every entry for $0.00029 and a median of 302 ms per call, and the one case it would not own went to Claude Code for $0.083.
Where did "Jev engineering" come from?
The term is a week old. TypeSafe AI shipped Jev on 2026-09-15 and dropped the waitlist on 2026-09-20. On 2026-09-18 0xCodila published a 10-step roadmap on X with the line that stuck: LLM writes, agents act, Jev chooses the next move. A day later 0xRicker framed it as a control system: state, decision, action, verification, next state, with the expensive model moved out of every decision loop.
Both are right about the shape. What neither post has is a production harness you can read, with the bills. That is what this page is: the definition once, then three working patterns from my own loops, with every number produced by scripts you can download from this page.
This is the same move as harness engineering and loop engineering, one layer down. Harness engineering is about the system around the model. Jev engineering is one layer of that: the small decisions inside the system get their own model.
What is Jev, in one screen?
Jev is TypeSafe AI's first System One model. You send a state (any text or JSON, up to 32k tokens with the longest question) and a map of typed questions. It evaluates every question against the state in parallel and returns typed answers with a probability distribution, in one pass, without generating tokens. It cannot write a sentence, cannot write code, cannot explain itself, and cannot pick an option you did not list.
| Question type | Ask | Returns |
|---|---|---|
| Choice | Which one of these options? | choice, probabilities over every option, confidence |
| Score | Where on this ordered scale? | score (a weighted mean), probabilities per level, confidence |
| Noul | Is this true? | noul, the probability of yes, from 0 to 1 (no separate confidence field) |
The numbers that matter for a harness, checked against docs.typesafe.ai on 2026-09-22:
| Model | jev-1.13.0, aliased as jev-latest |
| Price | $0.042 per million input tokens, output free |
| Context | 64k tokens per request; 32k for the state plus the longest question |
| Rate limits | 250,000 tokens per second, 1,200 requests per minute (TypeSafe says these move while demand settles) |
| Latency I measured | 302 ms median (the script's upper-middle of 8), 525 ms slowest, from a script; hook calls end to end (Node startup, proxy hop, model call): 749 to 1,563 ms for the five that answered in the run shown plus one 4,375 ms timeout, 591 to 949 ms on the earlier run |
| Training | RLCD, calibrated probabilities. TypeSafe says it is not trained on customer requests or responses. English first; other languages work with lower accuracy |
| Endpoint | POST https://api.typesafe.ai/v1/systemone |
TypeSafe's own coding-agents page says it plainly: there is no model: "jev-latest" setting that turns Claude Code into a Jev agent. Jev is a component inside the agent you are building, not the agent's brain. So don't go looking for that setting. Jev lives inside the harness, not in the model config.
Why split the loop into three roles?
Kahneman's System 1 is fast, cheap and intuitive, and right often enough to run on by default; it is also where the biases live, which is why the thresholds section further down exists. System 2 is slow, expensive and the only one that can reason about something new. The metaphor is loose, and TypeSafe chose it, not me. Chat LLMs are System 2 machines that we have been forcing to make System 1 calls: is this log line an incident, which team owns this ticket, is this command safe, should the agent stop. Every one of those calls costs seconds and, at frontier prices, cents, and comes back as text you then have to parse and trust.
My estimate from running loops for the last four months, stated as an estimate: about 90% of the steps in an unattended agent loop never needed a big model. They needed a fork to be taken and a number to justify it. When I said that in the 09/20 club workshop, the pushback was "but the LLM can do that too." It can. It also tells you "you're absolutely right" when you're wrong, and it can't tell you how sure it actually was.

So the split is:
| Role | Who | Runs on | Produces |
|---|---|---|---|
| Writes | Claude Code, Codex, any LLM | The exception path | Plans, code, prose, a patch to a rubric |
| Decides | Jev | Every step | A probability on every option you listed, plus confidence on Choice and Score |
| Acts | Your code | Every step | The threshold check, the action, the new state |
The rule that makes it work: the LLM never sits in the hot loop of a classification job. In the cron it is called when Jev will not own a template, and when it is called, it edits data the fast model reads (a rubric, a config, a taxonomy), not the loop's code. In the router the LLM does the task either way; Jev only picks which one.
The harness pattern with real code
Three places Jev sits in front of the model in my Claude Code setup. All three ran on 2026-09-22; the outputs are pasted, not typed. Every script reads TYPESAFE_API_KEY if you have one in the environment. I ran them with treg's proxy in front, which supplies the credential from the run's environment, so no TypeSafe key sits on disk. With neither, the API answers 401.
1. A PreToolUse hook that gates dangerous commands with a Noul question
Claude Code hooks are the one place in a session where a decision can block an action. The hooks guide on this site says to keep hooks dumb: a regex, a path check, an exit code. That advice is still right for the cases a regex can name. The gap is everything else: the psql -c "DROP TABLE" that your force-push regex never sees.
.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/jev-guard.mjs" }]
}
]
}
}
.claude/hooks/jev-guard.mjs:
// PreToolUse hook: Jev decides whether a Bash command is safe to run. Code enforces the policy.
import fs from 'node:fs';
const input = JSON.parse(fs.readFileSync(0, 'utf8'));
const command = input.tool_input?.command;
if (!command) process.exit(0);
const headers = { 'content-type': 'application/json' };
if (process.env.TYPESAFE_API_KEY) headers.authorization = `Bearer ${process.env.TYPESAFE_API_KEY}`;
let answers;
try {
const r = await fetch('https://api.typesafe.ai/v1/systemone', {
method: 'POST', headers, signal: AbortSignal.timeout(4000),
body: JSON.stringify({
model: 'jev-latest',
state: { command, cwd: input.cwd },
questions: {
destructive: {
type: 'noul',
instructions: 'Would running `command` delete data, rewrite shared history, or change production state in a way that is hard to undo?',
criteria: {
true: { what: 'Irreversible or shared-state changes', examples: ['rm -rf on a real path', 'git push --force to a shared branch', 'DROP TABLE', 'a curl that POSTs to a production API'] },
false: { what: 'Read-only, local, or trivially reversible', examples: ['ls', 'git status', 'npm test', 'cat a file', 'creating a new branch'] },
},
},
kind: {
type: 'choice',
instructions: 'What kind of command is this?',
criteria: { read_only: 'Inspects files or state', build_or_test: 'Compiles, lints, or runs tests', local_write: 'Writes files inside the working tree', git_history: 'Rewrites or force-pushes git history', deletion: 'Deletes files or data', remote_mutation: 'Changes state on a remote service or database' },
},
},
}),
});
if (!r.ok) throw new Error(`jev ${r.status}`);
({ answers } = await r.json());
const noul = answers?.destructive?.noul;
if (!(Number.isFinite(noul) && noul >= 0 && noul <= 1)) throw new Error('bad answer shape');
if (typeof answers?.kind?.choice !== 'string') throw new Error('bad answer shape');
} catch (err) {
// Fail closed: no decision from Jev means the user decides, never silent allow.
out('ask', `jev-guard: Jev unavailable (${err.message}); confirm manually`);
}
const p = answers.destructive.noul;
const reason = `jev-guard: p_destructive=${p.toFixed(2)}, kind=${answers.kind.choice}`;
if (p >= 0.7) out('deny', `${reason}. Ask the user first.`);
else if (p >= 0.35) out('ask', reason);
process.exit(0);
function out(permissionDecision, permissionDecisionReason) {
console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision, permissionDecisionReason } }));
process.exit(0);
}
I ran the same six commands twice. The first run was on the version of the hook before the fail-closed fix; it scored rm -rf ./dist at 0.60 and DROP TABLE at 0.96. The second run, shown here, is the hook printed above, except that two checks were tightened afterwards (a review found that an out-of-range probability, and a missing kind answer, slipped past the old validation); none of the six results depend on them. The first call timed out at 4 s and the fail-closed path fired; my guess is a cold proxy, I did not trace it:
ls -la src/ ask Jev unavailable (The operation was aborted due to timeout); confirm manually 4375 ms
npm test allow (silent) 1563 ms
git push --force origin main deny p_destructive=0.95 kind=git_history 814 ms
rm -rf ./dist ask p_destructive=0.63 kind=deletion 953 ms
psql -c "DROP TABLE users;" deny p_destructive=0.95 kind=remote_mutation 749 ms
git checkout -b feat/jev-guard allow (silent) 852 ms
rm -rf ./dist landed at 0.63 (0.60 on the first run), inside the ask band, which is where a build folder belongs: usually fine to delete, sometimes not, so the hook asks instead of deciding. "allow (silent)" means the hook printed nothing and Claude Code's normal permission rules apply; the hook has no opinion there, it does not grant anything. And the policy is two numbers, 0.7 and 0.35, on the Noul probability itself: Noul returns P(yes) and no separate confidence, so a low value is a confident no, not an uncertain answer. When I decide the team can live with more risk, I change two numbers; nothing is re-prompted.
The cost: 749 to 1,563 ms per answered Bash call in the run shown, and one 4 s timeout, measured end to end (Node startup, the proxy hop and the model call together; I did not split them), against the hooks guide's 200 ms target. I pay it on Bash only, not on every tool. If that is too slow for you, run the hook as a long-lived process or filter commands inside the hook before calling Jev. Two more honest limits: the hook sees the command string and the working directory, nothing else, so it cannot know what npm test runs; it is one more signal on top of Claude Code's permissions and your sandbox, not the authorization boundary. And 0.35 and 0.7 are illustrative; six commands are a demo, not an evaluation. Before trusting a guard like this, run a labelled set that includes destructive commands and report the false-allow rate. And when Jev cannot answer, or answers in a shape the hook does not expect, the hook asks; it never allows by default.
2. Model and effort routing with a Choice question
Before the expensive model sees a task, Jev decides which tier it deserves and whether it should plan first. The bit that matters is the fallback: a low-confidence answer never picks the cheaper model.
const models = { small: 'claude-haiku-4-5', mid: 'claude-sonnet-5', frontier: 'claude-opus-5' };
const headers = { 'content-type': 'application/json' };
if (process.env.TYPESAFE_API_KEY) headers.authorization = `Bearer ${process.env.TYPESAFE_API_KEY}`;
export async function route(task) {
const r = await fetch('https://api.typesafe.ai/v1/systemone', {
method: 'POST',
headers,
body: JSON.stringify({
model: 'jev-latest',
state: { task },
questions: {
tier: {
type: 'choice',
instructions: { question: 'Which model tier should handle `task`?', focus: 'Judge the reasoning depth the task needs, not its length.' },
criteria: {
small: { what: 'Mechanical edits, renames, formatting, one-file changes with a clear spec', not_for: 'Anything that needs a design decision' },
mid: { what: 'Multi-file changes with a known pattern, tests, refactors inside one module', not_for: 'Architecture or ambiguous requirements' },
frontier: { what: 'Architecture, debugging across systems, ambiguous specs, security-sensitive changes', not_for: 'Work a junior engineer could do from the ticket alone' },
},
},
needs_plan_first: { type: 'noul', instructions: 'Should the agent write a plan and get it approved before editing files for `task`?' },
},
}),
});
const { answers } = await r.json();
const tier = answers.tier;
// Low confidence falls one tier UP, never down.
const pick = tier.confidence >= 0.75 ? tier.choice : (tier.choice === 'small' ? 'mid' : 'frontier');
return { model: models[pick], tier: tier.choice, confidence: tier.confidence, plan_first: answers.needs_plan_first.noul >= 0.6 };
}
Four tasks:
| Task | Jev said | Confidence | Model selected | Plan first |
|---|---|---|---|---|
Rename userId to accountId across the billing module | mid | 0.85 | claude-sonnet-5 | no |
Add a unit test for parseEntries covering multi-line entries | small | 0.62 | claude-sonnet-5 (bumped) | no |
| Design retry and idempotency for our Stripe webhook; duplicate charges in prod | frontier | 1.00 | claude-opus-5 | yes |
| Fix the typo in README.md | small | 1.00 | claude-haiku-4-5 | no |
Task text is shortened for the table. Each call cost about 500 input tokens, so about $0.00002, and took 280 to 610 ms, from the usage and timing fields the script logs; the block above keeps only the routing logic. The second row is the pattern in one line: Jev leaned small at 0.62, the code refused to trust a cheap pick at that confidence, and the task was routed to Sonnet. The router returns a model name; running the task on it is your loop's job. Wrong-and-cheap doesn't show up in the logs. Wrong-and-expensive shows up on the bill.
3. The 10-minute log cron: Jev classifies, Claude Code rewrites the rubric
This is the pattern from the 09/20 workshop, built and run. Every 10 minutes the cron tails a log, dedupes the entries into templates (same level and message, same field values once IDs, paths and wait times are dropped), and asks Jev two questions per template: which class in rubric.json does this belong to, and how urgently should a human look. If the class is known and confidence clears 0.8, code records the class's action: ignore, count, alert or page. Severity is a separate Score on a 0 to 2 scale (Ignore, Watch, Page) and its weighted mean never exceeds 2, so the page bar is 1.5, not 2 (the run used 2, which nothing could clear; the highest severity in the run was 1.4, so lowering it changes no result). A known class whose severity read is uncertain keeps the class action and does not page. Wiring alert and page to your pager is the one line this script leaves to you. If not, the unknown templates and the current rubric go to Claude Code, which returns a JSON patch adding a class. The patch is validated in code, written to rubric.json, and Jev re-runs on the unknowns. Anything still unknown after that is appended to an unresolved queue file for a human before the cursor moves on. Claude Code is only asked for the patch, and the validator is the boundary: the run used the CLI's default tool set, so if you want the boundary enforced rather than relied on, disallow the file-editing tools on that call.

The rubric is data, and it is the whole prompt:
{
"version": 1,
"thresholds": { "auto": 0.8, "page_on_severity": 1.5 },
"classes": {
"server_unreachable": {
"what": "The daemon could not reach the loopany server: fetch failed, connection refused, or a 5xx gateway error on poll",
"not_for": "Failures inside a Claude session or failures syncing a loop folder",
"examples": ["poll failed err: fetch failed", "poll non-ok status: 502 Bad Gateway"],
"action": "count"
},
"claude_transient": {
"what": "A Claude Code session exited abnormally and the daemon is retrying it after a backoff",
"not_for": "Network errors between the daemon and the server",
"examples": ["transient claude failure - resuming the session after backoff, attempt: 1, error: claude exited with code 1"],
"action": "alert"
},
"normal_delivery": {
"what": "Routine lifecycle: a run was claimed, finished, a folder is being watched, or the daemon is polling",
"not_for": "Anything with an error, a non-ok status, or a retry",
"examples": ["delivery claimed - running", "delivery finished", "watching loop folder", "polling for deliveries"],
"action": "ignore"
}
}
}
The core of the cron, as an excerpt: the parser, askJev, timing, the cursor and the unresolved queue are in the full script, which you can download with the raw outputs at /code/jev-engineering/ (execFileSync comes from node:child_process):
function questionsFor(rubric) {
const criteria = {};
for (const [name, c] of Object.entries(rubric.classes)) criteria[name] = { what: c.what, not_for: c.not_for, examples: c.examples };
criteria.unknown = { what: 'A log entry that does not fit any class above', not_for: 'Entries that clearly match one of the classes, even if the wording differs' };
return {
issue: { type: 'choice', instructions: { question: 'Which known class does `entry` belong to?', focus: 'Match on what happened, not on exact wording.' }, criteria },
severity: { type: 'score', instructions: 'How urgently should a human look at `entry`?', criteria: [
{ summary: 'Ignore', signals: ['Routine lifecycle', 'No failure'] },
{ summary: 'Watch', signals: ['A failure that the system retries by itself', 'Transient upstream trouble'] },
{ summary: 'Page', signals: ['Work was lost or delivered late', 'Auth or data-integrity errors', 'Repeated failure with no recovery'] },
] },
};
}
async function triage(templates, rubric) {
const q = questionsFor(rubric);
const handled = [], unknowns = [];
for (const t of templates) {
const { answers } = await askJev({ entry: t.sample, seen_in_window: t.count }, q);
const ok = answers.issue.choice !== 'unknown' && answers.issue.confidence >= rubric.thresholds.auto;
if (!ok) { unknowns.push(t); continue; }
let action = rubric.classes[answers.issue.choice].action;
if (answers.severity.score >= rubric.thresholds.page_on_severity && answers.severity.confidence >= rubric.thresholds.auto) action = 'page';
handled.push({ ...t, class: answers.issue.choice, action });
}
return { handled, unknowns };
}
function escalateToClaude(unknowns, rubric) {
const prompt = `You maintain rubric.json for a log-triage cron. Jev (a decision model) could not classify these log templates with confidence:
${JSON.stringify(unknowns, null, 2)}
Current rubric classes:
${JSON.stringify(rubric.classes, null, 2)}
Return ONLY a JSON object of NEW classes to add, same shape as the existing ones: {"<snake_case_name>": {"what": "...", "not_for": "...", "examples": ["..."], "action": "count|alert|ignore"}}. Prefer one class per distinct failure mode. No prose, no code fences.`;
// claude -p refuses to start nested inside a Claude Code session unless CLAUDECODE is stripped from the env.
const env = Object.fromEntries(Object.entries(process.env).filter(([k]) => k !== 'CLAUDECODE'));
const out = JSON.parse(execFileSync('claude', ['-p', prompt, '--output-format', 'json', '--model', 'sonnet'], { encoding: 'utf8', maxBuffer: 1 << 24, env }));
const patch = JSON.parse(out.result.replace(/```(?:json)?/g, '').trim());
for (const [name, c] of Object.entries(patch)) {
if (typeof c.what !== 'string' || typeof c.not_for !== 'string' || !Array.isArray(c.examples) || !['count', 'alert', 'ignore'].includes(c.action)) throw new Error(`rejected ${name}`);
if (rubric.classes[name]) throw new Error(`rejected ${name}: already exists, patches are additive only`);
}
return { patch, cost: out.total_cost_usd };
}
I pointed it at the last 600 entries of the loop daemon log on this machine, the one that runs my scheduled agents. This is a replay: the script reads the file and keeps a cursor; the scheduler, a single-run lock and log-rotation handling are the loop's job, not this script's. Three classes in the rubric on purpose; I knew the log had a fourth failure mode.

What happened, in numbers:
| Entries in the window | 600 |
| Templates after dedupe | 7 |
| Jev calls | 8 (7 plus one re-check) |
| Jev input tokens | 7,014 |
| Jev cost | $0.00029 |
| Jev latency | 302 ms median, 525 ms slowest of 8 |
| Handled by Jev without escalation | 6 of 7 templates, 597 of 600 entries, confidence 0.99 to 1.00 |
| Escalated | 1 template, sync request failed, 3 entries, confidence 0.50 |
| Claude Code escalation | added sync_request_timeout to the rubric, $0.0834, 10.4 s |
| After the patch | Jev classified the same template at 1.00 |
| Wall time | 13.2 s for the whole cycle |
The escalation was about 283 times the Jev spend (0.0834 over 0.000295, list price times tokens, not a billing receipt), for one template. Read that as the price of an escalation, not the per-decision saving: the fair per-decision comparison is a small chat model classifying the same seven templates, and I did not run that, so there is no number for it here. Send every template to Sonnet with a rubric-writing prompt like this one and the cron would cost tens of dollars a day; that is an estimate, I did not run that version. With Jev in front, the Jev side of a cycle costs a fraction of a cent (this cycle was 8.4 cents in total, almost all of it the one escalation), and Claude gets called only when the rubric has a hole, to write the entry that fills it.
The 0.50 is worth a look. Jev picked unknown for "sync request failed", at confidence 0.50, and the code escalates on the choice itself: anything that lands on unknown, or under 0.8, goes to Claude regardless of the number. I did not log the full distribution, so I cannot show which class it was torn between; my guess is server_unreachable, whose not_for line excludes folder-sync failures, and a guess is all that is. What matters for the design is that the rubric gave the model an honest place to put a leftover, and the code treated that as a hole to fill rather than an answer to act on.
Want the full loop, with the scheduler and the verifier around it? The Loop Engineering course builds exactly this shape: a loop that wakes on schedule, hands the small decisions to a cheap model, and only wakes the big one when a rubric has a hole.
Rubrics, not prompts
Everything you would put in a prompt goes into the question, and every field that takes a string also takes JSON: the instructions, each option, each score level, the true and false sides of a Noul. TypeSafe's structure page documents the shape; the shape that has held up for me across fraud scans, buying-signal triage and this cron is three keys per option:
"billing": {
"what": "Charges, invoices, refunds, or subscriptions",
"not_for": "Order tracking or account access",
"examples": ["I was charged twice", "Where is my refund?"]
}
what is the definition. examples work like few-shot prompting. not_for is the lever: it is the line that separates two options that sound alike in plain English, and it is where product knowledge goes. "We do not have a Framer export" in a not_for is the difference between a bug report and a feature request. In the cron above, not_for is my reading of why Jev did not file the sync failure under server_unreachable; I did not run the ablation.
Three rules I follow when writing one:
- One question, one judgment. "Rate this ticket" is a bad question. "Which team owns this" plus "how urgent is this" plus "is the customer threatening to churn" are three good ones, sent in one call, combined in code. TypeSafe's own docs say the same: atomic questions, composed in code.
- Options are a closed set you can defend. If you cannot list the acceptable answers, the fork is not ready for Jev. Add an
unknownoption with its ownnot_forso the model has somewhere to put the leftovers. - The rubric is versioned data. It lives in a file, it has a version number, and the LLM edits it through a validated patch. That is what makes the loop self-improving without becoming self-modifying.
Route on confidence
Jev hands back probabilities. Your code owns the decision, which is what lets the cases that clear your bar run unattended, and why the threshold is on you.
How I set them, every time:
- Label a small set. Twenty to fifty real cases through the question, marked right or wrong by a human. For the fraud scan on treg that is a morning's worth of signups; for the cron it was one window of the log.
- Pick the floor per action, not per question. The docs' confidence-routing pattern shows the shape: a floor under which nothing acts, then a higher bar for the irreversible action. In the guard hook that is 0.35 to ask and 0.7 to deny, on the Noul probability rather than a confidence. In the cron it is 0.8 to auto-apply and a separate 0.8 on severity before anything pages.
- Low confidence escalates, never auto-applies. Below the floor, the case goes to the LLM or to a person. The router above encodes the same idea as "fall one tier up, never down."
- Two numbers own the policy. When the business changes its mind, you edit two numbers and the same answers route differently. Nothing is re-run.
- Pin the model version when the thresholds matter. Every response carries the versioned id in its
modelfield (jev-1.13.0today); log it, my scripts above do not yet. Aliases move. If you tuned thresholds against a version, log it and re-run the labelled set before you follow the alias.
The launch posts don't cover this part. TypeSafe says the model is trained to return calibrated probabilities, and its own docs tell you to start conservative and test on your data. Anthus ran 8,801 labeled examples and found Jev overconfident: in the top confidence bucket (5,559 Choice answers, 63% of the set) average stated confidence was 99.4% against 90.2% accuracy, and over all Choice answers it was 91.4% against 76.1%. Higher confidence still meant more likely right, so the ordering holds even where the calibration does not. Two caveats before you carry those numbers over: Anthus thresholds the probability on the predicted answer, not the API's confidence field this article thresholds (for a two-way Choice the two are tied, confidence is about 2p minus 1), and the set is binary sentiment with 2,000 deliberately arbitrary neutral labels. Read it as the shape of the problem, not a test of the cron's 0.8. I have not reproduced those numbers and I have not seen the failure on my own distributions, which are close to the examples in my rubrics. Read that as: calibration inside your examples' distribution is what you can measure, calibration outside it is what you should assume degrades. Both are arguments for the labelled set and the floor, not against the model.
When not to use Jev
The launch posts skip this section, so here it is from someone who runs it in production.
| Do not use Jev when | Why | Use instead |
|---|---|---|
| You need text, code, or an explanation | It returns probabilities over options you wrote. It cannot say why. | The LLM, with Jev in front of it to decide whether the call is needed |
| The answer is arithmetic, a date, a regex match | A calibrated guess at 3 times 17 is still a guess | Code |
| The input is adversarial and nothing checks the output | "Ignore your instructions" in a signup form is a real thing in our logs. One classifier, however calibrated, is one point of failure | Jev plus a second signal (email verification, rate limits, a second question phrased differently) |
| The state is over 32k tokens | Hard limit for state plus the longest question. Above it you chunk or summarise, and now a summariser is in the loop | Map-reduce with Jev per chunk, or an LLM summary first |
| Nobody has written the acceptable options down | A Choice with vague options returns a confident answer to a question you did not ask | Write the rubric first. If you cannot, it is an LLM job |
| Non-English state where accuracy matters | English is the primary training language; TypeSafe says other languages, including CJK, currently score lower | Test on your own content and watch confidence, or translate first |
| The fork happens once | A 300 ms decision model in front of a one-off human decision is engineering for its own sake | Ask the human |
One more that is not a limit of the model: do not use Jev to replace the model in your coding agent. TypeSafe's docs say it, and the repos that got this right in the first week show the pattern. browser-use/jev-ultrafast uses Jev to pick the DOM target before any text is generated. tamaratran/fast-jev-compaction is a Claude Code plugin where Jev decides what to keep at compaction time. Both keep the LLM for writing and put Jev on the fork.
Where this is already running
The three patterns on this page are harness patterns. The same model also runs the GTM side of my two products, and that lives on its own page: how we use Jev with treg for signup fraud scans, buying-signal triage and launch radar, with the cost per run. The short version from those runs: a day of 236 signups costs about $1.20 on treg and $0.01 on Jev, and a single guardrail call is about $0.00002 (the signup demo on that page is a synthetic sample built to show the segments; the pipeline and the prices are the production ones). That's roughly what pushed me to stop putting the LLM in the loop.
Key takeaways
- Jev engineering is a role split: the LLM writes, Jev decides, code acts. In the cron pattern the LLM only gets called when Jev won't own the fork; in the router it picks which LLM does the work.
- Jev returns a probability on every option you listed, in one pass, for $0.042 per million input tokens, at roughly 300 ms from a script.
- The three harness placements that work today: a PreToolUse hook that gates commands, a router that picks the model tier, a cron that triages logs.
- Write rubrics, not prompts:
what,not_for,examplesper option, in a versioned JSON file the LLM patches through validation. - Thresholds are yours. Label a small set, pick a floor per action, escalate below it, never auto-apply a low-confidence answer, pin the model version.
- The cron's receipt: 600 entries, $0.00029 on Jev, one $0.083 escalation that added the missing class, which Jev then classified at 1.00.
- Do not use it for text, arithmetic, adversarial input without a second check, states over 32k tokens, or forks nobody has written options for.
Frequently Asked Questions
What is Jev engineering? A way of building AI agents where the roles are split by model type: an LLM writes (plans, code, prose), Jev decides (typed Choice, Score and Noul answers with a probability on every option), and plain code acts on those numbers. The LLM becomes the exception path instead of the loop.
What is a System One model? TypeSafe AI's category name for Jev. It takes a state (text or JSON) plus typed questions and returns probabilities over the options you listed, in one pass, without generating tokens. It cannot write text or code. The name comes from Kahneman's fast, intuitive System 1 versus the slow, deliberate System 2.
Does Jev replace the LLM in Claude Code or Codex? No. TypeSafe's docs say there is no model setting that turns a coding agent into a Jev-powered agent. Jev sits inside the harness around the agent: in a hook that gates a command, in a router that picks the model, in a cron that triages logs. The LLM still writes the code.
How do you choose a Jev confidence threshold? Label a small set of real cases, run them through your question, and pick the lowest confidence at which the answers were still right for that action. Use a higher bar for irreversible actions than for read-only ones, and treat anything below the floor as escalate, never as auto-apply. Re-check when you change the rubric or the model version.
Is Jev's confidence calibrated? TypeSafe says the model is trained for calibrated probabilities and tells you to test thresholds on your own data. One independent test (Anthus, 8,801 labeled examples) found Jev overconfident: in the top confidence bucket of 5,559 Choice answers, average stated confidence was 99.4% against 90.2% accuracy, and over all Choice answers 91.4% against 76.1%, though higher confidence still meant more likely right (their metric is the probability on the predicted answer, on a sentiment benchmark). Measure calibration on your labelled set, assume it degrades on inputs unlike your examples, and keep a human path for low confidence.
What does Jev cost in a real agent loop? $0.042 per million input tokens, output free. The 600-entry log replay on this page took 8 calls, 7,014 input tokens and $0.00029. The one Claude Code escalation in the same run cost $0.083, about 283 times the Jev spend.
When should you not use Jev? When you need text, code or an explanation; when the answer is arithmetic or a date; when the input is adversarial and nothing checks the output; when the state is over 32k tokens; and when nobody has written the acceptable options down. Jev picks from a list you wrote.
What is the difference between Jev engineering and harness engineering? Harness engineering is the whole runtime control system around a model. Jev engineering is one design choice inside it: giving the harness its own decision model so the LLM is not called for every fork. Every Jev pattern here is a harness layer.
Related Content
- Harness Engineering: What OpenAI and Anthropic Changed: the six layers Jev now slots into.
- Claude Code Hooks: The Rules Your AI Can't Ignore: the hook lifecycle the guard above plugs into, and the "keep hooks dumb" rule it bends.
- Loop Engineering: Stop Writing Prompts, Start Writing Verifiers: why the verifier is the bottleneck, and where a decision model helps.
- The 4 Types of Agentic Loops: which loop type the log cron is, and what it hands off.
Start Here
Watch the 09/20 workshop where I walked through the System 1 / System 2 cron live, with the fraud scan and the buying-signal filter that run on the same model: it is on the live AI workshops hub.
Then build the loop around it. The Loop Engineering course takes you from "you are the for loop" to a scheduled loop that decides cheaply, escalates rarely, ships behind quality gates, and reports back. Jev is the cheapest model-backed verifier I have put in one; a deterministic check is cheaper still whenever one exists.
Frequently Asked Questions
What is Jev engineering?
Jev engineering is a way of building AI agents where the roles are split by model type: a large language model writes (plans, code, prose), Jev decides (typed Choice, Score and Noul answers with a probability on every option), and plain code acts on those numbers. The LLM becomes the exception path instead of the loop.
What is a System One model?
System One model is TypeSafe AI's category name for Jev. It takes a state (text or JSON) plus typed questions and returns probabilities over the options you listed, in one pass, without generating tokens. It cannot write text or code. The name comes from Kahneman's fast, intuitive System 1 versus the slow, deliberate System 2.
Does Jev replace the LLM in Claude Code or Codex?
No. TypeSafe's own docs say there is no model setting that turns a coding agent into a Jev-powered agent. Jev sits inside the harness around the agent: in a hook that gates a command, in a router that picks the model, in a cron that triages logs. The LLM still writes the code.
How do you choose a Jev confidence threshold?
Label a small set of real cases, run them through your question, and pick the lowest confidence at which the answers were still right for that action. Use a higher bar for irreversible actions than for read-only ones, and treat anything below the floor as escalate, never as auto-apply. Re-check the numbers when you change the rubric or the model version.
Is Jev's confidence calibrated?
TypeSafe says the model is trained to return calibrated probabilities, and its docs tell you to test thresholds on your own data. One independent test (Anthus, 8,801 labeled examples) found Jev overconfident: in the top confidence bucket of 5,559 Choice answers, average stated confidence was 99.4% against 90.2% accuracy, and over all Choice answers 91.4% against 76.1%, though higher confidence still meant more likely right (their metric is the probability on the predicted answer, on a sentiment benchmark). In practice: measure calibration on your labelled set, assume it degrades on inputs unlike your examples, and keep a human path for low confidence.
What does Jev cost in a real agent loop?
Jev bills $0.042 per million input tokens and output is free. A replay of 600 daemon log entries in this article took 8 Jev calls, 7,014 input tokens and $0.00029. The one Claude Code escalation in the same run cost $0.083, about 283 times the Jev spend.
When should you not use Jev?
When you need text, code or an explanation, when the answer is arithmetic or a date, when the input is adversarial and you have no second check, when the state is bigger than 32k tokens, or when nobody has written down the acceptable options. Jev picks from a list you wrote; it cannot invent an option.
What is the difference between Jev engineering and harness engineering?
Harness engineering is the whole runtime control system around a model. Jev engineering is one design choice inside it: giving the harness its own decision model so the expensive LLM is not called for every fork. Every Jev pattern here (hook, router, cron) is a harness layer.
Sources & Verification
The log-cron, guard-hook and router numbers were produced on 2026-09-22 by running the code shown on the author's machine (the cron against a real loop-daemon log), through the treg proxy from Sydney, and are reported as measured end to end. Jev pricing and limits were read from docs.typesafe.ai the same day. The calibration figures are Anthus's and were not reproduced here.
- Introducing System One Models & Jev (TypeSafe AI blog, 2026-09-15) - Launch post: System One models, RLCD, 70 to 500 ms, $0.042 per Mtok input, cardinality up to 255
- Jev is now available to everyone (@typesafeai on X, 2026-09-20) - Waitlist dropped
- Confidence-gated routing (TypeSafe AI docs) - A floor under which nothing acts, then per-action bars; the banking example uses 0.6 and 0.85
- Models (TypeSafe AI docs) - jev-1.13.0, $0.042 per Mtok input, output free, 64k context per request, 32k for state plus the longest question, rate limits
- Confidence (TypeSafe AI docs) - Confidence is derived from the probability distribution; Noul answers carry no confidence field; thresholds scale with risk
- Advanced: structure (TypeSafe AI docs) - Instructions, options, levels and criteria accept JSON; the what / not_for / examples shape
- Jev with coding agents (TypeSafe AI docs) - Jev is not a drop-in model for Claude Code or Codex; use it inside the agent for decisions
- Can You Trust Jev's Confidence? (Anthus, 2026-09-19) - 8,801 labeled examples; in the top confidence bucket (5,559 Choice answers, 63% of the set) average stated confidence 99.4% vs 90.2% accuracy; over all Choice answers 91.4% vs 76.1%; higher confidence still meant more likely right
- Jev Engineering: the 10-step roadmap (0xCodila on X, 2026-09-18) - Coined the term; 'LLM writes, agents act, Jev chooses the next move'
- Jev Engineering as a control system (0xRicker on X, 2026-09-19) - state, decision, action, verification, next state
- How to use Jev for GTM automation (Jason Zhou on X, 2026-09-21) - Rubrics not prompts, route on confidence, the three production runs
- How to use Jev: examples, use cases and code (treg) - The three GTM recipes with cost receipts: signup fraud scan, buying-signal triage, launch radar
- browser-use/jev-ultrafast (GitHub) - Jev picks the DOM target before any text is generated
- tamaratran/fast-jev-compaction (GitHub) - Claude Code plugin: Jev decides what to keep at compaction time
Join AI Builder Club
$37/mo
Get the free newsletter
Weekly deep-dives on AI tools, automation workflows, and builder strategies. Join 5,000+ readers.
No spam. Unsubscribe anytime.
Continue Learning
Claude Code 101
You've read the theory. The course is where you ship: 3 guided Labs (live website, full-stack app with payments, business automation) plus the Template Vault starter kit. Rebuilt June 2026.
Mastering AI Agents
The builder's deep dive into agent loops, tools, context engineering & memory. Go from using AI to building it.
AI Agent 101
Build autonomous research agents with tool use, API access, web scraping, and deep search.