Deep dives / One Pass, No Prose

One Pass, No Prose

A chatbot writes an answer. A decision model picks one.

By Jim Thornton Updated 28 min read An animated explainer for people who buy inference

A typed decision model takes some text plus a fixed question and returns a probability for each allowed answer. No prose, one forward pass, nothing to parse. Pick a situation below and compare the two kinds of answer. The decision-model numbers are real: the same six requests ran through five models (four on Oct 5, 2026; Clef 27B on Oct 9).

Situation
Model

A chatbot (generative LLM)

Illustrative
Subject: Checkout broken

Hi, every customer who tries to pay on our store has been getting a 502 at the payment step for the last hour. We are losing orders. Account: acme-retail (Scale plan).

This sounds like an outage affecting payments, so I'd route it to the technical team. It's urgent since customers can't check out, and the severity is probably major or critical. I'm about 90% confident on the routing.

You get sentences. Your code has to find the answer in them, and the "90% confident" is more generated text.

Jev (hosted)

Our run

team · choice

billing 0.00
technical 1.00
sales 0.00
other 0.00

urgent · noul

yes 0.94
no 0.06

severity · score

no impact 0.00
minor 0.00
major 0.01
critical 0.99

3 questions answered in one request: 432 ms measured, TypeSafe's API, round trip from a home connection. Oct 5, 2026.

1
forward pass per request. The input is read once; no output tokens are generated.
$0
for output tokens on every hosted decision endpoint we found. You pay for input only, from about $0.04 per million.1
109
models in our catalog nineteen days after the first one shipped. Most copy the interface, not the weights.
2.2
points: the gap on the independent board between the leader and a stock 27B model with no training at all.2

Look for the dashed side quest (side quest) links. Each opens a short explainer of one basic idea in a side panel. They are also collected in a row at the end of each chapter.

Chapter 01 · Foundations

Two ways to answer a question

Both kinds of model are built from the same parts. The difference is what happens at the very end: one keeps writing words, the other scores a list of options you gave it. That difference decides the latency, the cost and what you can do with the answer.

The same question, two machines

Writing versus picking

We'll follow one support ticket through both kinds of model.

  1. The requestA chatbot's answerA decision model's viewWhat comes backSame request, two models

    Illustrative Our run · Oct 5, 2026
    state     Subject: Checkout broken / Hi, every customer who tries to pay on our store has been getting a 502 at the payment step for the last hour. We are losing orders. Account: acme-retail (Scale plan).
    questions
      team      billing · technical · sales · other
      urgent    yes · no
      severity  no impact · minor · major · critical

    This sounds like a payment outage, so the technical team should own it. It is urgent because customers cannot check out, and I would call the severity major or critical. I'm about 90% confident on the routing.

    …502 at the payment step for the last hour…  Which team should own this?
    [slot] billing   [slot] technical   [slot] sales   [slot] other
    [slot] urgent?   [slot] severity…

    Jev (hosted)

    team · choice

    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00

    urgent · noul

    yes 0.94
    no 0.06

    severity · score

    no impact 0.00
    minor 0.00
    major 0.01
    critical 0.99

    Base Laya (local)

    team · choice

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    urgent · noul

    yes 0.20
    no 0.80

    severity · score

    no impact 0.00
    minor 0.04
    major 0.85
    critical 0.11

    One ticket, three questions, every allowed answer listed. About 45 tokens, written one at a time. Each one is a separate pass through the model. Highlighted: what your code has to dig out, a hedge, and a confidence that is only text. Each [slot] is read by the scoring head. Softmax runs over each question's options, not the whole vocabulary. Jev, one request, 432 ms round trip. Three answers, each with a full distribution. Base Laya, 43 ms on a laptop. Right team, but "not urgent" at 0.80 and "major" rather than "critical".

    01 / 06

    The request

    Every request has three parts: the state (what the model looks at), one or more questions, and the options you allow for each. This exact request ran through five models for this page.

    Our run · Oct 5, 2026
  2. The requestA chatbot's answerA decision model's viewWhat comes backSame request, two models

    Illustrative Our run · Oct 5, 2026
    state     Subject: Checkout broken / Hi, every customer who tries to pay on our store has been getting a 502 at the payment step for the last hour. We are losing orders. Account: acme-retail (Scale plan).
    questions
      team      billing · technical · sales · other
      urgent    yes · no
      severity  no impact · minor · major · critical

    This sounds like a payment outage, so the technical team should own it. It is urgent because customers cannot check out, and I would call the severity major or critical. I'm about 90% confident on the routing.

    …502 at the payment step for the last hour…  Which team should own this?
    [slot] billing   [slot] technical   [slot] sales   [slot] other
    [slot] urgent?   [slot] severity…

    Jev (hosted)

    team · choice

    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00

    urgent · noul

    yes 0.94
    no 0.06

    severity · score

    no impact 0.00
    minor 0.00
    major 0.01
    critical 0.99

    Base Laya (local)

    team · choice

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    urgent · noul

    yes 0.20
    no 0.80

    severity · score

    no impact 0.00
    minor 0.04
    major 0.85
    critical 0.11

    One ticket, three questions, every allowed answer listed. About 45 tokens, written one at a time. Each one is a separate pass through the model. Highlighted: what your code has to dig out, a hedge, and a confidence that is only text. Each [slot] is read by the scoring head. Softmax runs over each question's options, not the whole vocabulary. Jev, one request, 432 ms round trip. Three answers, each with a full distribution. Base Laya, 43 ms on a laptop. Right team, but "not urgent" at 0.80 and "major" rather than "critical".

    02 / 06

    A chatbot writes, one piece at a time

    A generative LLM reads the request and predicts the next token (side quest), then the next, until it decides to stop. Each piece is a weighted dice roll, and each one is a separate trip through the model.

  3. The requestA chatbot's answerA decision model's viewWhat comes backSame request, two models

    Illustrative Our run · Oct 5, 2026
    state     Subject: Checkout broken / Hi, every customer who tries to pay on our store has been getting a 502 at the payment step for the last hour. We are losing orders. Account: acme-retail (Scale plan).
    questions
      team      billing · technical · sales · other
      urgent    yes · no
      severity  no impact · minor · major · critical

    This sounds like a payment outage, so the technical team should own it. It is urgent because customers cannot check out, and I would call the severity major or critical. I'm about 90% confident on the routing.

    …502 at the payment step for the last hour…  Which team should own this?
    [slot] billing   [slot] technical   [slot] sales   [slot] other
    [slot] urgent?   [slot] severity…

    Jev (hosted)

    team · choice

    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00

    urgent · noul

    yes 0.94
    no 0.06

    severity · score

    no impact 0.00
    minor 0.00
    major 0.01
    critical 0.99

    Base Laya (local)

    team · choice

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    urgent · noul

    yes 0.20
    no 0.80

    severity · score

    no impact 0.00
    minor 0.04
    major 0.85
    critical 0.11

    One ticket, three questions, every allowed answer listed. About 45 tokens, written one at a time. Each one is a separate pass through the model. Highlighted: what your code has to dig out, a hedge, and a confidence that is only text. Each [slot] is read by the scoring head. Softmax runs over each question's options, not the whole vocabulary. Jev, one request, 432 ms round trip. Three answers, each with a full distribution. Base Laya, 43 ms on a laptop. Right team, but "not urgent" at 0.80 and "major" rather than "critical".

    03 / 06

    Then you have to read it

    Your code now has to find the answer inside a sentence. It might hedge ("major or critical"), and the confidence is a phrase it wrote, not a measurement. Why "90% confident" isn't a probability (side quest)

  4. The requestA chatbot's answerA decision model's viewWhat comes backSame request, two models

    Illustrative Our run · Oct 5, 2026
    state     Subject: Checkout broken / Hi, every customer who tries to pay on our store has been getting a 502 at the payment step for the last hour. We are losing orders. Account: acme-retail (Scale plan).
    questions
      team      billing · technical · sales · other
      urgent    yes · no
      severity  no impact · minor · major · critical

    This sounds like a payment outage, so the technical team should own it. It is urgent because customers cannot check out, and I would call the severity major or critical. I'm about 90% confident on the routing.

    …502 at the payment step for the last hour…  Which team should own this?
    [slot] billing   [slot] technical   [slot] sales   [slot] other
    [slot] urgent?   [slot] severity…

    Jev (hosted)

    team · choice

    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00

    urgent · noul

    yes 0.94
    no 0.06

    severity · score

    no impact 0.00
    minor 0.00
    major 0.01
    critical 0.99

    Base Laya (local)

    team · choice

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    urgent · noul

    yes 0.20
    no 0.80

    severity · score

    no impact 0.00
    minor 0.04
    major 0.85
    critical 0.11

    One ticket, three questions, every allowed answer listed. About 45 tokens, written one at a time. Each one is a separate pass through the model. Highlighted: what your code has to dig out, a hedge, and a confidence that is only text. Each [slot] is read by the scoring head. Softmax runs over each question's options, not the whole vocabulary. Jev, one request, 432 ms round trip. Three answers, each with a full distribution. Base Laya, 43 ms on a laptop. Right team, but "not urgent" at 0.80 and "major" rather than "critical".

    04 / 06

    A decision model reads once and scores

    A decision model reads the whole request in one forward pass (side quest). Each option has a marked slot, and a small head scores every slot. A softmax (side quest) turns the scores into percentages that add up to 100.

  5. The requestA chatbot's answerA decision model's viewWhat comes backSame request, two models

    Illustrative Our run · Oct 5, 2026
    state     Subject: Checkout broken / Hi, every customer who tries to pay on our store has been getting a 502 at the payment step for the last hour. We are losing orders. Account: acme-retail (Scale plan).
    questions
      team      billing · technical · sales · other
      urgent    yes · no
      severity  no impact · minor · major · critical

    This sounds like a payment outage, so the technical team should own it. It is urgent because customers cannot check out, and I would call the severity major or critical. I'm about 90% confident on the routing.

    …502 at the payment step for the last hour…  Which team should own this?
    [slot] billing   [slot] technical   [slot] sales   [slot] other
    [slot] urgent?   [slot] severity…

    Jev (hosted)

    team · choice

    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00

    urgent · noul

    yes 0.94
    no 0.06

    severity · score

    no impact 0.00
    minor 0.00
    major 0.01
    critical 0.99

    Base Laya (local)

    team · choice

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    urgent · noul

    yes 0.20
    no 0.80

    severity · score

    no impact 0.00
    minor 0.04
    major 0.85
    critical 0.11

    One ticket, three questions, every allowed answer listed. About 45 tokens, written one at a time. Each one is a separate pass through the model. Highlighted: what your code has to dig out, a hedge, and a confidence that is only text. Each [slot] is read by the scoring head. Softmax runs over each question's options, not the whole vocabulary. Jev, one request, 432 ms round trip. Three answers, each with a full distribution. Base Laya, 43 ms on a laptop. Right team, but "not urgent" at 0.80 and "major" rather than "critical".

    05 / 06

    What you get back

    Always one of your options, a probability for every option, and no text to parse. Three questions were answered in the same pass: the team, whether it's urgent, and a severity score. Jev put 0.99 on "critical" and 0.94 on "urgent".

  6. The requestA chatbot's answerA decision model's viewWhat comes backSame request, two models

    Illustrative Our run · Oct 5, 2026
    state     Subject: Checkout broken / Hi, every customer who tries to pay on our store has been getting a 502 at the payment step for the last hour. We are losing orders. Account: acme-retail (Scale plan).
    questions
      team      billing · technical · sales · other
      urgent    yes · no
      severity  no impact · minor · major · critical

    This sounds like a payment outage, so the technical team should own it. It is urgent because customers cannot check out, and I would call the severity major or critical. I'm about 90% confident on the routing.

    …502 at the payment step for the last hour…  Which team should own this?
    [slot] billing   [slot] technical   [slot] sales   [slot] other
    [slot] urgent?   [slot] severity…

    Jev (hosted)

    team · choice

    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00

    urgent · noul

    yes 0.94
    no 0.06

    severity · score

    no impact 0.00
    minor 0.00
    major 0.01
    critical 0.99

    Base Laya (local)

    team · choice

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    urgent · noul

    yes 0.20
    no 0.80

    severity · score

    no impact 0.00
    minor 0.04
    major 0.85
    critical 0.11

    One ticket, three questions, every allowed answer listed. About 45 tokens, written one at a time. Each one is a separate pass through the model. Highlighted: what your code has to dig out, a hedge, and a confidence that is only text. Each [slot] is read by the scoring head. Softmax runs over each question's options, not the whole vocabulary. Jev, one request, 432 ms round trip. Three answers, each with a full distribution. Base Laya, 43 ms on a laptop. Right team, but "not urgent" at 0.80 and "major" rather than "critical".

    06 / 06

    Same interface, very different models

    Base Laya, a 421-million-parameter open encoder, got the same request. It picked the right team at 0.62 and called the ticket not urgent. Both models are "typed", but one has learned what the options mean and one hasn't. The probabilities are only as useful as the training behind them, which is what calibration (side quest) measures.

Where the difference lives

Same engine, different last step

Most of the model is the same in both cases: a stack of layers that turns words into vectors that capture meaning. The only real change is the readout at the end, plus how it was trained.

  1. Inside a transformer

    checkoutfailing502…team?billingtechnical score all ~250,000 tokens → sample score only your options Encoder: “team?” looks both ways Decoder: only backwards checkoutfailing502…team?billingtechnical score all ~250,000 tokens → sample score only your options Encoder: “team?” looks both ways Decoder: only backwards

    Four layers shown; real models have 24 to 64. Each layer refines every token's vector using the others. Chatbot ending: the last vector scores every token in the vocabulary, then one is sampled. Repeat per word. Decision-model ending: read the vectors at the option slots and score just those. Who each token can see. This is the main architectural difference between an encoder like Laya and a decoder like Qwen.

    01 / 04

    The shared engine

    Both start as a transformer: dozens of layers that pass a vector (a list of numbers) for every token, each layer refining it using the tokens around it. By the top layer, each vector carries the meaning of its token in context.

  2. Inside a transformer

    checkoutfailing502…team?billingtechnical score all ~250,000 tokens → sample score only your options Encoder: “team?” looks both ways Decoder: only backwards checkoutfailing502…team?billingtechnical score all ~250,000 tokens → sample score only your options Encoder: “team?” looks both ways Decoder: only backwards

    Four layers shown; real models have 24 to 64. Each layer refines every token's vector using the others. Chatbot ending: the last vector scores every token in the vocabulary, then one is sampled. Repeat per word. Decision-model ending: read the vectors at the option slots and score just those. Who each token can see. This is the main architectural difference between an encoder like Laya and a decoder like Qwen.

    02 / 04

    Ending 1: predict the next word

    A chatbot takes the last vector and scores every token in its vocabulary, around 150,000 to 260,000 of them, then samples one. Repeat for every word it writes.

  3. Inside a transformer

    checkoutfailing502…team?billingtechnical score all ~250,000 tokens → sample score only your options Encoder: “team?” looks both ways Decoder: only backwards checkoutfailing502…team?billingtechnical score all ~250,000 tokens → sample score only your options Encoder: “team?” looks both ways Decoder: only backwards

    Four layers shown; real models have 24 to 64. Each layer refines every token's vector using the others. Chatbot ending: the last vector scores every token in the vocabulary, then one is sampled. Repeat per word. Decision-model ending: read the vectors at the option slots and score just those. Who each token can see. This is the main architectural difference between an encoder like Laya and a decoder like Qwen.

    03 / 04

    Ending 2: score your options

    A decision model ignores the vocabulary. It takes the vectors sitting at your option slots and scores only those, so the softmax runs over 4 options, not 260,000 tokens. That's the whole trick of a "typed" model.

    Documented in Laya, Jeeves and Clef source4,6,7
  4. Inside a transformer

    checkoutfailing502…team?billingtechnical score all ~250,000 tokens → sample score only your options Encoder: “team?” looks both ways Decoder: only backwards checkoutfailing502…team?billingtechnical score all ~250,000 tokens → sample score only your options Encoder: “team?” looks both ways Decoder: only backwards

    Four layers shown; real models have 24 to 64. Each layer refines every token's vector using the others. Chatbot ending: the last vector scores every token in the vocabulary, then one is sampled. Repeat per word. Decision-model ending: read the vectors at the option slots and score just those. Who each token can see. This is the main architectural difference between an encoder like Laya and a decoder like Qwen.

    04 / 04

    Two ways to read the request

    Laya is an encoder: every token can look at every other token, before and after it. Qwen, the base of Jeeves and Clef, is a decoder: each token only looks backwards, which is what you need to write text. Encoder vs decoder (side quest)

Why this matters to an inference bill

One pass, not sixty

Serving a model has two phases: prefill, which reads the prompt, and decode, which writes the answer. A decision model is a prefill-only workload.

  1. Passes through the modelWhat you payWhere the time goesAsk everything at once

    Chat model

    Thetechnicalteamshouldownthisticket.Itisurgentbecausecustomerscannotcompletecheckout,andtheseverityismajororcritical.Iwouldrouteitimmediatelyandpagetheon-callengineerforthepaymentservice.
    37passes
    960 msillustrative time

    Decision model

    prefill → score options
    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00
    01passes
    0 ms432 msmeasured (Jev)
    $1.26per day, decision model at $0.042/M in, $0 out
    $8.10per day, small LLM at $0.15/M in + 60 tokens out at $0.60/M
    6.4×ratio

    List prices as of Oct 2026: TypeSafe Jev $0.042 per million input tokens; a 9B to 31B open model on a serverless catalog typically $0.09–$0.15 in and $0.40–$0.60 out. Your numbers will differ; the shape won't.

    Chat
    Decision
    prefill: parallel, compute-bound, batches welldecode: sequential, memory-bound
    one state
    teamurgentseverityrefund due?SLA breached?needs engineer?customer tiersentimentduplicate?languagePII present?escalate?reply template

    Chat model: one prefill pass, then one pass per output token (illustrative 25 ms each). The answer still has to be parsed. Decision model: the same prefill, then the option slots are read. Jev's measured round trip for all three questions was 432 ms; Clef 27B hosted 1,255 ms; Clef Flash on a laptop 5,569 ms; Laya 43 ms. Input tokens are the whole bill. Fewer, better-chosen tokens in the state is the main cost lever. Bars are schematic. A chat request spends most of its wall time in decode; a decision request has no decode. Thirteen questions, one state, one pass. The questions are scored together, so the marginal question is nearly free.

    01 / 05

    A chat answer is a loop

    Reading the ticket is one pass. Then the model writes a 48-token answer, and every token is another pass that reads the whole context again. In the figure, each chip is a pass. The timings are illustrative, but the shape is exact.

  2. Passes through the modelWhat you payWhere the time goesAsk everything at once

    Chat model

    Thetechnicalteamshouldownthisticket.Itisurgentbecausecustomerscannotcompletecheckout,andtheseverityismajororcritical.Iwouldrouteitimmediatelyandpagetheon-callengineerforthepaymentservice.
    37passes
    960 msillustrative time

    Decision model

    prefill → score options
    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00
    01passes
    0 ms432 msmeasured (Jev)
    $1.26per day, decision model at $0.042/M in, $0 out
    $8.10per day, small LLM at $0.15/M in + 60 tokens out at $0.60/M
    6.4×ratio

    List prices as of Oct 2026: TypeSafe Jev $0.042 per million input tokens; a 9B to 31B open model on a serverless catalog typically $0.09–$0.15 in and $0.40–$0.60 out. Your numbers will differ; the shape won't.

    Chat
    Decision
    prefill: parallel, compute-bound, batches welldecode: sequential, memory-bound
    one state
    teamurgentseverityrefund due?SLA breached?needs engineer?customer tiersentimentduplicate?languagePII present?escalate?reply template

    Chat model: one prefill pass, then one pass per output token (illustrative 25 ms each). The answer still has to be parsed. Decision model: the same prefill, then the option slots are read. Jev's measured round trip for all three questions was 432 ms; Clef 27B hosted 1,255 ms; Clef Flash on a laptop 5,569 ms; Laya 43 ms. Input tokens are the whole bill. Fewer, better-chosen tokens in the state is the main cost lever. Bars are schematic. A chat request spends most of its wall time in decode; a decision request has no decode. Thirteen questions, one state, one pass. The questions are scored together, so the marginal question is nearly free.

    02 / 05

    A decision is the first pass, and that's it

    The decision model does the prefill, reads the option slots, and stops. There is no decode phase. In our runs Jev answered the ticket's three questions in one request in 160 to 430 ms over the network; a 9B open model on a laptop took about 0.6 s; a 0.4B encoder took 26 to 54 ms.

    Our run · Oct 5, 2026
  3. Passes through the modelWhat you payWhere the time goesAsk everything at once

    Chat model

    Thetechnicalteamshouldownthisticket.Itisurgentbecausecustomerscannotcompletecheckout,andtheseverityismajororcritical.Iwouldrouteitimmediatelyandpagetheon-callengineerforthepaymentservice.
    37passes
    960 msillustrative time

    Decision model

    prefill → score options
    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00
    01passes
    0 ms432 msmeasured (Jev)
    $1.26per day, decision model at $0.042/M in, $0 out
    $8.10per day, small LLM at $0.15/M in + 60 tokens out at $0.60/M
    6.4×ratio

    List prices as of Oct 2026: TypeSafe Jev $0.042 per million input tokens; a 9B to 31B open model on a serverless catalog typically $0.09–$0.15 in and $0.40–$0.60 out. Your numbers will differ; the shape won't.

    Chat
    Decision
    prefill: parallel, compute-bound, batches welldecode: sequential, memory-bound
    one state
    teamurgentseverityrefund due?SLA breached?needs engineer?customer tiersentimentduplicate?languagePII present?escalate?reply template

    Chat model: one prefill pass, then one pass per output token (illustrative 25 ms each). The answer still has to be parsed. Decision model: the same prefill, then the option slots are read. Jev's measured round trip for all three questions was 432 ms; Clef 27B hosted 1,255 ms; Clef Flash on a laptop 5,569 ms; Laya 43 ms. Input tokens are the whole bill. Fewer, better-chosen tokens in the state is the main cost lever. Bars are schematic. A chat request spends most of its wall time in decode; a decision request has no decode. Thirteen questions, one state, one pass. The questions are scored together, so the marginal question is nearly free.

    03 / 05

    What you pay

    Every hosted decision endpoint we found bills input tokens only; output is free because there is none. At Jev's $0.042 per million, a day of tickets costs cents.1 Drag the sliders. The comparison line uses a small general LLM's list price plus a short answer.

  4. Passes through the modelWhat you payWhere the time goesAsk everything at once

    Chat model

    Thetechnicalteamshouldownthisticket.Itisurgentbecausecustomerscannotcompletecheckout,andtheseverityismajororcritical.Iwouldrouteitimmediatelyandpagetheon-callengineerforthepaymentservice.
    37passes
    960 msillustrative time

    Decision model

    prefill → score options
    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00
    01passes
    0 ms432 msmeasured (Jev)
    $1.26per day, decision model at $0.042/M in, $0 out
    $8.10per day, small LLM at $0.15/M in + 60 tokens out at $0.60/M
    6.4×ratio

    List prices as of Oct 2026: TypeSafe Jev $0.042 per million input tokens; a 9B to 31B open model on a serverless catalog typically $0.09–$0.15 in and $0.40–$0.60 out. Your numbers will differ; the shape won't.

    Chat
    Decision
    prefill: parallel, compute-bound, batches welldecode: sequential, memory-bound
    one state
    teamurgentseverityrefund due?SLA breached?needs engineer?customer tiersentimentduplicate?languagePII present?escalate?reply template

    Chat model: one prefill pass, then one pass per output token (illustrative 25 ms each). The answer still has to be parsed. Decision model: the same prefill, then the option slots are read. Jev's measured round trip for all three questions was 432 ms; Clef 27B hosted 1,255 ms; Clef Flash on a laptop 5,569 ms; Laya 43 ms. Input tokens are the whole bill. Fewer, better-chosen tokens in the state is the main cost lever. Bars are schematic. A chat request spends most of its wall time in decode; a decision request has no decode. Thirteen questions, one state, one pass. The questions are scored together, so the marginal question is nearly free.

    04 / 05

    Where the time goes

    Prefill runs the prompt's tokens in parallel, so it is compute-bound and batches well. Decode is sequential and memory-bound: each token re-reads the cache. A decision model never enters the memory-bound phase, which is why the fastest entries on the independent board sit at 6 to 40 ms on a single GPU.2,10 Prefill vs decode (side quest)

  5. Passes through the modelWhat you payWhere the time goesAsk everything at once

    Chat model

    Thetechnicalteamshouldownthisticket.Itisurgentbecausecustomerscannotcompletecheckout,andtheseverityismajororcritical.Iwouldrouteitimmediatelyandpagetheon-callengineerforthepaymentservice.
    37passes
    960 msillustrative time

    Decision model

    prefill → score options
    billing 0.00
    technical 1.00
    sales 0.00
    other 0.00
    01passes
    0 ms432 msmeasured (Jev)
    $1.26per day, decision model at $0.042/M in, $0 out
    $8.10per day, small LLM at $0.15/M in + 60 tokens out at $0.60/M
    6.4×ratio

    List prices as of Oct 2026: TypeSafe Jev $0.042 per million input tokens; a 9B to 31B open model on a serverless catalog typically $0.09–$0.15 in and $0.40–$0.60 out. Your numbers will differ; the shape won't.

    Chat
    Decision
    prefill: parallel, compute-bound, batches welldecode: sequential, memory-bound
    one state
    teamurgentseverityrefund due?SLA breached?needs engineer?customer tiersentimentduplicate?languagePII present?escalate?reply template

    Chat model: one prefill pass, then one pass per output token (illustrative 25 ms each). The answer still has to be parsed. Decision model: the same prefill, then the option slots are read. Jev's measured round trip for all three questions was 432 ms; Clef 27B hosted 1,255 ms; Clef Flash on a laptop 5,569 ms; Laya 43 ms. Input tokens are the whole bill. Fewer, better-chosen tokens in the state is the main cost lever. Bars are schematic. A chat request spends most of its wall time in decode; a decision request has no decode. Thirteen questions, one state, one pass. The questions are scored together, so the marginal question is nearly free.

    05 / 05

    Ask everything at once

    Because the state is read once and the questions are scored together, you should ask every question you might need in one call. TypeSafe's GDPR cookbook reports 13 questions in one call as 12 times cheaper and 10 times faster than 13 separate calls.9 The ticket example already does this with three.

    TypeSafe cookbook · vendor figure

Side quests · foundations

Scroll sideways

Foundations

Tokens

checkout

Models don't see words. They see tokens: common words whole, rarer words in pieces. "checkout" might be one token and "acme-retail" four. Prices, context limits and speeds are all counted in tokens. A rule of thumb for English is about ¾ of a word per token.

Foundations

Scores to percentages: softmax

option 10.67
option 20.24
option 30.09

A model's raw outputs are scores called logits, which can be any number. Softmax turns them into percentages that add to 100: it raises e to each score, then divides by the total. Every point of score difference is a factor of about 2.7. Drag the scores to see it.

Foundations

One forward pass

A forward pass is one trip of the input up through every layer. A chatbot does one pass per token it writes, so a 60-token answer is 60 passes. A decision model does one pass and reads the answer off the top. That is why Laya takes milliseconds and why a reasoning decision model, which writes tokens first, is back to many passes.

Foundations

Prefill vs decode

Prefill processes the whole prompt at once and builds the KV cache; it is parallel and compute-bound. Decode produces the answer one token at a time, re-reading the cache each step; it is sequential and memory-bandwidth-bound. Serving stacks tune the two differently (chunked prefill, speculative decoding, disaggregation). A decision model is all prefill, so its latency floor is set by compute and its throughput by batch size.

Foundations

Encoder vs decoder

An encoder lets every token look both ways, which is good for understanding a fixed input. A decoder only lets each token look backwards, which is what lets it write text one token at a time. Both can be turned into decision models; they just put the option slot in different places.

Foundations

Why "I'm 90% confident" isn't a probability

When a chatbot writes "90%", it is predicting what text should come next, not measuring how often it is right. Studies find these stated numbers are sometimes reasonable and sometimes not; you only know by testing on your data. In our email tests Claude Haiku's stated confidence was better calibrated than GPT-4.1-mini's actual token probabilities, which shows how little the number's origin tells you.

Foundations

Calibration

A model is calibrated when its 80%-sure answers are right about 80% of the time. Group answers by confidence and compare to the actual hit rate. Bars under the diagonal mean overconfident. It is a property of many answers, never a guarantee about one.

Chapter 02 · Under the hood

Three ways to build one

Nearly every entry on the independent board is one of three designs: a small encoder with option slots, a chatbot model with a new scoring head, or an unchanged LLM read at a single token. Here is what each does with a request, using open models whose code we could read.

Design 1 of 3

An encoder that never writes

Laya: 421 million parameters, built on ModernBERT-large. It runs on a laptop in about 20 to 50 ms per request. It was never a chatbot. The same design appears in Lavoir, Julia-1 and the mmBERT entries.

  1. Laya's view of the request

    [CLS]Subject:Checkoutbroken…502atthepaymentstep…Whichteam?[MASK]billing[MASK]technical[MASK]sales[MASK]other
    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 0.5

    billing 0.17
    technical 0.82
    sales 0.00
    other 0.01

    T = 1

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 2

    billing 0.30
    technical 0.45
    sales 0.12
    other 0.13

    The ticket, the question and the four options in one row. The four outlined [MASK] chips are the answer slots. Every token's vector is updated using every other token, in both directions, across 28 layers. Base Laya's real output for the ticket. Right answer, but only 62% sure, with 'billing' and 'other' close behind. The same scores at different temperatures. The order never changes; only how spread out the bars are. Base Laya on our jobs: 0.62 on keyword buckets (majority guess 0.54), 0.36 on intent, 0.61 on email category, 0.50 on the seven-way form sort. Fine-tuned on about 1,300 keyword labels: 0.89.

    01 / 05

    The request becomes one row of tokens

    Laya lays out the state, the question and every option in one row. Each option gets a [MASK] token in front of it. In normal BERT training, [MASK] means "guess the missing word". Laya reuses it as a slot where the answer will be read.

    Documented · rl_common.py6
  2. Laya's view of the request

    [CLS]Subject:Checkoutbroken…502atthepaymentstep…Whichteam?[MASK]billing[MASK]technical[MASK]sales[MASK]other
    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 0.5

    billing 0.17
    technical 0.82
    sales 0.00
    other 0.01

    T = 1

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 2

    billing 0.30
    technical 0.45
    sales 0.12
    other 0.13

    The ticket, the question and the four options in one row. The four outlined [MASK] chips are the answer slots. Every token's vector is updated using every other token, in both directions, across 28 layers. Base Laya's real output for the ticket. Right answer, but only 62% sure, with 'billing' and 'other' close behind. The same scores at different temperatures. The order never changes; only how spread out the bars are. Base Laya on our jobs: 0.62 on keyword buckets (majority guess 0.54), 0.36 on intent, 0.61 on email category, 0.50 on the seven-way form sort. Fine-tuned on about 1,300 keyword labels: 0.89.

    02 / 05

    Everything reads everything

    Because Laya is an encoder, each slot can look at the whole request in both directions: the ticket, the question, and its own option text. By the top layer, the vector at each slot summarizes "how well does this option fit this ticket".

  3. Laya's view of the request

    [CLS]Subject:Checkoutbroken…502atthepaymentstep…Whichteam?[MASK]billing[MASK]technical[MASK]sales[MASK]other
    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 0.5

    billing 0.17
    technical 0.82
    sales 0.00
    other 0.01

    T = 1

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 2

    billing 0.30
    technical 0.45
    sales 0.12
    other 0.13

    The ticket, the question and the four options in one row. The four outlined [MASK] chips are the answer slots. Every token's vector is updated using every other token, in both directions, across 28 layers. Base Laya's real output for the ticket. Right answer, but only 62% sure, with 'billing' and 'other' close behind. The same scores at different temperatures. The order never changes; only how spread out the bars are. Base Laya on our jobs: 0.62 on keyword buckets (majority guess 0.54), 0.36 on intent, 0.61 on email category, 0.50 on the seven-way form sort. Fine-tuned on about 1,300 keyword labels: 0.89.

    03 / 05

    Score each slot, then softmax

    A small scorer turns each slot's vector into one number. Softmax over just this question's options gives the percentages. These are base Laya's real numbers for the ticket: right team, 62% sure, with "billing" and "other" not far behind.

    Our run · Oct 5, 2026
  4. Laya's view of the request

    [CLS]Subject:Checkoutbroken…502atthepaymentstep…Whichteam?[MASK]billing[MASK]technical[MASK]sales[MASK]other
    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 0.5

    billing 0.17
    technical 0.82
    sales 0.00
    other 0.01

    T = 1

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 2

    billing 0.30
    technical 0.45
    sales 0.12
    other 0.13

    The ticket, the question and the four options in one row. The four outlined [MASK] chips are the answer slots. Every token's vector is updated using every other token, in both directions, across 28 layers. Base Laya's real output for the ticket. Right answer, but only 62% sure, with 'billing' and 'other' close behind. The same scores at different temperatures. The order never changes; only how spread out the bars are. Base Laya on our jobs: 0.62 on keyword buckets (majority guess 0.54), 0.36 on intent, 0.61 on email category, 0.50 on the seven-way form sort. Fine-tuned on about 1,300 keyword labels: 0.89.

    04 / 05

    Temperature: one dial for confidence

    Laya ships overconfident, so its scores are divided by a fitted number called the temperature (side quest) before the softmax. A higher temperature spreads the bars out, a lower one sharpens them. The winner never changes, only how sure it sounds.13

  5. Laya's view of the request

    [CLS]Subject:Checkoutbroken…502atthepaymentstep…Whichteam?[MASK]billing[MASK]technical[MASK]sales[MASK]other
    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 0.5

    billing 0.17
    technical 0.82
    sales 0.00
    other 0.01

    T = 1

    billing 0.28
    technical 0.62
    sales 0.04
    other 0.05

    T = 2

    billing 0.30
    technical 0.45
    sales 0.12
    other 0.13

    The ticket, the question and the four options in one row. The four outlined [MASK] chips are the answer slots. Every token's vector is updated using every other token, in both directions, across 28 layers. Base Laya's real output for the ticket. Right answer, but only 62% sure, with 'billing' and 'other' close behind. The same scores at different temperatures. The order never changes; only how spread out the bars are. Base Laya on our jobs: 0.62 on keyword buckets (majority guess 0.54), 0.36 on intent, 0.61 on email category, 0.50 on the seven-way form sort. Fine-tuned on about 1,300 keyword labels: 0.89.

    05 / 05

    The limits

    The English checkpoint reads 512 tokens at most, so a long ticket gets cut off. And out of the box it hasn't learned your categories: it scores 6 on the independent board, where the leader scores 58.2,5 Its case is speed, privacy and cost once you fine-tune it on your own labels (chapter 3).

Design 2 of 3

A chatbot model with a new last step

PostHog's Jeeves started from Qwen3.5-9B, an open chatbot model twenty times bigger than Laya, and rebuilt its last step. It is the best-documented example of the pattern Kev, Strands Decider and Cloudflare's Clef also follow. This is the part that answers "how do you make an LLM typed?"

  1. Building Jeeves

    Qwen3.5-9B · 9 billion weightsfrozen
    Structural markers<state> <q> <opt> </opt> <decide>
    Pointer head2 small matrices
    LoRA adaptersrank 16, on every layer
    TrainingSFT → RL → temperature
    Reasoningoptional, before deciding
    <state>Subject: Checkout broken …<q>team?<opt>billing</opt><opt>technical</opt>…<think>…</think><q> … <decide>
    # model/head.py, Jeeves (complete)
    class PointerHead(nn.Module):
        def __init__(self, d_embed, d_latent=256):
            self.q = nn.Linear(d_embed, d_latent)   # reads <decide>
            self.k = nn.Linear(d_embed, d_latent)   # reads each </opt>
            self.scale = d_latent ** -0.5
            self.temperature = 1.0               # fitted after training
    
        def forward(self, questions, decide):
            options = self.k(questions)
            query = self.q(decide)
            logits = (options @ query) * self.scale   # one score per option
            return logits / self.temperature
    SFT
    19,126 questions, 2 epochs
    RL (CISPO)
    9,992 questions × 8 tries, stopped at 402/624
    Temperature
    1 number, fitted on dev

    A decoder LLM, unchanged. On its own it can only write. Outlined chips are the structural markers. Optional reasoning (dashed) goes between <think> tags, then the question is repeated before <decide>. The entire decision head. It compares one vector with each option's vector, and that's it. The 9B base stays frozen; only the small LoRA adapters and the head are trained. Bar length shows how far each stage ran: SFT to the end, RL stopped at 64% of its schedule. With reasoning on, the answer still comes from the head, but the request is back to many passes: 3–10 s on an A100 in our runs.

    01 / 06

    Start: an ordinary LLM

    Qwen3.5-9B reads left to right and predicts the next token, like any chatbot. Its weights take about 21 GB. Everything it knows about language is already in there; it just has no way to output a probability per option.

  2. Building Jeeves

    Qwen3.5-9B · 9 billion weightsfrozen
    Structural markers<state> <q> <opt> </opt> <decide>
    Pointer head2 small matrices
    LoRA adaptersrank 16, on every layer
    TrainingSFT → RL → temperature
    Reasoningoptional, before deciding
    <state>Subject: Checkout broken …<q>team?<opt>billing</opt><opt>technical</opt>…<think>…</think><q> … <decide>
    # model/head.py, Jeeves (complete)
    class PointerHead(nn.Module):
        def __init__(self, d_embed, d_latent=256):
            self.q = nn.Linear(d_embed, d_latent)   # reads <decide>
            self.k = nn.Linear(d_embed, d_latent)   # reads each </opt>
            self.scale = d_latent ** -0.5
            self.temperature = 1.0               # fitted after training
    
        def forward(self, questions, decide):
            options = self.k(questions)
            query = self.q(decide)
            logits = (options @ query) * self.scale   # one score per option
            return logits / self.temperature
    SFT
    19,126 questions, 2 epochs
    RL (CISPO)
    9,992 questions × 8 tries, stopped at 402/624
    Temperature
    1 number, fitted on dev

    A decoder LLM, unchanged. On its own it can only write. Outlined chips are the structural markers. Optional reasoning (dashed) goes between <think> tags, then the question is repeated before <decide>. The entire decision head. It compares one vector with each option's vector, and that's it. The 9B base stays frozen; only the small LoRA adapters and the head are trained. Bar length shows how far each stage ran: SFT to the end, RL stopped at 64% of its schedule. With reasoning on, the answer still comes from the head, but the request is back to many passes: 3–10 s on an A100 in our runs.

    02 / 06

    Step 1: mark the structure

    Every request is wrapped in markers: <state>, <q>, <opt>…</opt> and a final <decide>. They reuse rare tokens Qwen already has. PostHog found plain words like "State:" worked worse. Why special tokens (side quest)

    Documented · Jeeves README4
  3. Building Jeeves

    Qwen3.5-9B · 9 billion weightsfrozen
    Structural markers<state> <q> <opt> </opt> <decide>
    Pointer head2 small matrices
    LoRA adaptersrank 16, on every layer
    TrainingSFT → RL → temperature
    Reasoningoptional, before deciding
    <state>Subject: Checkout broken …<q>team?<opt>billing</opt><opt>technical</opt>…<think>…</think><q> … <decide>
    # model/head.py, Jeeves (complete)
    class PointerHead(nn.Module):
        def __init__(self, d_embed, d_latent=256):
            self.q = nn.Linear(d_embed, d_latent)   # reads <decide>
            self.k = nn.Linear(d_embed, d_latent)   # reads each </opt>
            self.scale = d_latent ** -0.5
            self.temperature = 1.0               # fitted after training
    
        def forward(self, questions, decide):
            options = self.k(questions)
            query = self.q(decide)
            logits = (options @ query) * self.scale   # one score per option
            return logits / self.temperature
    SFT
    19,126 questions, 2 epochs
    RL (CISPO)
    9,992 questions × 8 tries, stopped at 402/624
    Temperature
    1 number, fitted on dev

    A decoder LLM, unchanged. On its own it can only write. Outlined chips are the structural markers. Optional reasoning (dashed) goes between <think> tags, then the question is repeated before <decide>. The entire decision head. It compares one vector with each option's vector, and that's it. The 9B base stays frozen; only the small LoRA adapters and the head are trained. Bar length shows how far each stage ran: SFT to the end, RL stopped at 64% of its schedule. With reasoning on, the answer still comes from the head, but the request is back to many passes: 3–10 s on an A100 in our runs.

    03 / 06

    Step 2: bolt on a pointer head

    A tiny add-on, two small matrices, compares the model's vector at <decide> with the vector at each option's </opt>. A closer match gives a higher score. This is the whole head, from the Jeeves source. Pointer head vs classifier (side quest)

  4. Building Jeeves

    Qwen3.5-9B · 9 billion weightsfrozen
    Structural markers<state> <q> <opt> </opt> <decide>
    Pointer head2 small matrices
    LoRA adaptersrank 16, on every layer
    TrainingSFT → RL → temperature
    Reasoningoptional, before deciding
    <state>Subject: Checkout broken …<q>team?<opt>billing</opt><opt>technical</opt>…<think>…</think><q> … <decide>
    # model/head.py, Jeeves (complete)
    class PointerHead(nn.Module):
        def __init__(self, d_embed, d_latent=256):
            self.q = nn.Linear(d_embed, d_latent)   # reads <decide>
            self.k = nn.Linear(d_embed, d_latent)   # reads each </opt>
            self.scale = d_latent ** -0.5
            self.temperature = 1.0               # fitted after training
    
        def forward(self, questions, decide):
            options = self.k(questions)
            query = self.q(decide)
            logits = (options @ query) * self.scale   # one score per option
            return logits / self.temperature
    SFT
    19,126 questions, 2 epochs
    RL (CISPO)
    9,992 questions × 8 tries, stopped at 402/624
    Temperature
    1 number, fitted on dev

    A decoder LLM, unchanged. On its own it can only write. Outlined chips are the structural markers. Optional reasoning (dashed) goes between <think> tags, then the question is repeated before <decide>. The entire decision head. It compares one vector with each option's vector, and that's it. The 9B base stays frozen; only the small LoRA adapters and the head are trained. Bar length shows how far each stage ran: SFT to the end, RL stopped at 64% of its schedule. With reasoning on, the answer still comes from the head, but the request is back to many passes: 3–10 s on an A100 in our runs.

    04 / 06

    Step 3: adapt, don't retrain

    Retraining 9 billion weights is expensive. Instead, LoRA (side quest) freezes them and trains small add-on matrices beside each layer, so only a sliver of the model learns. Together trained its Tev1-4B this way for about $17.8,17

  5. Building Jeeves

    Qwen3.5-9B · 9 billion weightsfrozen
    Structural markers<state> <q> <opt> </opt> <decide>
    Pointer head2 small matrices
    LoRA adaptersrank 16, on every layer
    TrainingSFT → RL → temperature
    Reasoningoptional, before deciding
    <state>Subject: Checkout broken …<q>team?<opt>billing</opt><opt>technical</opt>…<think>…</think><q> … <decide>
    # model/head.py, Jeeves (complete)
    class PointerHead(nn.Module):
        def __init__(self, d_embed, d_latent=256):
            self.q = nn.Linear(d_embed, d_latent)   # reads <decide>
            self.k = nn.Linear(d_embed, d_latent)   # reads each </opt>
            self.scale = d_latent ** -0.5
            self.temperature = 1.0               # fitted after training
    
        def forward(self, questions, decide):
            options = self.k(questions)
            query = self.q(decide)
            logits = (options @ query) * self.scale   # one score per option
            return logits / self.temperature
    SFT
    19,126 questions, 2 epochs
    RL (CISPO)
    9,992 questions × 8 tries, stopped at 402/624
    Temperature
    1 number, fitted on dev

    A decoder LLM, unchanged. On its own it can only write. Outlined chips are the structural markers. Optional reasoning (dashed) goes between <think> tags, then the question is repeated before <decide>. The entire decision head. It compares one vector with each option's vector, and that's it. The 9B base stays frozen; only the small LoRA adapters and the head are trained. Bar length shows how far each stage ran: SFT to the end, RL stopped at 64% of its schedule. With reasoning on, the answer still comes from the head, but the request is back to many passes: 3–10 s on an A100 in our runs.

    05 / 06

    Step 4: teach it, then sharpen it

    First, examples with answers (19,126 questions). Then reinforcement learning (side quest): 8 attempts per question, rewarding good decisions. They stopped early, at step 402 of 624, because past that point the probabilities got overconfident. Last, one temperature fitted on held-out data.

  6. Building Jeeves

    Qwen3.5-9B · 9 billion weightsfrozen
    Structural markers<state> <q> <opt> </opt> <decide>
    Pointer head2 small matrices
    LoRA adaptersrank 16, on every layer
    TrainingSFT → RL → temperature
    Reasoningoptional, before deciding
    <state>Subject: Checkout broken …<q>team?<opt>billing</opt><opt>technical</opt>…<think>…</think><q> … <decide>
    # model/head.py, Jeeves (complete)
    class PointerHead(nn.Module):
        def __init__(self, d_embed, d_latent=256):
            self.q = nn.Linear(d_embed, d_latent)   # reads <decide>
            self.k = nn.Linear(d_embed, d_latent)   # reads each </opt>
            self.scale = d_latent ** -0.5
            self.temperature = 1.0               # fitted after training
    
        def forward(self, questions, decide):
            options = self.k(questions)
            query = self.q(decide)
            logits = (options @ query) * self.scale   # one score per option
            return logits / self.temperature
    SFT
    19,126 questions, 2 epochs
    RL (CISPO)
    9,992 questions × 8 tries, stopped at 402/624
    Temperature
    1 number, fitted on dev

    A decoder LLM, unchanged. On its own it can only write. Outlined chips are the structural markers. Optional reasoning (dashed) goes between <think> tags, then the question is repeated before <decide>. The entire decision head. It compares one vector with each option's vector, and that's it. The 9B base stays frozen; only the small LoRA adapters and the head are trained. Bar length shows how far each stage ran: SFT to the end, RL stopped at 64% of its schedule. With reasoning on, the answer still comes from the head, but the request is back to many passes: 3–10 s on an A100 in our runs.

    06 / 06

    Step 5 (optional): think, then decide

    Jeeves can write reasoning first, then re-read the question and decide with the pointer head. That brings back a decode phase, so latency jumps from about 0.3 s to 3 to 10 s. The independent board excludes anything over 1,000 ms, which is why reasoning decision models like Jeeves and GLiDE are not on it.2

Design 3 of 3

Any chat model, read at one token

Four of the top nine entries on the independent board publish no weights of their own. They are a prompt plus a readout on a stock open model. You can do the same through any API that returns log-probabilities.

  1. The forced-letter readout

    Shape illustrative Our run · Oct 5, 2026
    Ticket: Subject: Checkout broken … 502 at the payment step for the last hour …
    Which team should own this? Answer with one letter.
    A. billing   B. technical   C. sales   D. other
    max_tokens=1, temperature=0, logprobs=true, top_logprobs=20
    B 1.0e+0A 2.0e-4The 1.0e-4D 1.0e-4C 4.0e-5Technical 3.0e-5** 2.0e-5b 1.0e-5
    A · billing 0.00
    B · technical 1.00
    C · sales 0.00
    D · other 0.00

    An ordinary prompt. The readout is the only unusual part. Top alternatives at the answer position (shape illustrative; the real list is model-specific). Keep the four letters, drop the rest, renormalize. GPT-4.1-mini on the ticket, 2,747 ms for two questions in two calls. 1.00 on technical. Letter bias, missing logprobs in reasoning modes, one generation per question, and one output token billed each time. On the board: Decider chat (Gemma-4-31B, no training) 57.33; simple-jev (Qwen3.8-27B, no training) 55.74; the hosted leader 57.91.

    01 / 05

    Letter the options

    Render the question with lettered options and ask for one letter. The prompt is ordinary; the trick is in how you read the reply.

  2. The forced-letter readout

    Shape illustrative Our run · Oct 5, 2026
    Ticket: Subject: Checkout broken … 502 at the payment step for the last hour …
    Which team should own this? Answer with one letter.
    A. billing   B. technical   C. sales   D. other
    max_tokens=1, temperature=0, logprobs=true, top_logprobs=20
    B 1.0e+0A 2.0e-4The 1.0e-4D 1.0e-4C 4.0e-5Technical 3.0e-5** 2.0e-5b 1.0e-5
    A · billing 0.00
    B · technical 1.00
    C · sales 0.00
    D · other 0.00

    An ordinary prompt. The readout is the only unusual part. Top alternatives at the answer position (shape illustrative; the real list is model-specific). Keep the four letters, drop the rest, renormalize. GPT-4.1-mini on the ticket, 2,747 ms for two questions in two calls. 1.00 on technical. Letter bias, missing logprobs in reasoning modes, one generation per question, and one output token billed each time. On the board: Decider chat (Gemma-4-31B, no training) 57.33; simple-jev (Qwen3.8-27B, no training) 55.74; the hosted leader 57.91.

    02 / 05

    Read the distribution, not the text

    At the answer position the model has a score for every token in its vocabulary. Ask the API for logprobs (side quest) and keep only the letters A to D. Renormalize them and you have a probability per option, from one decode step.11

  3. The forced-letter readout

    Shape illustrative Our run · Oct 5, 2026
    Ticket: Subject: Checkout broken … 502 at the payment step for the last hour …
    Which team should own this? Answer with one letter.
    A. billing   B. technical   C. sales   D. other
    max_tokens=1, temperature=0, logprobs=true, top_logprobs=20
    B 1.0e+0A 2.0e-4The 1.0e-4D 1.0e-4C 4.0e-5Technical 3.0e-5** 2.0e-5b 1.0e-5
    A · billing 0.00
    B · technical 1.00
    C · sales 0.00
    D · other 0.00

    An ordinary prompt. The readout is the only unusual part. Top alternatives at the answer position (shape illustrative; the real list is model-specific). Keep the four letters, drop the rest, renormalize. GPT-4.1-mini on the ticket, 2,747 ms for two questions in two calls. 1.00 on technical. Letter bias, missing logprobs in reasoning modes, one generation per question, and one output token billed each time. On the board: Decider chat (Gemma-4-31B, no training) 57.33; simple-jev (Qwen3.8-27B, no training) 55.74; the hosted leader 57.91.

    03 / 05

    What it looks like for real

    GPT-4.1-mini on the ticket, read this way: 1.00 on "technical". Right answer, with a confidence that leaves nothing to sort on. Across our tests its probabilities were badly overconfident (calibration error 0.12 to 0.40), which is the usual result of chat post-training.

    Our run · Oct 5, 2026
  4. The forced-letter readout

    Shape illustrative Our run · Oct 5, 2026
    Ticket: Subject: Checkout broken … 502 at the payment step for the last hour …
    Which team should own this? Answer with one letter.
    A. billing   B. technical   C. sales   D. other
    max_tokens=1, temperature=0, logprobs=true, top_logprobs=20
    B 1.0e+0A 2.0e-4The 1.0e-4D 1.0e-4C 4.0e-5Technical 3.0e-5** 2.0e-5b 1.0e-5
    A · billing 0.00
    B · technical 1.00
    C · sales 0.00
    D · other 0.00

    An ordinary prompt. The readout is the only unusual part. Top alternatives at the answer position (shape illustrative; the real list is model-specific). Keep the four letters, drop the rest, renormalize. GPT-4.1-mini on the ticket, 2,747 ms for two questions in two calls. 1.00 on technical. Letter bias, missing logprobs in reasoning modes, one generation per question, and one output token billed each time. On the board: Decider chat (Gemma-4-31B, no training) 57.33; simple-jev (Qwen3.8-27B, no training) 55.74; the hosted leader 57.91.

    04 / 05

    The catches

    Models prefer some letters regardless of content, so shuffle options and average.12 Reasoning modes often don't return logprobs. Each question is a separate generation unless you batch cleverly. And it is still one decode step on a chat endpoint, so it costs an output token and a scheduling slot.

  5. The forced-letter readout

    Shape illustrative Our run · Oct 5, 2026
    Ticket: Subject: Checkout broken … 502 at the payment step for the last hour …
    Which team should own this? Answer with one letter.
    A. billing   B. technical   C. sales   D. other
    max_tokens=1, temperature=0, logprobs=true, top_logprobs=20
    B 1.0e+0A 2.0e-4The 1.0e-4D 1.0e-4C 4.0e-5Technical 3.0e-5** 2.0e-5b 1.0e-5
    A · billing 0.00
    B · technical 1.00
    C · sales 0.00
    D · other 0.00

    An ordinary prompt. The readout is the only unusual part. Top alternatives at the answer position (shape illustrative; the real list is model-specific). Keep the four letters, drop the rest, renormalize. GPT-4.1-mini on the ticket, 2,747 ms for two questions in two calls. 1.00 on technical. Letter bias, missing logprobs in reasoning modes, one generation per question, and one output token billed each time. On the board: Decider chat (Gemma-4-31B, no training) 57.33; simple-jev (Qwen3.8-27B, no training) 55.74; the hosted leader 57.91.

    05 / 05

    Why it matters if you run open models

    On the board, "Decider chat" on Gemma-4-31B scores 57.33 with no training, 0.6 points under the leader.2 The same base model is on most serverless providers today, so a near-leader decision model can be a prompt and a readout on an endpoint you may already use. A good decision model is as much a serving recipe as it is a set of weights.

Side quests · under the hood

Scroll sideways

Under the hood

Temperature scaling

billing0.79
technical0.17
sales0.04

Divide every score by one number, T, before the softmax. T above 1 spreads the probabilities out; below 1 sharpens them. The winner never changes. You fit T on held-out data so the confidence matches the real hit rate. Laya's model card reports its calibration error falling from 0.47 to 0.08 after a refit. Refit on your own traffic whenever the model, the wording or the inputs change.

Under the hood

Fine-tuning vs prompting

Prompting changes what you tell the model; its weights stay the same. Fine-tuning changes the weights using labeled examples, so the model itself learns your categories. It costs labels and a training run, and the result only knows that task. Our keyword fine-tune took about 1,300 labels and under seven minutes on a free GPU; about 400 labels were enough to match the hosted model on that one job.

Under the hood

LoRA

Instead of changing a big weight matrix, LoRA learns two thin matrices whose product is added to it. Jeeves uses rank 16: each adapter is 16 columns wide against thousands, so only a small fraction of the model is trained and the original stays intact. A one-epoch rank-16 LoRA on Qwen3.8-27B scored 54.67 on the board after 167 minutes on one H200.

Under the hood

Reinforcement learning, briefly

Supervised training shows the right answer. Reinforcement learning lets the model try (Jeeves: 8 attempts per question), scores the attempts, and pushes toward the better ones. For decision models the score can reward honest probabilities, not just right answers. It can also overshoot: Jeeves stopped early when its confidence started inflating. TypeSafe calls its version RLCD; nobody outside has reproduced it.

Under the hood

Why special tokens

The head needs exact, reliable places to read from: the end of each option, and the moment of decision. Rare tokens the model almost never saw make clean, unambiguous anchors. Plain words like "Option:" also appear in normal text, which muddies them. PostHog measured this and kept the rare tokens.

Under the hood

Pointer head vs classification head

A classic classifier has one fixed output per category, so adding a category means retraining. A pointer head scores whatever options appear in the request by comparing vectors, so the same model handles 4 options today and 7 tomorrow. Laya does the same with its [MASK] slots and one shared scorer. Clef uses a small joint head that scores all of a request's questions together.

Under the hood

Logprobs and letter bias

Many OpenAI-compatible servers (vLLM included) can return the log-probability of the sampled token and the top alternatives at each position. Force a one-letter answer and the letters' probabilities at that position form a real distribution over your options. Two catches: models prefer some letters regardless of content, so shuffle and average; and chat post-training tends to make the probabilities overconfident, so recalibrate on your labels.

Chapter 03 · Our tests

What we measured

Eight models, five jobs, one method, three weeks. Jobs: sorting search queries into a client's four buckets, labeling search intent, categorizing inbox email, flagging email that needs a reply, and sorting a client's inbound contact forms (1,290 real submissions: five models reach 0.80–0.84 on a seven-way sort with 90–99% of real leads caught, while a yes/no spam gate failed for all of them). Every model was scored the same way on sets it had never seen. The answer keys for everything except the keyword set were made by a frontier model working blind, not by people, so "correct" there means "agrees with the frontier model".

Hosted decision model (Jev)

The default for a new decision

Accuracy
About level with GPT-4.1-mini and Claude Haiku on every job
Calibration
Best on almost every job (error 0.04–0.09)
Handles alone
70–91% of items at 90% accuracy
Cost
About 2¢ per 1,000 decisions; 29¢ for everything we ever sent it

Open 27B (Clef, hosted on Workers AI)

The first open model that matched the leader on email

Email
0.870 vs Jev's 0.878 on "needs me", inside the interval; catches more real asks (recall 0.79 vs 0.68); calibration error 0.029, the best on email. Category within noise of Jev
Search intent
Ties its 9B sibling for the closest spreads of all eight (JS 0.053–0.055; Jev 0.102)
Keyword buckets
0.760, two points under Jev, within noise on 300 items
Speed and cost
0.6–2 s round trip hosted (median 641 ms); about 7¢ per 1,000 at $0.24 per million input. Locally: an 18 GB download and 2–6 s per item on a MacBook. Its 9B sibling Clef Flash is the laptop option: best intent spreads, cautious on email (recall 0.45)

General LLM with logprobs (GPT-4.1-mini)

Works, costs more, trusts itself too much

Accuracy
Level with Jev when the question is good
Calibration
Overconfident: error 0.12–0.40
Cost and speed
5–12 times Jev per decision; 0.6–1.8 s per item. Claude Haiku: 60–200 times, with a stated confidence that was better calibrated on email
Our tests · Sep 15 to Oct 9, 2026

Accuracy on the most-confident share

The chart that matters

  1. Accuracy on the most-confident share · "needs me", 246 emailsPlain wording vs precise wording · same 246 emails

    Our data · Sep 15 to Oct 9, 2026
    0.500.600.700.800.901.00 0%25%50%75%100% share of emails kept, most confident first always "no": 0.809 0.500.600.700.800.901.00 0%50%100% share of emails kept, most confident first always "no": 0.809
    Jev 0.878Clef 27B (hosted) 0.870Clef Flash (local) 0.846GPT-4.1-mini 0.829Claude Haiku 4.5 0.825Base Laya 0.756

    The first 5% is left out because it's too few emails to read. Answer key: a frontier model labeling blind, with a second pass on uncertain items. Figures after each name: accuracy on all 246.

    Jev 0.65 → 0.88
    Clef 27B (hosted) 0.85 → 0.87
    Clef Flash (local) 0.83 → 0.85
    GPT-4.1-mini 0.75 → 0.83
    Claude Haiku 4.5 0.72 → 0.83
    Base Laya 0.60 → 0.76

    Accuracy with the plain wording (left bar) and the precise wording (right bar) of the same question, per model.

    01 / 07

    Sort by confidence, keep the top

    Sort 246 fresh emails from most to least confident and track accuracy as you include more of them. A useful model stays high on the left. That left edge is the share of work you could hand to it.

  2. Accuracy on the most-confident share · "needs me", 246 emailsPlain wording vs precise wording · same 246 emails

    Our data · Sep 15 to Oct 9, 2026
    0.500.600.700.800.901.00 0%25%50%75%100% share of emails kept, most confident first always "no": 0.809 0.500.600.700.800.901.00 0%50%100% share of emails kept, most confident first always "no": 0.809
    Jev 0.878Clef 27B (hosted) 0.870Clef Flash (local) 0.846GPT-4.1-mini 0.829Claude Haiku 4.5 0.825Base Laya 0.756

    The first 5% is left out because it's too few emails to read. Answer key: a frontier model labeling blind, with a second pass on uncertain items. Figures after each name: accuracy on all 246.

    Jev 0.65 → 0.88
    Clef 27B (hosted) 0.85 → 0.87
    Clef Flash (local) 0.83 → 0.85
    GPT-4.1-mini 0.75 → 0.83
    Claude Haiku 4.5 0.72 → 0.83
    Base Laya 0.60 → 0.76

    Accuracy with the plain wording (left bar) and the precise wording (right bar) of the same question, per model.

    02 / 07

    The line to beat

    The dashed line is what always answering "no" scores: only 47 of 246 emails needed the owner, so a model has to beat 0.809 to be worth anything. Beat the base rate (side quest)

  3. Accuracy on the most-confident share · "needs me", 246 emailsPlain wording vs precise wording · same 246 emails

    Our data · Sep 15 to Oct 9, 2026
    0.500.600.700.800.901.00 0%25%50%75%100% share of emails kept, most confident first always "no": 0.809 0.500.600.700.800.901.00 0%50%100% share of emails kept, most confident first always "no": 0.809
    Jev 0.878Clef 27B (hosted) 0.870Clef Flash (local) 0.846GPT-4.1-mini 0.829Claude Haiku 4.5 0.825Base Laya 0.756

    The first 5% is left out because it's too few emails to read. Answer key: a frontier model labeling blind, with a second pass on uncertain items. Figures after each name: accuracy on all 246.

    Jev 0.65 → 0.88
    Clef 27B (hosted) 0.85 → 0.87
    Clef Flash (local) 0.83 → 0.85
    GPT-4.1-mini 0.75 → 0.83
    Claude Haiku 4.5 0.72 → 0.83
    Base Laya 0.60 → 0.76

    Accuracy with the plain wording (left bar) and the precise wording (right bar) of the same question, per model.

    03 / 07

    Jev and Clef 27B

    Jev and Clef 27B hold above 0.9 for about the most confident 90%.

  4. Accuracy on the most-confident share · "needs me", 246 emailsPlain wording vs precise wording · same 246 emails

    Our data · Sep 15 to Oct 9, 2026
    0.500.600.700.800.901.00 0%25%50%75%100% share of emails kept, most confident first always "no": 0.809 0.500.600.700.800.901.00 0%50%100% share of emails kept, most confident first always "no": 0.809
    Jev 0.878Clef 27B (hosted) 0.870Clef Flash (local) 0.846GPT-4.1-mini 0.829Claude Haiku 4.5 0.825Base Laya 0.756

    The first 5% is left out because it's too few emails to read. Answer key: a frontier model labeling blind, with a second pass on uncertain items. Figures after each name: accuracy on all 246.

    Jev 0.65 → 0.88
    Clef 27B (hosted) 0.85 → 0.87
    Clef Flash (local) 0.83 → 0.85
    GPT-4.1-mini 0.75 → 0.83
    Claude Haiku 4.5 0.72 → 0.83
    Base Laya 0.60 → 0.76

    Accuracy with the plain wording (left bar) and the precise wording (right bar) of the same question, per model.

    04 / 07

    The open 9B

    The open 9B is cautious and never clears the baseline's noise.

  5. Accuracy on the most-confident share · "needs me", 246 emailsPlain wording vs precise wording · same 246 emails

    Our data · Sep 15 to Oct 9, 2026
    0.500.600.700.800.901.00 0%25%50%75%100% share of emails kept, most confident first always "no": 0.809 0.500.600.700.800.901.00 0%50%100% share of emails kept, most confident first always "no": 0.809
    Jev 0.878Clef 27B (hosted) 0.870Clef Flash (local) 0.846GPT-4.1-mini 0.829Claude Haiku 4.5 0.825Base Laya 0.756

    The first 5% is left out because it's too few emails to read. Answer key: a frontier model labeling blind, with a second pass on uncertain items. Figures after each name: accuracy on all 246.

    Jev 0.65 → 0.88
    Clef 27B (hosted) 0.85 → 0.87
    Clef Flash (local) 0.83 → 0.85
    GPT-4.1-mini 0.75 → 0.83
    Claude Haiku 4.5 0.72 → 0.83
    Base Laya 0.60 → 0.76

    Accuracy with the plain wording (left bar) and the precise wording (right bar) of the same question, per model.

    05 / 07

    GPT-4.1-mini

    GPT-4.1-mini's curve is nearly flat because its confidence is nearly always 1.0: there is nothing to sort on.

  6. Accuracy on the most-confident share · "needs me", 246 emailsPlain wording vs precise wording · same 246 emails

    Our data · Sep 15 to Oct 9, 2026
    0.500.600.700.800.901.00 0%25%50%75%100% share of emails kept, most confident first always "no": 0.809 0.500.600.700.800.901.00 0%50%100% share of emails kept, most confident first always "no": 0.809
    Jev 0.878Clef 27B (hosted) 0.870Clef Flash (local) 0.846GPT-4.1-mini 0.829Claude Haiku 4.5 0.825Base Laya 0.756

    The first 5% is left out because it's too few emails to read. Answer key: a frontier model labeling blind, with a second pass on uncertain items. Figures after each name: accuracy on all 246.

    Jev 0.65 → 0.88
    Clef 27B (hosted) 0.85 → 0.87
    Clef Flash (local) 0.83 → 0.85
    GPT-4.1-mini 0.75 → 0.83
    Claude Haiku 4.5 0.72 → 0.83
    Base Laya 0.60 → 0.76

    Accuracy with the plain wording (left bar) and the precise wording (right bar) of the same question, per model.

    06 / 07

    Base Laya

    Base Laya hands almost everything onward.

  7. Accuracy on the most-confident share · "needs me", 246 emailsPlain wording vs precise wording · same 246 emails

    Our data · Sep 15 to Oct 9, 2026
    0.500.600.700.800.901.00 0%25%50%75%100% share of emails kept, most confident first always "no": 0.809 0.500.600.700.800.901.00 0%50%100% share of emails kept, most confident first always "no": 0.809
    Jev 0.878Clef 27B (hosted) 0.870Clef Flash (local) 0.846GPT-4.1-mini 0.829Claude Haiku 4.5 0.825Base Laya 0.756

    The first 5% is left out because it's too few emails to read. Answer key: a frontier model labeling blind, with a second pass on uncertain items. Figures after each name: accuracy on all 246.

    Jev 0.65 → 0.88
    Clef 27B (hosted) 0.85 → 0.87
    Clef Flash (local) 0.83 → 0.85
    GPT-4.1-mini 0.75 → 0.83
    Claude Haiku 4.5 0.72 → 0.83
    Base Laya 0.60 → 0.76

    Accuracy with the plain wording (left bar) and the precise wording (right bar) of the same question, per model.

    07 / 07

    Wording moved results more than model choice

    The chart uses the second wording of the "needs me" question. With the first, plainer wording, every model failed. Jev went from 0.650 to 0.878 on one rewrite (McNemar p ≈ 7×10⁻¹⁰). Treat question text like code.

Chapter 04 · Testing

How to test one of these properly

Accuracy alone doesn't tell you whether a model saves work. What matters is how much you can hand off at an error rate you can live with, what happens to the rest, and what each decision costs.

Try it: confidence routing

Pick a model and drag the threshold. Emails at or above it are handled automatically; the rest go to a person. Each dot is one of the 246 emails, most confident first.

At 0.90, Jev handles about nine in ten emails and gets them right about nine times in ten. Lower the bar and watch the wrong answers arrive. Switch to GPT-4.1-mini and notice that the threshold barely does anything.

Risk-coverage curves (side quest) ECE (side quest) Beat the base rate (side quest)

126handled automatically
0.98accuracy on those
120sent to a person
0.809always-"no" baseline
Handled, matches the keyHandled, doesn't matchSent to a person

Jev: 0.878 accuracy on all 246; 281 ms per email in our run; about $0.017 per 1,000.

The testing ladder

The steps a careful test goes through. We've done 1 through 6 on four tasks; the rules for steps 3 to 5 were written down before scoring.

Agreement between labelers (side quest) Data leakage (side quest)

  1. Write the decision downOne decision, its allowed answers, what each answer triggers, and who owns the definitions. Always include an "other" or "unclear" option.
  2. Build an answer key the model never seesA few hundred real items, labeled by people or by a frontier model working blind. Say which. Measure agreement between two labelers first; low agreement means the definitions need work, not the model.
  3. Split before you tuneSeparate tuning and test sets; keep related items together. Touch the test set once. Our "needs me" wordings were tuned on 182 older emails and scored on 246 fresh ones.
  4. Beat the trivial baselinesAlways-guess-the-common-answer, a few rules, and a cheap trained classifier if you already have labels. One published test found an embedding model plus logistic regression beating a zero-shot decision model by ten points on Banking77.
  5. Check confidence, not just accuracyDo the 80%-sure answers come out right about 80% of the time? Fit a cutoff on half the items and score it on the other half.
  6. Design the cascadeRules first, the cheap model next, a stronger model for what it escalates, a person last. Measure whether the second model's errors differ from the first's; if they share mistakes, escalation repairs nothing.
  7. Shadow modeRun it beside the current process without acting on it. Log the state, the question version, every probability and the model version. The log becomes your calibration data and your next training set.
  8. Roll out reversiblyStart with actions you can undo (tags, queue order, a confirmation prompt), one decision at a time, with a kill switch. Fail closed: if the decision service is down, escalate everything.

The options, side by side

Inference costs per 1,000 decisions of about 300 input tokens, from published list prices and our runs. Labels and someone's time to maintain the thing usually cost more.

OptionCost / 1kLatencyNeedsConfidenceData stays with you
Hosted decision model (Jev)~$0.013160–500 ms round tripAn API keyBest we measured; still verify on your dataNo (zero-retention on enterprise plans)
Open 27B decision model on your provider (AutoJev / pplx-decider, Rune, Decider)$0.012–0.045 at $0.04–0.15 / M input~100 ms on one server GPU (board median)A provider that serves it, or a 48–96 GB GPUBoard ECE 0.02–0.12 depending on the modelYes, on dedicated capacity
Clef / Clef Flash on Workers AI$0.07 (measured) / $0.027Clef 27B: 0.6–2 s round trip measured, median 641 ms. Vendor medians 209 / 39 ms on their GPUsA Cloudflare account with the Workers AI permissionMeasured: the 27B level with Jev on email and better calibrated there; Flash cautiousCloudflare says it doesn't store or train on requests
Small encoder you fine-tune (Laya)~$0 compute20–50 ms on a laptop~400+ labels, minutes of trainingAccurate on one narrow job; weak everywhere elseYes
LLM you already use, read with logprobs$0.05–0.250.6–1.8 s per questionA prompt and an API that returns logprobsOverconfident; shuffle letters and recalibrateDepends on the endpoint
LLM with JSON output, no logprobs$1–4 (Haiku)0.8–3.5 sA promptStated, not measuredNo

Sources: TypeSafe, Cloudflare Workers AI, Perplexity and OpenRouter pricing pages; OpenAI and Anthropic pricing; the Decision Index 0.2.1 board; our runs (Oct 2026).1,2,7

Side quests · testing

Scroll sideways

Testing

Risk-coverage

Coverage is the share of items you let the model handle. Risk is the error rate among those. Raising the threshold lowers both. The curve tells you, for example, "we can automate 90% at 10% error" or "50% at 3% error". Pick the point your process can live with, on tuning data, then confirm it once on test data.

Testing

ECE

Expected Calibration Error: group predictions by confidence, measure the gap between average confidence and actual accuracy in each group, and average the gaps weighted by group size. 0 is perfect. The independent board shows it but doesn't score it; the leader sits at 0.074, several open 27B entries at 0.01–0.02. A low ECE doesn't mean accurate: a model that is always 50% sure and right half the time scores 0.

Testing

Beat the base rate

If 81% of emails don't need you, always answering "no" scores 0.81. If 79% of an agent's tool calls are benign (as one team found on real traffic), always answering "allow" scores 0.79. A question whose accuracy loses to a constant is broken, however reasonable it reads. Report the base rate next to every accuracy.

Testing

Agreement between labelers

Have two people label the same 100 items without seeing each other's answers. Raw agreement is the share they match on. Cohen's kappa corrects for agreement by chance. If two people only agree 70% of the time, no model will reliably beat 70% against either of them. Fix the definitions first. Two frontier-model passes on our emails agreed 95% of the time, which says the key is consistent, not that it is right.

Testing

Data leakage

Leakage is when test items sneak into training, so the score looks better than reality. Every benchmark on the public board is public, which is why the maintainers count flagged items as wrong and why author-reported numbers routinely sit 20 to 40 points above board numbers. Keep your own test set frozen, hashed and private.

Chapter 05 · Where it slots in

A decision layer between information and an action

These models don't replace generation, retrieval or judgment. They sit at the points in a system where something has to be chosen: gate, route, rank, triage, verify. The model is the easy part. What makes it pay off is everything around it.

Before a tool call

Gate

"Could this command destroy data?" in 30–300 ms before an agent runs it. Jev and the open 9B both flagged our force-push; base Laya did not. Pause above a probability you set; log every call.

Before generation

Route

Pick the model tier, the reasoning effort, or the endpoint for a prompt. Every model in our run sent the one-line rewrite to "small". OpenRouter's Jev Router and Databricks' ai_decide do this in production.

After generation

Judge

Is this answer supported by the passage? On-policy? On-voice? A CMU study kept 99% of a frontier judge's accuracy at 57% of the cost by escalating only low-confidence verdicts.15

At intake

Triage

Tickets, forms, email, alerts: team, urgency, severity, needs-a-human. One request answers all of them. Jev decided 91% of our fresh emails alone at 0.90 accuracy.

In bulk

Label

Decisions over whole tables: MotherDuck's SQL function labeled 100K rows at 89% in 40 s for about 50 cents.16 This is a batch workload: throughput matters, latency doesn't.

Between steps

Verify

Extraction checks, citation checks, entity matches. Let a deterministic rule reject; let the probabilistic judge only lower confidence or request review, never overrule the rule.

Get your house in order

The things that separate a useful pilot from a demo. Tick what's true for a decision you're considering; this page remembers your ticks in this browser only.

How these go wrong

  1. Grading against the teacherAgreeing with the model that made the labels measures imitation, not truth. Score against a key that never fed training.
  2. Fuzzy questions"Is this urgent?" fails. "Does this ticket need a response within the hour?" works. Name the boundary cases in the option descriptions.
  3. Mistaking decisive for correctA typed model always returns a valid option. It can still be confidently wrong, especially on inputs unlike its training. "No hallucinations" means the shape is valid, nothing more.
  4. Answer shoppingRephrasing until the model is confident selects the luckiest wording, not the right answer. Average across phrasings instead, then refit the cutoff.
  5. Averages that hide the costly misses90% overall can still mean missing most of the rare, expensive cases. Weight errors by what they cost, and check each class.
  6. Copying thresholds between modelsA 0.9 from one model is not a 0.9 from another. Every vendor says so; our data agrees. Refit on your traffic when you swap.

Sources and method

Companion briefing, with the market, the Decision Index, our studies and what to do about it: Decision models.

Model internals come from the projects' own code and READMEs. Our numbers come from a test program (Sep 15 to Oct 9, 2026): five jobs, eight models, one scoring method, with the answer keys and their provenance stated on the companion field guide. The six worked examples on this page are invented situations run on Oct 5, 2026 through TypeSafe's hosted API, Clef Flash on Ollama 0.35.1 on a MacBook, base Laya on the same machine, and GPT-4.1-mini with logprobs. Clef 27B was added on Oct 9, 2026 through Cloudflare Workers AI, with a local re-run on the same MacBook for timing. Latencies are what we observed, not vendor figures, unless marked.

First published Oct 5, 2026; updated Oct 9, 2026. Evidence marks: filled for our own runs, half for a vendor or author figure, hollow for something read from a project's code or README, dashed for an illustration.

  1. 1 TypeSafe: introducing System One models and Jev · Sep 15, 2026
  2. 2 Decision Index (board 0.2.1) · generated Sep 28, 2026
  3. 3 Decision Index reproduction kit
  4. 4 PostHog/jeeves (README, model/head.py)
  5. 5 Laya model card
  6. 6 Laya rl_common.py
  7. 7 Cloudflare: Clef and Clef Flash · Oct 1, 2026
  8. 8 Together: train your own Jev for $17
  9. 9 TypeSafe: parallel questions cookbook
  10. 10 Parasail: prefill vs decode in LLM inference
  11. 11 OpenAI cookbook: using logprobs
  12. 12 LLMs are not robust multiple choice selectors (Zheng et al.) · 2023
  13. 13 On calibration of modern neural networks (Guo et al.) · 2017
  14. 14 Just ask for calibration (Tian et al.) · 2023
  15. 15 CMU judge-cascade study
  16. 16 MotherDuck: prompt_jev
  17. 17 LoRA (Hu et al.) · 2021
Side quest

Every side quest is also in the row at the end of its chapter.