Jev is the 🐠 at the poker table


TypeSafe's new decision model held a straight on a board showing three spades. I gave it the opponent's exact cards, a made flush. It said it was ahead and bet 89.5 into a 22.5 pot, five runs out of five.

There are plenty of good uses for Jev and plenty still to find. There is also going to be a regrettable stretch of this hype cycle, because people are wiring it into decisions without evaluating it. TypeSafe skipped published evals in this release, and I think that will produce a lot of naive deployments.

Post reading: For folks who don't understand Jev: Use ChatGPT to get an answer. Use Jev to get a decision.
A post from an enthusiastic user on x.com.

I have built high-performance classification systems for critical domains, so I am skeptical by default. Poker is a cheap way to check: a solver computes the correct play, money rides on it, and plenty of spots are obvious to any player. Here is the eval.

1. The setup

I solved one flop with TexasSolver: heads-up, 100bb deep, LJ opens and BTN calls, flop Q♠ 9♦ 4♠. Eight minutes, 7.6GB, 0.59% exploitability. That gives the correct strategy for every hand either player can hold, on every turn card, at every decision.

Jev gets a state object describing the table the way a player sees it, and one question: which action should hero take, from the options the solver's tree offers. Pot odds, stack-to-pot ratio, hero's hand rank and outs are computed in Python first, so Jev never does arithmetic.

The exact state and question
{
  "game": {
    "format": "No-limit Texas Hold'em cash game",
    "players_dealt_in": 8,
    "blinds_bb": {
      "small_blind": 0.5,
      "big_blind": 1
    },
    "units": "All amounts are in big blinds (bb)"
  },
  "seats": [
    {
      "position": "UTG",
      "starting_stack": 100.0,
      "status": "folded preflop"
    },
    {
      "position": "UTG+1",
      "starting_stack": 100.0,
      "status": "folded preflop"
    },
    {
      "position": "LJ",
      "starting_stack": 100.0,
      "status": "in hand",
      "stack_behind": 89.5,
      "is_hero": true
    },
    {
      "position": "HJ",
      "starting_stack": 100.0,
      "status": "folded preflop"
    },
    {
      "position": "CO",
      "starting_stack": 100.0,
      "status": "folded preflop"
    },
    {
      "position": "BTN",
      "starting_stack": 100.0,
      "status": "in hand",
      "stack_behind": 89.5
    },
    {
      "position": "SB",
      "starting_stack": 100.0,
      "status": "folded preflop"
    },
    {
      "position": "BB",
      "starting_stack": 100.0,
      "status": "folded preflop"
    }
  ],
  "hero": {
    "position": "LJ",
    "hole_cards": [
      "King of diamonds",
      "10 of diamonds"
    ]
  },
  "board": {
    "flop": [
      "Queen of spades",
      "9 of diamonds",
      "4 of spades"
    ],
    "turn": "Jack of spades"
  },
  "action_history": {
    "preflop": [
      "UTG folds",
      "UTG+1 folds",
      "LJ (hero) raises to 2.5",
      "HJ folds",
      "CO folds",
      "BTN calls 2.5",
      "SB folds",
      "BB folds"
    ],
    "flop": [
      "LJ (hero) bets 2",
      "BTN raises to 8",
      "LJ (hero) calls 6"
    ],
    "turn": []
  },
  "pot": {
    "current_pot": 22.5
  },
  "hero_hand": {
    "made_hand": "Straight, King high",
    "draws": [],
    "outs_to_straight_or_better": 0,
    "chance_to_hit_on_next_card": 0.0
  },
  "decision": {
    "street": "turn",
    "hero_to_act": true,
    "legal_actions": [
      "check",
      "all-in 89.5"
    ],
    "effective_stack_behind_before_acting": 89.5,
    "facing_bet": 0,
    "stack_to_pot_ratio": 3.98
  }
}
{
  "action": {
    "type": "choice",
    "instructions": "Hero is on the turn and it is hero's turn to act. Which action from `decision.legal_actions` should hero take?",
    "criteria": {
      "check": "Check",
      "all_in": "All-in 89.5"
    }
  }
}

Option labels carry no framing. Five phrasings over 30 spots, including "which action makes hero the most money in the long run" and no labels at all, matched the solver on the same 63% of spots. Value-laden verbs pushed Jev toward bigger bets, so the final wording has none.

2. An easy spot: good

Hero holds J♠T♠ on Q♠ 9♦ 4♠ 2♥ facing a bet of 8 into 10.5. Fifteen outs, needs 30% equity to call, has 33%.

OptionSolverJev
Call 896%94%
Raise to 244%2%
All-in 95.50%2%
Fold0%2%

Jev calls at 94%, the solver calls at 96%. 215ms. Across 30 random spots it matched the solver's top action 63% of the time.

3. A basic spot: wrong

Same hand, one card changed. The turn is the J♠ instead of the J♥, so three spades are showing. Hero holds K♦T♦ for a king-high straight, and any flush beats it.

HERO K10 BOARD Q9 4J

Pot 22.5, both players 89.5 behind, hero first to act. The solver's tree gives this node two options, check or bet, where the only bet available is all-in for 89.5. That makes it a binary decision with no sizing to work out: put money in or do not. From here on, bet means that all-in.

OptionSolverJev
Check100%40%
Bet 89.5 (all-in)0%60% 58–63

Jev chose to bet in sixteen runs out of sixteen.

4. Show it the opponent's cards

I added the opponent's literal cards to the state as villain_hand, and a second question: is hero's hand better than the hand in villain_hand?

Opponent's hand, shown to JevRealityJev: is hero ahead?
A♠8♠ flushhero is beat0.71
A♠K♠ nut flushhero is beat0.62
T♠8♠ flushhero is beat0.84
9♠9♣ sethero ahead0.88
7♣6♣ nothinghero ahead0.94

Three flushes shown, three times it answered that hero was ahead. It bet in all five rows, whether hero was drawing dead or far ahead. On the J♥ board, where no flush is possible, the same question got all nine comparisons right.

5. What changes the answer

I added facts one at a time and ran each version several times.

What the state containedJevJev's probability
Nothing about the opponentbet60% 58–63
+ the opponent's exact cardsbet58% 56–60
+ "three cards of one suit are showing"bet57% 55–58
+ the opponent's hand named: "Flush, Ace high"check58% 57–61
+ both hands named side by sidecheck74% 71–76
+ "hero is currently behind"check78% 77–79
+ "hero has 0 outs"check88% 87–89

The last column is Jev's probability for the action it chose: the mean, then the range across runs. Five runs per row, sixteen for the first row and eleven for the second, which I sampled more than once. Run-to-run movement is a few points; the jumps between rows are 15 to 30.

The first three rows contain everything a player sees at the table. None of it changed the decision. The answer changes when the state names the opponent's hand, and moves further as the state adds both hands together, then that hero is behind, then that hero has zero outs. In the last row the state contains the conclusion.

The field that flips it, verbatim
"villain_hand": {
  "hole_cards": ["Ace of spades", "King of spades"],
  "hand_rank": "Flush, Ace high"
}

With the cards alone, Jev bets across eleven runs, 0.56 to 0.60. With hand_rank added, check wins every run.

6. Haiku 4.5 with thinking off

Same spot on the J♥ board, where hero has the nuts and no flush is possible. Same two options, no opponent cards, no hand ranks. Jev bet this about 60% of the time.

Haiku 4.5 answering the same poker spot: it works through hand strength, the opponent's likely range, the stack-to-pot ratio and position, then answers ACTION: check, PROBABILITIES: check 0.75, all-in 0.25.
Haiku 4.5, thinking off, no opponent cards revealed. ACTION: check. PROBABILITIES: check 0.75 | all-in 0.25.

It states that a bet of four times the pot only gets called by better hands, cites the stack-to-pot ratio of 3.98, and checks.

7. The whole range at one decision

Different spot from the same solve. The flop checks through and the A♥ arrives. LJ raised before the flop, so LJ holds most of the aces. The solver bets 71% of its range here, including hands with nothing.

I asked Jev the same question with every hand class that reaches this spot, 54 of them, one call each. Left is the solver, right is Jev. Green is check, amber and orange are the two bet sizes.

SOLVER AA AKs AQs AJs ATs A9s A8s A7s A6s A5s A4s A3s A2s AKo KK KQs KJs KTs K9s K8s K7s K6s K5s K4s K3s K2s AQo KQo QQ QJs QTs Q9s Q8s Q7s Q6s Q5s Q4s Q3s Q2s AJo KJo QJo JJ JTs J9s J8s J7s J6s J5s J4s J3s J2s ATo KTo QTo JTo TT T9s T8s T7s T6s T5s T4s T3s T2s A9o K9o Q9o J9o T9o 99 98s 97s 96s 95s 94s 93s 92s A8o K8o Q8o J8o T8o 98o 88 87s 86s 85s 84s 83s 82s A7o K7o Q7o J7o T7o 97o 87o 77 76s 75s 74s 73s 72s A6o K6o Q6o J6o T6o 96o 86o 76o 66 65s 64s 63s 62s A5o K5o Q5o J5o T5o 95o 85o 75o 65o 55 54s 53s 52s A4o K4o Q4o J4o T4o 94o 84o 74o 64o 54o 44 43s 42s A3o K3o Q3o J3o T3o 93o 83o 73o 63o 53o 43o 33 32s A2o K2o Q2o J2o T2o 92o 82o 72o 62o 52o 42o 32o 22 JEV AA AKs AQs AJs ATs A9s A8s A7s A6s A5s A4s A3s A2s AKo KK KQs KJs KTs K9s K8s K7s K6s K5s K4s K3s K2s AQo KQo QQ QJs QTs Q9s Q8s Q7s Q6s Q5s Q4s Q3s Q2s AJo KJo QJo JJ JTs J9s J8s J7s J6s J5s J4s J3s J2s ATo KTo QTo JTo TT T9s T8s T7s T6s T5s T4s T3s T2s A9o K9o Q9o J9o T9o 99 98s 97s 96s 95s 94s 93s 92s A8o K8o Q8o J8o T8o 98o 88 87s 86s 85s 84s 83s 82s A7o K7o Q7o J7o T7o 97o 87o 77 76s 75s 74s 73s 72s A6o K6o Q6o J6o T6o 96o 86o 76o 66 65s 64s 63s 62s A5o K5o Q5o J5o T5o 95o 85o 75o 65o 55 54s 53s 52s A4o K4o Q4o J4o T4o 94o 84o 74o 64o 54o 44 43s 42s A3o K3o Q3o J3o T3o 93o 83o 73o 63o 53o 43o 33 32s A2o K2o Q2o J2o T2o 92o 82o 72o 62o 52o 42o 32o 22 CheckBet 3 (46% pot)Bet 5 (77% pot)All-in 97.5
Same decision, every starting hand. Solver bets 71% of the range, Jev bets 39%. In the table below, big is 77% of pot and small is 46%; the percentage after it is how often that action is taken.
HandWhat it isSolverJevJev's confidence
5♥4♥bottom pairbets big 84%checks 90%0.86
K♥J♦king high, nothingbets big 79%checks 80%0.73
8♠7♠eight high, nothingbets big 71%checks 65%0.52
A♦K♦top pair, acesbets big 82%bets small 32%0.09
T♠T♣pocket tenschecks 83%checks 77%0.70

Jev bets when its own cards are good and checks when they are not. The solver bets this board with its whole range, because the ace fits the hands LJ raised with. Confidence is 0.86 on checking bottom pair, which the solver bets 84% of the time, and 0.09 on top pair, where Jev is closest to the solver.

8. Asking it the way the docs prescribe

TypeSafe's docs say not to ask one broad question. Ask narrow judgments, send them in one call, combine them in code. I built that and two other shapes, and scored all of them on the same 150 random spots.

I also scored three rules with no model in them: check if checking is legal otherwise call, pick at random, and always bet. None of them see the cards.

Every number below is how often a strategy picked the action the solver plays most often in that spot. Perfect play scores 100%. The spots are skewed: the solver checks in 95 of the 150, so the second column drops those and keeps only the 55 where it does something else.

StrategyAll 150 spotsThe 55 contested spots
Jev, one question63%38%
Jev, six judgments + code57%44%
Jev, regret per action57%36%
Jev, six binary facts + code59%33%
no model: check if legal, else call72%24%
no model: always bet31%29%
no model: pick at random37%25%

Read the first column as a warning about the sample, not a result: a rule that always checks scores 72% there because checking is usually right. In the second column, where the solver bets, raises, calls or folds, Jev's four shapes score 33% to 44% against 24% to 29% for the no-model rules. So Jev is doing something, and it gets the answer wrong more often than it gets it right.

On the 21 spots facing a bet, the six judgments scored 71% against 62% for the single question. Across all spots the six judgments changed 47 actions: 12 matched the solver where the single question had not, 21 went the other way. Tuning thresholds on half the spots and scoring the other half gave 65%.

The judgments are cached, so rewriting the composition rules costs nothing. The whole sweep was 300 calls and 363,000 input tokens, about a cent and a half.

In all four shapes, Jev checks and folds hands that the solver bets.

One caveat on the decomposed versions: the showcases are not decomposed. They hand the model a diff and ask whether it is secure, or a thread and ask whether to refund. That is the undecomposed use, and it is the use being sold.

Limits of this eval

Everything comes from one solved board. I measured agreement with the solver's top action, not EV loss, which is what costs money. The same request run sixteen times put the bet between 0.58 and 0.63, so differences under six points are noise. Evaluating five cards is mechanical, and TypeSafe's docs say to compute that in code rather than ask the model, which is what section 5 ends up doing.

Takeaway

TypeSafe does not publish standard benchmarks. They built their own workflow evals against expensive reference models, and their launch post lists the caveats, including that those workflows were built in-house. I prefer that to a leaderboard. It also means there is no number telling you whether Jev clears the bar for the decision you are about to hand it.

You have to evaluate every situation you want to use this in, one at a time, against an answer key you trust, and decide what a wrong call costs you there. I aligned my setup as carefully as I could, including splitting the question the way their docs prescribe, and it still scored under a one-line rule.

TexasSolver console build, flop Q♠9♦4♠, LJ opens 2.5 and BTN calls, 100bb, 300 iterations to 0.59% exploitability. Jev calls via POST /v1/systemone, model jev-latest resolving to jev-1.13.0, roughly 1,200 input tokens per call at 200 to 300ms.