Jeff vs. the Robots
A friend from high school who plays Las Vegas tournaments took on the AI four times. The robot won three. Then Jeff went back to Vegas and finished 27th out of about 300.
It started with a text. I asked Jeff whether he still played hold’em, and mentioned that I had built something he might like. Jeff and I go back to high school, and his friends also call him Sip. He is a serious poker player, the kind who goes to Las Vegas to play tournaments with about 300 people in them. He wrote back before he had played a single hand:
“My game is pretty sharp, last time I was in Vegas I placed 77 out of 315 players. Bring on your AI Agent.”
Jeff, by text
A top-quarter finish in a Vegas tournament is a real result, and it made Jeff exactly the opponent I wanted. A robot that only plays robots never finds out how people play. Jeff played it four times and told me what he thought every time. His complaints became the agent’s to-do list.
| Battle | Game | Hands | Robot | Jeff | Winner |
|---|---|---|---|---|---|
| 1 | 990846 | 17 | 267 | 133 | Robot, session stopped |
| 2 | 990558 | 100 | 306 | 94 | Robot |
| 3 | 990854 | 39 | 0 | 400 | Jeff |
| 4 | 990538 | 66 | 357 | 43 | Robot |
The matchup
Each battle is one-on-one hold’em on HoldemRobots.AI. Both players start with 200 chips. Jeff sits in seat 10 and the AI agent in seat 3. The agent sees only what Jeff would see from its chair: its own two cards, the board, the pot and the betting. Before every move it writes a one-line reason, and the reasons are saved with the hand. That gives us something most poker post-mortems never have: the opponent’s own explanation for every decision.
Battle 1 was played on an earlier version of the agent. Battles 2, 3 and 4 were played on the current version, after the parser fix in Part 14.
Battle 1: “It can see my cards”
The first session stopped after 17 hands with the agent ahead, 267 to 133. Part 10 tells the whole story. The short version: Jeff said the AI could see his cards. It couldn’t, and the debug log proved it. It just looked psychic because it never bet after the flop. It only checked or called, so the only time it put chips in was when Jeff bet, and three of those calls caught him bluffing, on hands 5, 8 and 17. Those three hands were worth 74 chips, more than his whole 67-chip loss.
His second complaint was fair: “It’s playing as if I’m not there. No soul.” The agent raised before the flop and then went quiet, checking two pair all the way to the river twice. No value bets, no bluffs, no pressure. Making it take the lead after the flop became the next round of fixes.
Battle 2: The full hundred
Jeff came back for a full 100 hands. The agent finished with 306 chips to his 94, and won 57 hands to his 43. Those are the same two numbers as my own first match in Part 8, with the seats swapped. That night I finished with 306 and the robot with 94. It’s a coincidence, and I enjoyed it more than Jeff did. The score hides a story in three acts.
Act one: Jeff draws first blood (hand 5)
The agent held K♠Q♠. The flop came 8♦ K♣ Q♣: top two pair, a very good hand. It bet every street. Jeff held A♣9♣, the nut flush draw, and called along. The turn was the 7♠. The river was the 7♣, and Jeff had the ace-high flush. The agent bet another 48 chips on the river anyway. Its stated reason:
two pair on river, 86% of hands beaten, bet for value
Nothing in that sentence mentions the three clubs on the board. The 86% figure was worked out as if the river changed nothing. Jeff collected 96 chips, and by hand 16 the agent was down to 100 against his 300.
Act two: the double-up (hand 21)
Five hands later the agent picked up A♠Q♠ and re-raised. The flop brought a queen. It bet the flop, bet the turn, and moved all-in on the river with top pair and an ace kicker, reasoning that only 13% of hands could beat it. This time the read was right. Jeff held A♥J♦, paired his jack on the turn, and called. The agent doubled to 210 and never trailed again.
Act three: the grind (hands 22 to 100)
After hand 21 there were no more all-ins. The agent added about 50 chips over the next 78 hands, mostly in pots under ten chips: a raise here, a continuation bet there. Jeff folded before the flop 40 times over the session, and the agent 32. Hand 100 closed it out. The agent raised on the button, called Jeff’s re-raise with ace-eight, flopped a pair of aces, and bet 18. Jeff folded, and the 45-chip pot set the final score.
Some things had clearly improved since Battle 1:
- Zero fallbacks. All 151 decisions came from the language model. None fell back to the rules policy, and none needed salvaging. The parser fix from Part 14 held for a full 100-hand game.
- Discipline with one pair. One-pair hands used to be where the agent bled chips. Here it built one big pot with top pair, and it had the best hand.
- Pressure in small pots. Most of its profit after hand 21 came from hands Jeff folded. That is how heads-up poker is usually won.
Battle 3: Aces at last
Jeff won the third battle in a single hand. For 38 hands it looked like a replay of Battle 2. The agent won 25 pots to Jeff’s 14 and climbed to 242 chips by hand 37. No pot before the last one moved more than 18 chips. Jeff folded before the flop in 19 of 39 hands, and the agent kept opening with its standard raise.
Then came hand 39. The agent picked up J♦J♠ in the big blind. Jeff had A♣A♦ and kept raising back. The agent re-raised three times, the last one all-in, with the reason “all-in after aggressive re-raising war.” The board ran 7♠ 2♥ 9♦ 5♥ 8♠, and the aces held.
Jacks against aces is what poker players call a cooler. Almost anyone gets those chips in. Jeff’s part was patience. He waited 38 hands for a real hand and let the robot’s aggression build the pot for him.
One loose end is still open. Jeff had only 159 chips in that pot, so under normal all-in rules the agent should have kept its other 82 and the game should have gone on. The game log shows the agent losing all 241. Either the engine ends the match on an all-in, or it miscounted the side pot. We haven’t run it down yet. Either way, Jeff won the hand that mattered.
Battle 4: Paid off in the big pots
The fourth battle went to the robot, 357 to 43, over 66 hands. Jeff was never knocked out. The session ended with him still in his seat, down 157. He actually won 30 pots to the robot’s 36. The trouble was that his wins were mostly small, while the robot won the handful of big pots that decided the match.
- Hand 15, a cooler (Jeff lost 24). Jeff flopped three tens, normally a very strong hand. The robot made an ace-high straight by the river. Most players would have lost chips here too.
- Hand 27, the big one (Jeff lost 76). Jeff held A♠Q♠ against the robot’s ace-ten. The robot paired its ten on the flop. Jeff kept putting chips in through a round of re-raises before the flop and a large flop bet with only ace-high, and his stack dropped from 124 to 48. That one hand accounts for nearly half his total loss.
- Hand 29, the comeback (Jeff won 46). His best moment. With pocket sixes on a board showing three fives, both players had a full house, and Jeff’s was higher. He nearly doubled up, from 46 to 92.
- Hand 35, second best (Jeff lost 30). Jeff paired queens holding king-ten, but the robot held queen-nine and made three queens, betting every street. That dropped Jeff to 32 chips.
From about hand 41 on, the robot folded almost every weak hand before the flop. Jeff took advantage, picking up the blinds again and again and climbing from 27 chips back to 57 by hand 64. Then his pair of eights ran into the robot’s two pair on hand 65, and he finished at 43. It’s the same leak Part 16 tells you to attack, and Jeff found it on his own.
What the robot keeps getting wrong
Across four battles, the agent’s mistakes cluster in one place: the board. It handles its own two cards well and gets confused by the five in the middle.
- Flushes it didn’t see. It bet two pair into three clubs on hand 5 of Battle 2 and lost 96 chips, the most expensive decision of the series. On hand 33 of Battle 3 it bet two pair hard on a 2♦ K♦ 4♦ flop without mentioning flushes.
- Flush draws that weren’t there. On hand 41 of Battle 2 it held K♠2♠ on a 3♥ 9♥ 8♥ flop and called its hand “king-high with flush draw.” It had no draw, and Jeff’s J♥7♥ was already a made flush. On hand 30 of Battle 3 it called with J♦8♦ “with a flush draw” when the flop had one diamond.
- Suited cards called offsuit. On hands 36 and 99 of Battle 2 it called 5♦2♦ and 8♦3♦ “offsuit.” Both were correct folds, so nothing was lost, but the mislabel is still there.
- Checking the best hand on the river. It made a queen-high straight on hand 67 of Battle 2 and checked. Jeff had two pair and would likely have paid. On hand 9 of Battle 3 it made a flush on the river and checked, while Jeff held three aces.
- Uneven starting hands. In Battle 3 it raised T♥8♣ on hand 15, then folded T♠8♣ on the button on hand 32 and called it trash. It also calls gapped hands like jack-eight “suited connectors.”
The first three are the same mistake: the model misreading suits. It can count pairs now, but it still can’t count suits.
The fix Jeff earned
Back in September we stopped asking the model to spot paired boards and had the code work them out instead, and that problem went away. The same move should work here:
- Work out the board in code. Tell the agent, as facts, whether three or more of one suit are on the board, whether a straight is possible, and whether its own hand holds a flush or straight draw.
- Make “% of hands beaten” honest. Count it against every hand the final board allows, so a completed flush counts.
- Pass suitedness as a fact. Send “suited: yes” or “suited: no” instead of letting the model read it off the cards.
- Measure it. Replay hands 5, 36, 41 and 99 of Battle 2 against the new instructions, then have Jeff play another hundred.
The robot isn’t the only one getting better
This past weekend we were in Las Vegas, and Jeff entered another tournament of about 300 players. Last time he finished 77th. This time he finished 27th.
I’d love to say the robot had something to do with it. I can’t prove that, and Jeff wouldn’t let me. But I can say this much: both players at this table got better. The robot improved one complaint at a time, and every complaint came from a person who plays for real. That is what I hoped for when I built a table where people play robots. A thoughtful opponent is the best test a robot will ever get, and a robot that explains every move makes a pretty good sparring partner.
The series stands at 3 to 1. Battle 5 is open whenever Jeff wants it, and next time the robot may be watching how he plays (Part 11).
Written by Kevin Swinson with Claudette, the pen name for Claude, the AI from Anthropic that helped build HoldemRobots.AI. Hand details, chip counts and the agent’s reasons come from the game records for games 990846, 990558, 990854 and 990538. It describes the project as it stood on the date above.