Creuto is now an OpenAI Select Partner Read More

AI & Machine Learning

Jev prompt examples: questions that work, and why

Jev prompt examples that hold up in production: copy-paste question sets for support triage, moderation, lead scoring and intent routing.

Jev prompt examples: questions that work, and why

Jev has no prompt. There is no system message to tune, no few-shot block to pad and no "think step by step" to add, so almost every set of jev prompt examples you will find is really a set of question definitions: an instructions field, a criteria map, and a type. Get those three right and the model behaves; tune wording around them and you are tuning nothing.

That is not a stylistic difference. TypeSafe's primitives documentation defines a question as an ID, a type of choice, score or noul, and instructions, with criteria carrying the options for a Choice or the ordered levels for a Score. The model returns a probability distribution constrained to the options you supplied. It cannot return anything else, so the failure mode that LLM prompt engineering exists to prevent — the model wandering off the schema — is not available to it.

What follows is four copy-paste question sets we would actually ship, then the rewrite rules that turn a vague instruction into one that holds up. Everything here maps onto the request shape in TypeSafe's docs as of September 2026.

What you are actually writing: four fields, all of which take JSON

The single most useful thing in the docs is buried in a table. TypeSafe's advanced structure page states that instructions, Choice option descriptions, Score level descriptions and a Noul's criteria.true and criteria.false all accept a string, an object, an array or null. Every field you would otherwise cram into one English sentence can be a labelled JSON object instead.

FieldApplies toAccepted shape
instructionsChoice, Score, Noulstring, object, array or null
criteria valuesChoice (option descriptions)string, object, array or null
criteria entriesScore (level descriptions)string, object, array or null
criteria.true / criteria.falseNoulstring, object, array or null

The docs give two reasons to use structure: clarity when a question has several parts, because the keys are labelled, and the fact that a schema, a taxonomy or a database row is already JSON, so you can pass the relevant subfields instead of serialising them into a string template. In the systems we build, the second reason wins more often. Your product already has the taxonomy; string-formatting it is work that only loses information.

One more rule that changes how you write: question IDs are not sent to the model. TypeSafe says so explicitly. An ID of refund_requested tells the model nothing, so the whole question goes in instructions even when the key looks self-explanatory.

Most jev prompt examples online are really question definitions

The examples below are ours, written against the documented request shape. Each one is a questions object you can paste into a request alongside your state and send to the System One endpoint. All the questions in a request see the same state, are evaluated independently and come back under the IDs you chose.

Support triage: one request, four judgments

Support triage is the case where the fan-out matters most. TypeSafe's docs say questions in a request are evaluated in parallel, that adding questions "barely changes the response time", and that asking a question you might not need is close to free. So ask for everything the router might want, and let code discard what it does not use.

{
  "department": {
    "type": "choice",
    "instructions": {
      "question": "Which team should handle `ticket.message`?",
      "focus": "Classify the primary request, not every topic mentioned."
    },
    "criteria": {
      "billing":  {"what": "Charges, invoices, refunds or subscriptions",
                   "not_for": "Order tracking or account access",
                   "examples": ["I was charged twice", "Where is my refund?"]},
      "orders":   {"what": "Order status, delivery, cancellation or returns",
                   "not_for": "Charges or account access",
                   "examples": ["Where is my package?", "Cancel my order"]},
      "account":  {"what": "Login, password, profile or security",
                   "not_for": "Charges or delivery",
                   "examples": ["I can't log in", "Change my email"]},
      "other":    {"what": "None of the above"}
    }
  },
  "is_urgent": {
    "type": "noul",
    "instructions": "`ticket.message` states that the customer is blocked right now."
  },
  "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"]
  },
  "refund_requested": {
    "type": "noul",
    "instructions": "Does `ticket.message` ask for money to be returned?"
  }
}

Three details do the work. The not_for key on each option draws the boundary between options, which is where classifiers actually fail. The backticked path ticket.message points the judgment at one part of a structured state — the docs call this referencing specific fields, and it matters as soon as your state carries a conversation, an order and a policy at once. And other exists because the docs advise adding an other or none of the above option whenever the list might not cover every input.

Content moderation: severity and the check are separate questions

The mistake we see most in moderation is a single Score called "how bad is this", which mixes what the content does with how serious it is. Split it. Ask a Noul per policy and a Score for severity, then combine in code.

{
  "harassment": {
    "type": "noul",
    "instructions": {
      "question": "Does `post.body` target a specific person with abuse?",
      "inspect": "post.body",
      "focus": "Judge the treatment of a person, not the opinion expressed."
    },
    "criteria": {
      "true":  {"what": "Insults, threats or demeaning statements aimed at an individual",
                "examples": ["You are worthless, kill yourself", "@alex is a moron"]},
      "false": {"what": "Criticism of an idea, product, company or public policy",
                "examples": ["This feature is badly designed", "That policy is unfair"]}
    }
  },
  "personal_data": {
    "type": "noul",
    "instructions": "`post.body` contains someone's phone number, home address or government ID."
  },
  "severity": {
    "type": "score",
    "instructions": {
      "question": "How serious is the harm if `post.body` stays up?",
      "note": "Judge the harm, not how offensive the language is."
    },
    "criteria": [
      {"summary": "No realistic harm", "signals": ["Disagreement", "Strong opinion"]},
      {"summary": "Harm to one person's experience", "signals": ["Insults", "Mockery"]},
      {"summary": "Harm to safety or identity", "signals": ["Threats", "Doxxing", "Incitement"]}
    ]
  }
}

Those structured Noul criteria come straight from the documented pattern: when the yes/no boundary is subtle, a what plus examples on each of true and false pins it down far better than a longer sentence. The structured Score levels use the same idea — the docs show each level as an object with a summary and a list of signals, which is easier to keep consistent across a rubric than three prose descriptions of increasing length.

Lead scoring: one question per factor, weights in your code

TypeSafe's guidance here is unusually direct: if a judgment depends on several independent factors, ask about each factor separately and combine the answers with your own logic. Their example is a startup pitch — market size, technical feasibility, differentiation — weighted in code. Lead scoring has the same shape, and it is the shape we use when we build the scoring layer of an AI-powered CRM and sales engagement platform.

{
  "icp_fit": {
    "type": "score",
    "instructions": {
      "question": "How well does `company` match the ideal customer profile?",
      "icp": {"employees": "50-500", "regions": ["IN", "AE", "UK", "US"],
              "buys": "custom software engineering"}
    },
    "criteria": ["No overlap", "Adjacent", "Partial match", "Clear match"]
  },
  "buying_intent": {
    "type": "score",
    "instructions": "How close is `message` to an active purchase decision?",
    "criteria": ["Browsing or research",
                 "Comparing options",
                 "Has budget and a timeline",
                 "Asking for a contract or a start date"]
  },
  "is_competitor": {
    "type": "noul",
    "instructions": "`company.domain` belongs to a competing software agency."
  },
  "named_a_deadline": {
    "type": "noul",
    "instructions": "`message` names a date, quarter or event the work must land before."
  }
}

Note the icp object sitting inside instructions. That is the payoff of structured instructions: the profile is a record in your database, so it goes in as a record. When sales changes the definition of the ideal customer profile, one JSON value changes. The docs make the equivalent point about weights — when priorities shift, you change the value of a weight rather than rewriting a prompt.

Intent routing: the Choice picks the handler, the Score picks the tier

TypeSafe's routing pattern classifies intent and complexity together, then uses the answers to send each message to deterministic code, a specialist LLM or a human. The question set is small because the routing logic lives in your code, not in the question.

{
  "intent": {
    "type": "choice",
    "instructions": "The primary intent of `message`.",
    "criteria": {
      "order_status":    "Asking about an existing order",
      "product_question":"Asking about a product before buying",
      "return_exchange": "Wants to return or exchange something",
      "complaint":       "Unhappy with experience, wants resolution"
    }
  },
  "complexity": {
    "type": "score",
    "instructions": "How complex is `message` to resolve?",
    "criteria": ["Simple lookup or standard procedure",
                 "Requires some judgment or a multi-step process",
                 "Unusual situation, edge case or escalation needed"]
  }
}

One intent goes to a database lookup with no model in the path at all. Two go to specialist LLMs loaded with different context. One uses the complexity score to decide between an LLM and a person. That division — a cheap classifier in front, expensive handlers behind — is the argument we made at length in our piece on when a decision model beats an LLM, and it is the pattern that survives contact with production.

Six rewrite rules that turn a vague instruction into a reliable one

These are the edits we make when a question underperforms. They are ordered by how often they fix the problem.

  1. Cut the question down to one snap judgment. TypeSafe's test is whether a knowledgeable person could answer it in a second given the right context. "Does this message convey urgency?" passes. "Analyse this message and determine the best course of action" does not — the docs call that a signal to break the task into small questions and compose the answers in code.
  2. Move the boundary into the options, not the instruction. A long instruction that explains how billing differs from orders is doing work that belongs in not_for on each option. The docs' own example tells the model what each option does and does not cover, and says plainly that this sharpens the boundary between options.
  3. Name the field you mean. If the state is an object, put a backticked path in the instruction — ticket.messages[0].text, not "the customer's message". Explicit paths make it clear which part of a structured state informs each judgment.
  4. Swap a Noul for a Score when the answer is a spectrum. The docs are blunt about this: a Noul of 0.5 means the model gives yes and no equal probability, not that the subject is medium. "Is this candidate strong in Python?" needs a definition of "strong"; either define it tightly ("does the resume state the candidate has used Python at work?") or use a Score with named levels.
  5. Give structured levels a summary and signals. Rubrics drift when each level is a paragraph of prose. An object per level keeps the axis consistent, and lets you add a note to the instruction naming what the score is not about — the docs' pull-request example says "judge the number of independent changes, not the size of any one change".
  6. Add the option you think you will never need. An other option is the difference between a classifier that tells you it is stuck and one that picks the least-wrong label at a confidence you then have to interpret.

Why is my Jev answer wrong? Usually it is the question, not the model

Four checks, in order. First, read the probabilities rather than the chosen option — a Choice returns the full distribution across your options, and a near-tie between two of them is a question whose boundary is wrong, not a model that failed. Second, check whether a low confidence value is telling you the state does not contain enough to answer; the docs describe low confidence on a Score as a sign the levels are ambiguous or multi-dimensional. Third, check whether you asked one question that should have been three. Fourth, check whether the state actually contains the evidence — Jev accepts text only, and its primary training language is English, with the docs noting lower accuracy on other languages including CJK scripts.

There is a class of problem no rewrite fixes. Anything needing deliberate multi-step reasoning, anything where the answer is prose, anything where the set of valid answers is not knowable in advance: those are LLM tasks, and Jev is capped at a cardinality of 255 options in any case, a limit TypeSafe states in its launch post. Use the decision model for the branch and the language model for the paragraph. That split is most of what we do when we take on AI engineering work for a product team that has already tried to do the whole job with one model.

Test the question set before you wire it to anything

Write thirty examples by hand, label them the way your team would, and run the question set against them in the playground before a single line of routing code exists. Most of the rewrite rules above came out of doing exactly that and watching which option boundaries the labels disagreed on. The question set is the specification of your decision — it deserves the same review as the code that acts on it, and a place in version control beside the generative AI components it feeds.

Frequently asked questions

Jev does not use a prompt in the LLM sense. A Jev request carries a state and a set of questions, each with a type of choice, score or noul, an instructions field and, for Choice and Score, a criteria map of options or levels. There is no system message and no few-shot block.

A good Jev question asks for one snap judgment a knowledgeable person could make in a second. Put the judgment in instructions, put the boundary between answers in criteria, name the state field you mean with a backticked path, and split anything that depends on several independent factors into separate questions.

Yes. TypeSafe's documentation states that instructions, Choice option descriptions, Score level descriptions and a Noul's criteria.true and criteria.false all accept a string, an object, an array or null. Structured instructions are the recommended way to pass a schema, a taxonomy or a database row without serialising it.

Use a Score. TypeSafe warns that a Noul value of 0.5 means the model gives yes and no equal probability, not that the subject sits in the middle. For skill level, define ordered levels such as no experience, some familiarity, daily use and deep expertise, and let the Score place the answer along them.

No. TypeSafe's documentation says every question in a request is evaluated in parallel, that adding questions barely changes the response time, and that the extra questions cost only their own tokens. Asking a speculative question your code may discard is close to free, so ask for everything the routing logic might need.

Check the probabilities before blaming the model. A near-tie between two options usually means the boundary between those options is undefined rather than that the judgment failed. Adding a not_for description to each option, naming the exact state field, and splitting compound questions fixes most cases we see.

Written by

Akash Mohapatra

Akash Mohapatra

Co Founder & Director

22 Sep 2026

·

11 min read

Share

LET'S CONNECT

Connect with Creuto!

Ready to take the first step towards unlocking opportunities, realizing goals, and embracing innovation? We're here and eager to connect.

We don't just aim to fit in – we strive to stand out. Experience the perfect blend of innovation, excellence, and trust that makes us truly unforgettable. Discover the difference with Creuto.

© 2026 Creuto All Rights Reserved