Back to blog

September 21, 2026Ceren Kaya Akgün

System One Models: Jev, Laya, and One Wire Format

System One models return calibrated probabilities instead of text. What Jev and Laya actually send back, and how one node runs either without a rewrite. →

system-one-modelsjevlayadecision-modeltypesafe-aicalibrated-probabilityai-workflowself-hosted
System One Models: Jev, Laya, and One Wire Format

We shipped a node last week that does something none of our other nodes do. It calls a model and gets back no text at all. No string to parse, no JSON to validate, no retry because the model wrapped its answer in an apology. Just a number, and a distribution behind the number.

I have been writing about this platform for a year, and System One models are the first thing that has made me rewrite my mental model of what a model call is.

The category is six days old. TypeSafe launched Jev on 15 September 2026 and called it a System One model. Convai answered with Laya, Apache-2.0 and running on your own hardware. A third entrant is already circulating on r/LocalLLaMA. By the time you read this there may be a fourth.

So this article is not another explainer. I read the ones that exist, and I will tell you exactly what they contain and where they stop. This one is about wiring a System One model into something that runs on a schedule, survives a rate limit, and hands the uncertain cases to a person.

  • The 0.9 an LLM writes is not the 0.9 Jev measures. A confidence field inside generated JSON is generated text: a number the model wrote. A System One model returns the distribution it actually computed
  • Jev and Laya speak the same wire format. Same three question types, same criteria shapes, same answers keyed by your own ids. We verified this against both providers' published schemas, and it means the choice between them is a deployment decision rather than a rewrite
  • A top-five ranking guide calls the boolean type null. It is noul, in TypeSafe's contract and in Laya's alike. Small error, but it will not compile
  • Zero of the ranking pages show the model inside a workflow. Every build is a script: curl, Node, Python, an SDK. None covers retries, tracing, branch routing, or what happens when nobody is awake to review the uncertain case
  • The guarantee is structural, not empirical. TypeSafe's own framing: a zero type-error rate covers the shape of an answer, not whether it is correct. Our docs say the same thing in four words, and it is the most important sentence on the page
  • Our own cost column stays empty for these calls. Decision models are not in the pricing tables we sync. Token counts still record. We would rather you read that here than discover it in a trace

Table of Contents


What System One Models Actually Return

Definition: System One models answer typed questions about a state and return calibrated probabilities instead of generated text. You send state plus a map of questions, and each answer comes back as a number with a probability distribution behind it. There is no prompt and no temperature.

That is the whole category, and the two load-bearing words are typed and calibrated.

The name comes from Thinking, Fast and Slow, where Kahneman splits cognition into System 1, fast and intuitive, and System 2, slow and deliberate. TypeSafe's framing is that Jev handles the first and reasoning models handle the second.

Jev itself is named after William Stanley Jevons, the economist behind the Jevons paradox: more efficient steam engines drove coal consumption up, because cheaper power found new uses. The bet is the same for judgment. Make a decision cost a fraction of a cent and you will put decisions in places you would never have called an LLM.

You send two things. State is the situation to judge, and it can be a string, an object, or an array. Questions is a map, keyed by ids you choose. Each answer comes back under the same key.

What you do not send is as interesting. No prompt. No system instruction. No temperature. No tools. There is nothing to prompt-engineer, which removes a whole category of work and a whole category of bug.

The 0.9 an LLM Writes Is Not the 0.9 Jev Measures

This is the part I had to sit with, and it is the reason the category exists.

Ask an LLM to classify a ticket and return {"team": "billing", "confidence": 0.9}. You will get valid JSON. Structured output will even guarantee the schema. And that 0.9 is generated text. It is a token the model produced because 0.9 is a plausible-looking number to produce in that position. Nothing measured it.

Our own guide to building a support agent that answers tickets uses exactly this pattern, gating on a confidence field an LLM returned in JSON. It works, and it is still a number the model wrote.

You can prove this to yourself cheaply: ask the same model the same question twenty times and watch the confidence cluster on 0.85, 0.9 and 0.95 regardless of how genuinely ambiguous the input was. It is reporting a style of certainty, not a degree of it.

A System One model returns the distribution it actually computed. Confidence is derived from the shape of that distribution: mass concentrated on one option means high, mass spread across several means low. You get the full distribution too, so you can compute your own statistic if your domain needs one.

TypeSafe trained for this specifically, with an approach it calls Reinforcement Learning for Calibrated Decisions. The target is that across many predictions, answers given 90% probability are right about 90% of the time. Laya's model card describes training against strictly proper scoring rules, which is the same idea from the other direction: reporting honest probabilities is the only way to maximise the reward.

Here is the sentence that matters most, and it is TypeSafe's own. The zero type-error rate is structural rather than empirical. It covers the shape of an answer, not whether the answer is correct. Our documentation says it in four words: a typed answer guarantees the shape, not the truth.

Read that twice before you build anything that spends money on it.

Three Question Types, and One the Guides Spell Wrong

There are exactly three, and both providers use the same names.

noul asks whether a condition holds and returns the probability that the answer is yes, from 0 to 1. Criteria are optional: you can describe what each side covers. A value near 0.5 means the model finds yes and no about equally likely. It does not mean "medium intensity", and reading it that way is the most common early mistake.

choice picks one option from a set you define, and returns the chosen key, the full distribution, and a confidence derived from it. Always include an option covering "none of these". The model cannot choose an option you did not offer, so without that escape hatch it will assign your edge cases to whichever of your real options is least wrong.

score rates the state along an ordered rubric you write. It returns a probability-weighted value that can land between levels, plus the legend and the distribution. Levels run lowest first, and each one should describe a concrete situation that stands on its own.

Now the correction. One of the guides currently ranking in the top five for this category calls the boolean type null. It is noul. TypeSafe's contract uses noul, Laya's API uses noul, and our own node validates against a tuple of exactly ("noul", "choice", "score"). If you copy null out of an article, the request fails validation before it ever leaves your machine.

I am not pointing this out to score a point. I am pointing it out because I nearly copied it myself.

Jev and Laya Speak the Same Wire Format

This is the finding I did not expect, and it is the most useful thing in this article.

The public conversation about these two models is a benchmark fight. Search jev vs laya and you get a Reddit head-to-head, three YouTube videos, a Hugging Face benchmark dataset, and a fair amount of heat about who invented what. Laya's own site makes a pointed case about open weights and published papers.

None of that matters for your integration, because the two speak the same contract.

A Laya question, from its published model card:

{
  "department": {
    "type": "choice",
    "instructions": "Which team should handle this ticket?",
    "criteria": { "billing": "payments, refunds, invoices", "support": "product help and bugs" }
  },
  "urgency": {
    "type": "score",
    "instructions": "How urgent is this request?",
    "criteria": ["not urgent", "soon", "critical deadline or blocking issue"]
  },
  "refund_requested": {
    "type": "noul",
    "instructions": "Does the user explicitly request a refund?"
  }
}

And the body our Decision node builds, from our own source: each question becomes {"type": ..., "instructions": ...}, choice gets criteria as a map of option keys to descriptions, score gets criteria as an ordered list of levels, and noul gets an optional criteria object with true and false sides. Answers come back keyed by your ids, and we pass the provider's response through unchanged. Nothing is renamed or flattened.

Those are the same structure. The receptron package says so in as many words, describing Laya as the open-source Jev-compatible System 1 decision model.

Short answer, because nothing else on the web gives one: Jev and Laya are interchangeable at the contract level. Same three question types, same criteria shapes, same answers keyed by your ids. They differ in transport, not in schema. Jev is a hosted HTTPS API; Laya is Apache-2.0 weights you run yourself.

Side by side, the differences that survive are all about deployment.

Jev (TypeSafe)Laya (Convai)
Question typesnoul, choice, scorenoul, choice, score
criteria for choiceMap of option key to descriptionMap of option key to description
criteria for scoreOrdered list of levelsOrdered list of levels
Answer keysYour own question idsYour own question ids
WeightsHosted, not publishedApache-2.0, published
How you reach itHTTPS APILocal weights via ONNX Runtime
Cost model$0.042 per million input tokens, output freeYour own hardware
Quoted latency70 to 500ms end to end, most near 100ms, measured from US West Coast~33ms single question, 7.2ms per question batched at ten
LanguagesNot published as a figure100+ claimed, 45 of 51 tested

The top four rows are the integration surface, and they are identical. Everything that differs sits below the contract.

One contract, two deployments
Same
Three question types
noul, choice and score, with identical names and identical semantics on both providers. A question written for one is a question for the other
Same
criteria shapes
A map of options for choice, an ordered list of levels for score, an optional true/false object for noul. Verified against both published schemas
Same
Answers keyed by your ids
The id you choose is never sent to the model; it is only how you read the answer back. Both providers return answers under the keys you supplied
Different
How you reach it
Jev is a hosted API you call over HTTPS. Laya is Apache-2.0 weights you run yourself through ONNX Runtime, so it needs a small server in front of it to be reachable over HTTP
Why the benchmark fight is not your problem
What this buys you
The choice becomes reversible
Because the contract is shared, switching providers is a credential change rather than a rewrite. Prototype against the hosted API, move to local weights when volume or data residency demands it, and keep the questions you already wrote
The models compete. The wire format does not. That asymmetry is the whole reason this integration is worth building once.

The practical consequence: running the Laya decision model instead of the hosted one stops being an architecture decision and becomes a deployment one. Hosted API with a per-token price, or local weights with a hardware cost. Prototype on one, move to the other when volume or data residency says so, and keep every question you wrote.

What the Explainers Stop Short Of

I read the pages currently ranking for this category so you do not have to, and I want to be fair to them, because one is genuinely excellent.

Flavio Copes' deep dive is the best thing written about Jev so far. Thirty-five sections, honest about limits, with a whole section on where the model breaks. LangChain's post builds a real harness. Sean Goedecke made it play Doom. These are good pages written by people who actually ran the thing.

They also share one shape. Every build is a script. Curl, then Node, then Python, then an SDK. The decision is made inside a program you run.

That is the right way to learn a model and an incomplete way to operate one. In production the model call is the small part. The work is everything around it: what happens on a rate limit halfway through a batch, how the uncertain case reaches a human who is not watching a terminal, where the trace goes, and who gets paged when the endpoint starts refusing the key.

Not one of the ranking pages covers that. I checked, because I expected to find it and wanted to link to it instead of writing it.

The gap is not their fault. It is six days old and everyone is still at the "what is this" stage. But if you are past that stage, the rest of this article is the part you were looking for.

Wiring One Into a Workflow

Here is the same triage decision as a workflow rather than a script. It takes a support ticket, asks all three question types in one request, gates on confidence, and only then routes.

Ticket triage with a confidence gate
View template JSON
{
  "heym": true,
  "nodes": [
    {
      "id": "so_note",
      "type": "sticky",
      "position": {
        "x": 40,
        "y": 40
      },
      "data": {
        "label": "setupNote",
        "stickyTitle": "Read this before you run it",
        "stickyColor": "sky",
        "stickyWidth": 380,
        "stickyHeight": 280,
        "note": "Create a Decision Model credential first, then select it on AskTheModel.\n\nThe model name here is jev-latest. Change it if your endpoint uses a different one.\n\nThe 0.7 in ConfidenceGate is a placeholder, not a recommendation. Read the threshold section before you trust it with anything that costs money."
      }
    },
    {
      "id": "so_input",
      "type": "textInput",
      "position": {
        "x": 60,
        "y": 380
      },
      "data": {
        "label": "SupportTicket",
        "value": "Our checkout has returned payment errors for every customer for 25 minutes. A paid campaign is live and orders have stopped. Please help immediately.",
        "inputFields": [
          {
            "key": "text"
          }
        ]
      }
    },
    {
      "id": "so_decide",
      "type": "decision",
      "position": {
        "x": 400,
        "y": 380
      },
      "data": {
        "label": "AskTheModel",
        "credentialId": "",
        "model": "jev-latest",
        "state": "$SupportTicket.text",
        "questions": [
          {
            "id": "is_urgent",
            "type": "noul",
            "instructions": "Does this message describe work that is currently blocked or time critical?",
            "criteriaTrue": "Explicitly time-sensitive, or something is broken right now",
            "criteriaFalse": "No urgency expressed and nothing is blocked"
          },
          {
            "id": "team",
            "type": "choice",
            "instructions": "Which team should own this ticket?",
            "options": [
              {
                "key": "billing",
                "description": "Payments, invoicing, refunds"
              },
              {
                "key": "technical",
                "description": "Bugs, outages, integrations"
              },
              {
                "key": "other",
                "description": "Nothing above fits"
              }
            ]
          },
          {
            "id": "business_impact",
            "type": "score",
            "instructions": "How much customer-facing business activity is affected right now?",
            "levels": [
              "None",
              "One customer",
              "Many customers",
              "Revenue has stopped"
            ]
          }
        ],
        "customBodyEnabled": false,
        "customBody": "",
        "requestTimeoutSeconds": 60
      }
    },
    {
      "id": "so_gate",
      "type": "condition",
      "position": {
        "x": 760,
        "y": 380
      },
      "data": {
        "label": "ConfidenceGate",
        "condition": "$AskTheModel.answers.team.confidence >= 0.7"
      }
    },
    {
      "id": "so_auto",
      "type": "output",
      "position": {
        "x": 1110,
        "y": 260
      },
      "data": {
        "label": "RouteAutomatically",
        "outputText": "Confident enough to route without a person.\n\nTeam: $AskTheModel.answers.team.choice\nConfidence: $AskTheModel.answers.team.confidence\nUrgency: $AskTheModel.answers.is_urgent.noul\nImpact: $AskTheModel.answers.business_impact.score"
      }
    },
    {
      "id": "so_human",
      "type": "output",
      "position": {
        "x": 1110,
        "y": 500
      },
      "data": {
        "label": "SendToHuman",
        "outputText": "Model was not confident. A person decides this one.\n\nBest guess: $AskTheModel.answers.team.choice at $AskTheModel.answers.team.confidence\nFull distribution is in the node output.\n\nOriginal message:\n$SupportTicket.text"
      }
    }
  ],
  "edges": [
    {
      "id": "so_e1",
      "source": "so_input",
      "target": "so_decide"
    },
    {
      "id": "so_e2",
      "source": "so_decide",
      "target": "so_gate"
    },
    {
      "id": "so_e3",
      "source": "so_gate",
      "target": "so_auto",
      "sourceHandle": "true"
    },
    {
      "id": "so_e4",
      "source": "so_gate",
      "target": "so_human",
      "sourceHandle": "false"
    }
  ]
}

That graph is a complete system one model workflow, and four things in it are doing work that a script would have made you write yourself.

The state is a single expression, $SupportTicket.text. A field holding exactly one expression keeps its own type, so passing the object instead would send the object rather than its text. That distinction bites people once and then never again.

The question ids carry no meaning to the model. is_urgent is how you read the answer back; it is never transmitted. All the meaning lives in instructions. Writing id: is_urgent with instructions: "Is it?" gives the model nothing to work with, and it will answer anyway, which is worse than failing.

The choice question has an other option. Without it, a ticket about a mis-sent marketing email would be forced into billing or technical, and it would arrive there with a respectable-looking confidence.

The gate reads confidence, not the answer. That ordering is the entire safety property. Branching on team.choice first and checking confidence later means you have already acted.

Picking a Threshold Is Your Job

Every guide on this subject says "route on confidence" and then moves on. I want to stay here, because this is the step where a demo becomes a system, and because I asked an AI answer engine the operational version of this question and got back the following:

"integrate it to make fast, structured decisions, and set thresholds for fallback to more complex models if needed. Test a small, high-volume workflow first to ensure effectiveness."

That is a sentence about thresholds containing no threshold. It names no field, no value, and no mechanism. If that is the state of the answer, here is a better one.

The number comes from consequences, not from a guide. TypeSafe's docs use 0.5 as a review floor and 0.9 before a destructive action, and say plainly that these are examples rather than defaults. Our own documentation says to pick thresholds against your own data and consequences rather than copying a number from an example. The 0.7 in the workflow above is a placeholder and I labelled it as one inside the sticky note.

Run it in shadow first. Send real traffic through the decision without letting it act. Record what the model answered beside what a person actually decided. After a few hundred rows you can see where the disagreements cluster, and the threshold is wherever the disagreement rate falls below what the business can absorb.

Use three bands, not two. This is the same shape as the four guardrail layers every agent needs, applied to one decision. High acts automatically. Medium asks for confirmation, or gathers more evidence, or escalates to a reasoning model. Low goes to a person. A binary gate throws away the most useful information the model gave you, which is that it was unsure.

Re-check it. Traffic shape drifts. A threshold that was right in March describes March. Put a reminder in the calendar the way you would for a certificate.

One more thing, and it is the uncomfortable one. Calibration is a property of the aggregate, not of the individual answer. "Right about 90% of the time at 0.9" is a statement about a thousand decisions. It tells you nothing about this decision. Build for the distribution, and keep a human path for the tail.

What Breaks in Production

This is the section the explainers do not have, and it is written from our own error-handling code rather than from imagination.

The key gets rejected. A 401 should name the credential, not the endpoint. When you have three decision credentials across staging and production, "auth failed" costs you twenty minutes and "rejected the API key on this credential" costs you none.

The provider refuses the request. A 422 means your question was malformed in a way the provider caught. Carry the provider's own field-level message through to the node error instead of replacing it with something generic. The provider knows which field; you do not.

You get rate limited mid-run. 429 and 529 are transient, and the correct response is retry rather than failure. Rate limits on Jev during early access are quoted at 250,000 tokens per second and 1,200 requests per minute, adjusting dynamically. That is generous until you map a decision over a backlog, which is exactly the use case the pricing invites.

The question is broken before you send it. Duplicate ids, an empty id, an unknown type, a choice with no options, a score with fewer than two levels. We validate all of these before any request leaves the machine, because a request that cannot succeed should not cost a round trip or a token.

Nobody is awake. The low-confidence branch has to go somewhere that survives the absence of a person at a terminal. A notification, a queue, a review link. Not a retry, and not a log line.

What Heym is: Heym is a source-available, self-hosted AI workflow automation platform with a visual canvas for multi-agent pipelines, RAG and MCP. Everything described about our own product in this article comes from the shipped source and documentation, not from a roadmap.

And one honest operational gap on our side. Decision models are absent from the LLM pricing tables we sync, so the cost column in traces stays empty for these calls. Token counts still record, and you can add a pricing override to get the number back. I would rather you read that here than find it during a budget review.

Five Places This Earns Its Keep

We shipped five templates alongside the node. They are on the templates page and each one is a different shape of decision.

Support triage asks all three question types in one call: is it urgent, which team owns it, how much business activity is affected. Two thresholds feed one priority gate, then a Switch routes the rest.

Smart model router decides which LLM should answer before paying for the expensive one. This is the case with the clearest arithmetic, because the decision costs a fraction of a cent and the model it avoids calling does not. It is the dynamic half of model routing, and it slots into any orchestration pattern that moves work between models.

RAG reranker scores retrieved chunks for relevance before they reach the context window. Retrieval gives you similarity; a score question gives you judgment, and the two disagree more often than is comfortable.

Agent tool gate sits in front of a tool call an agent wants to make and asks whether it should happen. This is the one I would reach for first, because it puts a calibrated check in front of the step that actually touches something.

Post quality extension backend scores a draft before it is published. A rubric a person wrote, applied consistently, at a cost that makes it worth applying every time.

The pattern across all five: the decision model never acts. It reports, and something downstream decides what the report is worth. That separation is not an accident of our design, it is the only safe way to use a component that is calibrated in aggregate.

What We Got Wrong

Two things, and both are ours.

The first is timing. The node shipped with the cost column silently empty, and we documented that in the node reference rather than in the credential dialog where somebody would actually hit it. A gap documented in the place nobody is looking is a gap.

The second is bigger and it is about this article. I started writing it as a Jev piece. Jev is the funded launch, Jev is what people are searching, and the draft had Laya in one paragraph near the end as an "open alternative". Then I read both schemas side by side and the paragraph was wrong. It is not an alternative, it is the same contract with a different deployment story, and framing it as a rivalry would have sent readers into a benchmark argument that has no bearing on what they need to build.

A third entrant is already circulating. The category will be plural within the month. Writing about the contract ages well and writing about one vendor does not, and I only worked that out because the schemas forced me to.

What To Do This Week

Find the calls that were never language tasks. Go through your existing LLM calls and mark the ones whose output you immediately parse into a branch. If an if statement consumes the answer rather than a person reading it, that is a decision, and it is currently being made by a text generator.

Price one of them. Take the highest-volume item on that list and do the arithmetic at the TypeSafe Jev rate of $0.042 per million input tokens with output free. At roughly 300 tokens a call you are at about $1.26 per hundred thousand. Compare that with what the same volume costs you now.

Build the gate before the routing. Whatever you wire first, put the confidence check in front of the branch. It is two minutes at the start and a rewrite later.

Run it in shadow for a week. Do not let it act. Collect the disagreements. Set the threshold from what you find, then turn it on for the confident band only.

Leave the rest on the LLM. Generation, summarization, code, open-ended reasoning. The same split applies in document pipelines, where recognition, extraction and the decision to trust a value are three different jobs. The win here is narrow and real, and overreaching for it is the fastest way to make the narrow real win look bad.

If you want the shortest possible start, copy the triage template, point it at an endpoint, and change one threshold. Everything above is what you will want to know by the second week.


Frequently Asked Questions

What is a System One model?

A System One model answers typed questions about a state and returns calibrated probabilities instead of generated text. You send it a block of state plus a map of questions, and it evaluates them in a single parallel pass. There is no prompt, no system instruction, no temperature and no tool calling. The name comes from Daniel Kahneman's Thinking, Fast and Slow, where System 1 is fast intuitive judgment and System 2 is slow deliberate reasoning. TypeSafe coined the category name when it launched Jev in September 2026. The practical difference from an LLM is that the answer is a number with a distribution behind it rather than a string you have to parse and validate.

How is Jev different from an LLM with structured output?

Structured output constrains the shape of generated text. The model still generates tokens one at a time, and a confidence field inside that JSON is itself generated text, so it is a number the model wrote rather than a number the model measured. Jev does not generate at all. It returns a probability distribution over the options you defined, and the confidence is computed from the shape of that distribution: concentrated on one option means high, spread across several means low. TypeSafe describes its zero type-error rate as structural rather than empirical, which is an important distinction. It guarantees the answer has a valid shape, not that the answer is right.

Is Laya compatible with Jev?

At the level that matters for integration, yes. Laya uses the same three question types (noul, choice, score), the same per-question fields (type, instructions, criteria), and returns answers keyed by your own question ids. The receptron Node.js package describes Laya in those words, as the open-source Jev-compatible System 1 decision model. The difference is transport rather than contract. Jev is a hosted API you reach over HTTPS, while Laya ships as Apache-2.0 weights you run yourself through ONNX Runtime. To use Laya from a workflow tool that speaks HTTP, you put a small server in front of the weights, or point the node at whichever endpoint you already run.

How do I pick a confidence threshold?

From your own data and your own consequences, never from an example in a guide. The number depends entirely on what a wrong answer costs. TypeSafe's documentation uses 0.5 as a review floor and 0.9 before a destructive action, and is explicit that these are illustrations rather than defaults. The practical method is to run the decision in shadow mode first: send real traffic through it, record the answers next to what a person actually decided, then set the threshold where the disagreement rate drops below what you can absorb. A threshold copied from a blog post is a guess wearing a decimal point.

What happens when a decision model returns low confidence?

Nothing, unless you build the branch. The model reports uncertainty honestly and then it is finished; acting on that report is your workflow's job. The pattern that works is a three-way split. High confidence acts automatically. Medium confidence asks for confirmation or gathers more evidence first. Low confidence routes to a person, or falls back to a slower and more capable model. In a visual builder this is a Condition node reading the confidence field and sending the false branch to a human review step rather than to a retry. Retrying the same state against the same model usually returns the same uncertainty.

What do Jev and Laya cost to run?

Jev is priced at $0.042 per million input tokens with output free, which TypeSafe also writes as $42 per billion to make the point. A support ticket with its questions runs around 300 tokens in TypeSafe's own examples, so roughly $1.26 for 100,000 tickets of that size. Laya's cost is your own hardware, since the weights are Apache-2.0 and run locally. The cost that catches teams out is neither of those: decision models are absent from the LLM pricing tables most platforms sync, so the cost column in your traces can stay empty while token counts still record. Add a pricing override if you need the number to appear.

Can a System One model replace my LLM?

No, and the framing is wrong. It replaces the LLM calls that were never really language tasks: classify this, route that, score this on a rubric, decide whether this is urgent. Those are reflex judgments that happen to have been implemented with a text generator because a text generator was the tool in reach. Generation, summarization, code, and open-ended reasoning remain LLM work. The two compose well in practice. Use the decision model as the fast layer that classifies and routes, then hand the small slice of genuinely hard cases to a reasoning model. Calibration is what makes that handoff clean, because you can route on a threshold.


Sources

  • TypeSafe AI, Introducing System One Models and Jev, September 2026. Category definition, typed outputs, calibrated probabilities, and the structural framing of the type-error rate.
  • TypeSafe AI, Documentation, 2026. Request contract and the illustrative 0.5 and 0.9 threshold examples.
  • Convai Innovations, Laya model card, September 2026. Checkpoints, RLCD against strictly proper scoring rules, question schema, and the ~33ms single-question figure.
  • Convai Innovations, Laya project site, September 2026. Latency breakdown and multilingual coverage.
  • receptron, laya Node.js package, September 2026. Jev-compatibility statement and the published question schema used for the comparison in this article.
  • Flavio Copes, A deep dive into Jev, September 2026. Pricing arithmetic, latency ranges, rate limits, the Jevons naming, and the confidence-band pattern.
  • LangChain, Building a Harness with Jev, September 2026. Code-first harness construction.
  • ONNX Runtime, 2026. Runtime used to execute Laya weights without PyTorch.
  • Wikipedia, Thinking, Fast and Slow and William Stanley Jevons. Origin of the System 1 framing and the Jev name.

Steps at a glance

  1. Decide whether your call is a judgment or a language task. Look at the LLM calls you already make and find the ones whose output you immediately parse into a branch. If the answer is consumed by an if statement rather than read by a person, it is a judgment and a decision model fits. If the output is prose, code, or a summary, leave it on the LLM.
  2. Create the credential. Add a Decision Model credential with the endpoint base URL and, if your provider needs one, an API key. Heym appends the evaluation path to whatever base URL you supply. Test Connection sends one tiny question to confirm the endpoint and key work before you build anything on top of them.
  3. Write the state, not just the question. State is the situation the model judges, and it accepts a string, an object, or an array. A field holding exactly one expression keeps its type, so passing the input object sends the object rather than its text. Give each question enough to answer with: source text, identities, relationships, policies, and current facts.
  4. Write questions that carry their own meaning. The question id is how your workflow reads the answer back and is never sent to the model, so all the meaning has to live in the instructions. Naming an id is_urgent and writing Is it? as the instruction gives the model nothing. For a choice question, always include an option that covers none of these, because the model cannot pick an option you did not offer.
  5. Gate on confidence before you branch on the answer. Put a Condition node between the decision and the routing. Check the confidence field first and send anything below your threshold to a human review path. Only the confident cases should reach the Switch node that routes on the chosen option. This ordering is what turns a probability into a safe automation.
  6. Validate the threshold against real traffic before you trust it. Run the decision in shadow mode next to the existing process and record what the model answered beside what a person decided. Set your threshold where the disagreement rate falls below what the business can absorb, then re-check it after the first month, because the traffic shape changes and the threshold does not follow it on its own.
Vol. 01On AI Infrastructure
Self-hosted · Source Available
Heym
An opinion, plainly stated
— on what production AI actually needs

A chatbot is not
a workflow system.

The argument

Wrapping an LLM in a nice UI solves a demo. It does not solve production. The moment an AI step has operational consequences, you need retrieval, approvals, retries, traces, and evals — in one runtime you actually control.

What breaks first

× silent failures
× no audit trail
× untestable prompts
× glue code sprawl

What heym gives you

agents & RAG
HITL approvals
traces & evals
self-hosted
Ceren Kaya Akgün
Ceren Kaya Akgün

Co-founder & Engineer

Ceren is a co-founder and engineer at Heym, working on AI workflow orchestration and the visual canvas editor. She writes about AI automation, multi-agent systems, and the practitioner experience of building production LLM pipelines.

Reviewed by Mehmet Burak Akgün. Statistics cite named, dated sources, and claims about Heym are verified against the source code before publication. See our editorial policy or report a correction.

Enjoyed this post? Get the next one in your inbox.

A monthly note with practical ideas for building AI workflows that hold up in production. No noise, and you can unsubscribe anytime.

No spam, no marketing fluff