Skip to content

Designing the State: What to Include and What to Drop

Most Jev accuracy problems are state problems. What belongs in a state, what is a pre-made judgment to leave out, and why naming the slice you ask about matters more than the wording.

Published
Category
Jev Practices & Patterns
Resources cited
6
Reading time
3 min
Tags#state#design#primitives#architecture

Most Jev accuracy problems people blame on the model are state problems. The question is fine; the state handed to it is ambiguous, redundant, or missing the one field the judgment depends on. This is the design-side guide to what belongs in a state, in the order the primitives docs and the advanced guide frame it.

The state is the input, not the prompt

Jev takes two things: a state and a questions map. Everything a question can see has to be reachable from that state. There is no conversation history, no system prompt, and no hidden context — if a field is not in the state, the answer cannot use it.

That constraint is a feature. It means the state is the complete, auditable record of what the decision saw, and a wrong answer can always be traced back to a state that did not contain the right information.

state = {
    "ticket": {
        "subject": subject,
        "body": body,
        "account_tier": tier,
    },
    "policy": { "refund_window_days": 30 },
}

Include the material, not your conclusion

The most common mistake is putting the answer into the state. A field named is_angry: true computed upstream hands the model a verdict and asks it to agree. Pass the words, the metadata, and the raw values, and let the question do the judging.

Keep derived business facts the model cannot infer — the account tier, the policy window, the current time — but leave out anything that is itself a judgment you are asking Jev to make.

Name the part you are asking about

When a question concerns one slice of a large state, name it explicitly with a backticked path in the instructions, the convention the primitives docs recommend. A question about ticket.messages[0].text gets a sharper answer than "is the message angry" over a state holding several messages, because the model is not left to guess which one you mean.

Separate the record from the instructions

Do not string-build "Here is the ticket: ... Now classify it." Pass the ticket as structured state and the question in instructions. The pre-parsed extraction cookbook shows why: pre-parsing the fields in code removes a formatting step the model is weak at, and the question only has to judge the values you already split out.

One state, many questions

Every question in a request is answered against the same state, which is what makes parallel fan-out cheap. Design the state to serve all the questions a branch might need in one pass, then decide in code which answers matter. Adding a field costs input tokens; adding a second request costs a round trip.

Keep the untrusted parts clearly untrusted

If part of the state is text a user wrote, treat it as material to judge, never as instructions to follow. The jaggedness notes and the guardrails cookbook both assume the model takes instructions literally, so anything user-authored belongs in a state field, not in instructions.

A short checklist

  • Every field a question needs is in the state, and nothing else is.
  • No field is a pre-made judgment you are asking the model to rubber-stamp.
  • The specific slice a question is about is named with a backticked path.
  • Structured state replaces string-built prompts.
  • User-authored text lives in state, never in instructions.
  • The state serves every question in the request, so one call answers them all.

Get the state right and most "the model was wrong" reports turn into "the state was ambiguous," which is a fix you can ship today.

From the Jev directory

The resources behind this article.

How to shape what Jev evaluates: a string, a named object, or an array of messages. Every question in a request sees the same state and is evaluated independently.
Jev Practices & PatternsDocs#official#docs#state
Official
Instructions, option descriptions, score levels, and noul criteria all accept JSON, so you can label question parts, pass schemas and taxonomies, and keep candidate paths alive.
Jev Practices & PatternsDocs#official#primitives#architecture
Official
A maintained list of jev-1.13's known failure modes, literal reading, unreliable counting, dates as text, indirection, context rot, and contradictory criteria, each with a guardrail.
Jev Practices & PatternsDocs#official#docs#evaluation
Official
Regex finds candidate emails, phone numbers, and amounts; Jev picks the requested span so code copies a verbatim value that cannot be invented, with no free-text extraction required.
Jev CookbooksDocs#official#cookbook#extraction
Official
Ask everything the system might need in one request, then let code throw away what it does not use. The ticket-triage example sends a category plus four speculative questions in parallel.
Jev Practices & PatternsDocs#official#patterns#batching
Official
Screen every message going into and out of an LLM app: a Noul describes possible hazards, a Score rates severity, and code thresholds the probabilities.
Jev CookbooksDocs#official#cookbook#guardrails
Official
Back to all articles

More Jev articles

A Noul returns one number and no separate confidence. How to read the value, pin its boundary with criteria, split compound questions, and set a per-action threshold that matches the cost of being wrong.
Jev Practices & Patterns#noul#primitives#confidence
Read article
A Score is a weighted position, not a ruler. Why the number can land between levels, why levels are judged separately, and how to combine several atomic scores in code instead of one crowded rubric.
Jev Practices & Patterns#score#primitives#scoring
Read article

From the Jev community

Posts from builders shipping with Jev right now.

Follow @typesafeai