Comparison

Jev vs Instructor and Guardrailsretry until it parses, or cannot be wrong-shaped

Instructor and Guardrails are wrappers. They ask an LLM for JSON, validate it, and re-ask when it fails. Jev is a different class of model: the answer space is the schema, so there is nothing to parse and nothing to retry. That difference shows up in your p99, in whether you get a probability back, and almost not at all in your bill.

Last updated: September 2026

Try the live Jev scorer

A free Jev-backed post scorer. No signup.

The one sentence that matters

Instructor guarantees the shape by retrying until it parses. Jev guarantees the shape because it cannot emit anything else.

Everything below follows from that. Instructor and Guardrails are a control loop around an autoregressive model that was free to write anything and happened to write JSON. The loop closes the gap after the fact. Jev never opens the gap: TypeSafe trains it to evaluate declared questions in one parallel pass, and the answer is drawn from the values you listed. There is no string to parse, so there is no parse failure, so there is no reask.

This is not the same as saying Jev is correct. It can pick the wrong option out of your list, and TypeSafe says so: its own launch post calls the 0 percent hallucination figure "not empirical" and notes that only "schema matching is guaranteed." Schema hallucination is eliminated. Semantic error is not, on either side.

Side by side

Instructor / GuardrailsJev
What it isA library around a model call. Python, open sourceA model. Hosted API, closed weights
How the shape is enforcedParse the output, validate it, re-ask on failureThe answer space is the schema. Nothing else can be emitted
Retries on a malformed answermax_retries or num_reasks, sequential, each one a full model callNot applicable. There is no parse step to fail
Effect on p50 latencyThe underlying model's latency70ms to 500ms end to end, per TypeSafe
Effect on tail latencyA reask doubles that request. A second reask triples itNo retry path, so the tail is the base distribution
Cost of a failureInput tokens again, plus the output tokens of the attempt that failedNo failure mode to pay for
Output token billThe underlying model's output rate, on every attemptZero. Output is unmetered
Confidence signalNone. A confidence field in your model is the LLM writing a number about itselfChoice and Score return probabilities plus a derived confidence. Noul returns the probability itself
Business-rule validationAny Pydantic validator. Cross-field, regex, ranges, custom codeOnly the answer space. Arithmetic, dates and invariants stay in your code
Generated text fieldsYes. Summaries, rewrites, explanations, extracted stringsNo. Jev cannot produce a string it was not given
Model portabilityAny provider, including a local model behind an OpenAI-compatible endpointTypeSafe only. No self-host, no open weights
Availabilitypip install, works todayEarly access waitlist, or via Vercel AI Gateway, OpenRouter, Cloudflare
Multimodal inputWhatever the underlying model supportsText only

Jev column from docs.typesafe.ai, September 2026. Library column from the Instructor and Guardrails AI docs. Both projects move fast, so read their changelogs rather than this table if you are choosing today.

The same task, three ways

One support ticket. Which team owns it, how annoyed the writer is on a three-level rubric, whether it is urgent. Instructor first.

triage_instructor.py
import instructor
from openai import OpenAI
from pydantic import BaseModel, Field
from typing import Literal

class Triage(BaseModel):
    department: Literal["billing", "technical", "sales"]
    frustration: int = Field(ge=0, le=2)
    is_urgent: bool

client = instructor.from_openai(OpenAI())

triage = client.chat.completions.create(
    model="gpt-5.6-terra",
    response_model=Triage,
    max_retries=3,
    messages=[{"role": "user", "content": ticket}],
)

print(triage.department, triage.frustration, triage.is_urgent)

# What you have: a validated Triage.
# What you do not have: how close "technical" came to winning.

Guardrails, same contract, wider validator pipeline.

triage_guardrails.py
from guardrails import Guard
from pydantic import BaseModel, Field
from typing import Literal

class Triage(BaseModel):
    department: Literal["billing", "technical", "sales"]
    frustration: int = Field(ge=0, le=2)
    is_urgent: bool

guard = Guard.for_pydantic(output_class=Triage)

result = guard(
    model="gpt-5.6-terra",
    messages=[{"role": "user", "content": ticket}],
    num_reasks=2,
)

print(result.validated_output)

# Same mechanism, wider remit. The validator pipeline can also
# reask, fix, filter or refrain on things a schema cannot express.

And Jev.

triage_jev.py
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

client = TypeSafeClient()   # reads TYPESAFE_API_KEY

response = client.system_one(
    state=ticket,
    model="jev-1.13.0",
    questions={
        "department": Choice(
            instructions="Which team should handle this",
            criteria={
                "billing": "Payment or subscription issues",
                "technical": "Bugs or integration problems",
                "sales": "Pricing or account questions",
            },
        ),
        "frustration": Score(
            instructions="How frustrated the customer appears",
            criteria=[
                "Calm, just stating facts",
                "Frustrated but civil",
                "Very angry, strong language",
            ],
        ),
        "is_urgent": Noul(
            instructions="The message conveys urgency or time-sensitivity",
        ),
    },
)

dept = response.answers["department"]
print(dept.choice)          # "billing"
print(dept.probabilities)   # {"billing": 0.84, "technical": 0.159, "sales": 0.001}
print(dept.confidence)      # 0.596

print(response.answers["frustration"].score)   # 1.035
print(response.answers["is_urgent"].noul)      # 0.999

# Noul returns only .noul, a float from 0 to 1.
# There is no .confidence on a Noul answer.

The detail that separates a written-from-the-docs page from a rewritten press release

A Noul answer returns noul, a float from 0 to 1, and nothing else. There is no confidence field on a Noul. Only Choice and Score have one. If a tutorial reads answers["x"].confidence on a Noul, it was never run.

What a reask actually costs you

Not money. Time, and only in the tail, which is exactly where it hurts.

Assumptions:

  • Base call latency of 8.6 seconds. That is the figure from TypeSafe's own recorded side-by-side, where GPT-5.6 Terra took 8.566s to Jev's 0.114s. Substitute your own p50.
  • A reask is sequential and is a full second call, so it roughly doubles that request.
  • A reask pays the input tokens again plus the output tokens of the failed attempt.
  • Jev's range is TypeSafe's published 70ms to 500ms end to end.
Failure ratep50TailExtra spend
No reasks (0%)8.6s8.6sbaseline
2% reask rate8.6s~17.2s+2%
5% reask rate8.6s~17.2s+5%
5% reask, 1% second reask8.6s~17.2s, p99.5 ~25.8s+6%
Jev, no retry path~0.1sno retry multiplier; TypeSafe publishes 70ms to 500ms end to end, which is a stated range, not a p99 guaranteeoutput free

Arithmetic, not a measurement. Your reask rate depends on your model, your schema depth and your prompt. Measure it before you size a timeout.

Two things fall out of that table. First, the money argument against retries is weak. A 5 percent reask rate costs about 5 percent more, which nobody notices. Anyone telling you retries are expensive has not done the multiplication.

Second, the latency argument is strong, and it is a tail argument rather than an average one. Retries do not move your p50 at all. They put a second full model call into the slowest few percent of requests, which is precisely the slice that trips timeouts, blows a synchronous request budget and shows up in a postmortem. If a retry loop sits on a user-facing path, the reask rate is your p99, not a footnote.

Jev has no retry path, so its tail is just its distribution. That is the real structural win here, and it is smaller and more specific than "444x cheaper." The published limits page has the rest of the operational envelope.

The thing a wrapper cannot give you

You can put a confidence: float field on a Pydantic model and the LLM will fill it in. It will look like a probability. It is not one. It is a token the model generated about its own answer in the same forward pass that produced the answer, with no access to the distribution that produced it. Nothing trained it to be right.

Jev computes confidence from the distribution it already returns, so a concentrated distribution reads high and a flat one reads low. That is a statistic, and it lets code make a three-way decision rather than a binary one.

gate.py
dept = response.answers["department"]

if dept.confidence >= 0.9:
    route_to(dept.choice)                    # act
elif dept.confidence >= 0.5:
    queue_for_confirmation(dept.choice)      # verify
else:
    escalate_to_human(ticket)                # do not guess

# The same three-way split with Instructor needs a confidence field
# the LLM writes itself, which is a token, not a statistic.

Be careful about how much weight you put on the word calibrated. TypeSafe says RLCD optimises for "epistemically honest probabilities," but it has published no calibration curves, no Brier scores and no reliability diagrams, the training method has no paper, and the docs decline to name a universal threshold: "start with conservative thresholds, test with your own data, and adjust as you observe results." Plot confidence against accuracy on your own labels before you automate anything on the strength of it.

0.9+
docs guidance for acting automatically
under 0.5
docs guidance for routing to a human
0
published calibration curves

Where each one wins, honestly

Keep Instructor or Guardrails if

  • The output includes generated text: a summary, a rewrite, an extracted quote.
  • Your contract is a nested object with arrays and conditional branches, not a flat set of judgments.
  • You enforce real business rules: cross-field invariants, regex, ranges, totals that must add up.
  • You need to stay portable across providers, or run against a local model.
  • You want the Guardrails validator hub for PII, toxicity or competitor checks.
  • You want it working this afternoon, with no waitlist and no new vendor review.

Move the call to Jev if

  • The call is pure judgment: one of these labels, a level on this rubric, yes or no.
  • Tail latency is a product constraint and a reask is not acceptable.
  • You want a probability over every option so code can gate on how sure it is.
  • You ask several questions about the same text and pay for each one separately today.
  • Volume is high enough that per-decision cost is something you discuss.
  • You can accept a single closed-weight vendor in early access on that path.

Most real systems keep both. Jev takes the judgment, the LLM takes the writing, and the validators stay exactly where they are, because Jev does not enforce that your numbers add up and does not claim to.

Then something has to ship it

Jev decides, an LLM writes, and neither of them publishes anything. On the social side that last step is one request.

bash
curl -X POST https://opentweet.io/api/v1/posts \
  -H "Authorization: Bearer ot_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The triage pipeline ships today.",
    "scheduled_date": "2026-09-20T14:00:00Z",
    "platforms": ["x", "bluesky", "linkedin"]
  }'

Same surface as a hosted MCP server, so an agent takes the same action without a second integration. Get an API key, or see how the composer wires in a decision model.

Frequently asked questions

What is the difference between Jev and Instructor?

They are different kinds of thing. Instructor is a Python library that wraps an LLM client: you hand it a Pydantic model, it asks the model for JSON, validates the result, and on a validation failure re-asks with the error appended until the object parses or max_retries runs out. Jev is a model. It is trained so that its answer space is the set of values you declared, so there is nothing to parse, nothing to validate and nothing to retry. Instructor guarantees the shape by retrying until it parses. Jev guarantees the shape because it cannot emit anything else.

Is Guardrails AI the same thing as Instructor?

Close enough for this comparison, different in scope. Both wrap a model call and enforce an output contract. Guardrails is broader: a Guard runs a pipeline of validators over the output and can reask, fix, filter or refrain depending on what failed, and its validator hub covers things like PII detection, toxicity and competitor mentions that have nothing to do with schema shape. Instructor is narrower and is essentially Pydantic plus reask. Against Jev they line up the same way, because the retry loop is the mechanism in both.

Do retries actually cost much money?

No, and pages that claim otherwise are wrong. A reask pays the input tokens again plus the output tokens of the failed attempt. At a 2 percent reask rate that is roughly 2 percent more spend, which is noise. What a reask costs is time. The retry is sequential and it is a second full model call, so a 2 percent reask rate means the slowest 2 percent of your requests take about twice as long as the median. If your p50 is 8 seconds, your p99 is about 16. That is the number that shows up in an incident review, not the bill.

Can I get a calibrated confidence score out of Instructor?

Not a real one. You can add a confidence float to your Pydantic model and the LLM will fill it in, but that is the model writing a number about itself in the same forward pass, not a measurement of the distribution over your options. It is a token, not a statistic. Jev computes confidence from the probability distribution it already returns: concentrated distribution means high confidence, flat distribution means low. Whether those probabilities are well calibrated on your data is a separate question you should measure, because TypeSafe has published no calibration curves.

Which one locks me in more?

Jev, clearly. Instructor and Guardrails are open-source libraries that sit in front of whatever model you point them at, including OpenAI, Anthropic, Gemini, and a local model behind an OpenAI-compatible endpoint. Swapping providers is a client swap. Jev is a hosted, closed-weight model from a company founded in 2026 that is still in waitlist-gated early access, with no self-host option and no open weights. There is no drop-in replacement. Community replications like NanoJev exist but they are replications, not compatible backends.

Can Jev replace my Pydantic validators?

Only the enum ones. Jev enforces that the answer is a value you declared. It does not enforce that a date is after another date, that a total equals the sum of its lines, or that an identifier matches a regex, and it will not enforce a cross-field invariant. TypeSafe documents this directly: counting and arithmetic are unreliable and should be done in code, dates are treated as text rather than ordered values, and no structural invariants hold across separate questions. Keep the validators. Move the judgment.

Can I run Instructor and Jev together?

Yes, and it is a sensible split. Jev takes the judgment calls that are pure classification, scoring or yes-no, and returns a distribution your code can gate on. Anything that needs generated text goes to an LLM with Instructor holding the shape. The free post scorer at /tools/will-it-go-viral is one worked example of that split: seven Jev questions on one draft, then a single POST to /api/v1/posts.

Judgment is a model call. Shipping is an API call.

The Jev-powered scorer at /tools/will-it-go-viral is free and needs no signup. The publishing half starts at $11.99 a month, with the REST API and the MCP server on every plan.

  • 7-day free trial
  • No X developer account needed
  • Cancel anytime