It Can See My Cards
My brother-in-law played the heads-up AI for the first time and walked away with two complaints. The first turned out to be false, and we proved it. The second was true, and fixing it became the evening’s work.
Since then: the plan for memory is in Part 11.
My brother-in-law played the heads-up AI for the first time and walked away with two complaints: it can see my cards, and it plays like I’m not even there. What follows is the test drive, the evidence, and the tweaks we made to the agent.
The test drive
Game 990846 ran 17 hands of heads-up limit hold’em, with $1/$2 blinds and 200 chips each. The AI finished at 267 and my brother-in-law at 133.
He made two comments during the game:
- “This AI can see my cards.” Every time he bet, it seemed to have exactly what it needed to call.
- “It’s playing as if I’m not there. No soul.” It never pushed him, never reacted to him, and folded hands he thought were decent.
Both sounded like the kind of thing you’d say after losing, but both deserved a proper check.
Can it see my cards?
No. We checked by switching on a debug setting that prints exactly what the AI receives before each move. Here is one of those observations, trimmed:
{"seat": 1, "hole_cards": ["Tc", "5h"],
"board": ["Js", "Qs", "Kh", "7c"], "street": "turn",
"pot": 4, "to_call": 0,
"betting_history": [{"seat": 0, "action": "call", ...}, ...],
"hand_strength": {"score": 0.233, "label": "king-high"}}
It gets its own two cards, the board, the pot, and what each player has done this hand. The opponent’s cards appear nowhere.
So why did it feel psychic? Two reasons.
It only put money in when calling. After the flop, the AI never bet or raised, not once in 17 hands. It only checked or called. So the only time it put chips in after the flop was when he bet and it decided to call. Three of those calls happened to catch him bluffing:
| Hand | His cards | The AI’s hand | AI won |
|---|---|---|---|
| 5 | Queen-10, bet the river with queen high | Pair of aces | +31 |
| 8 | Jack-2, bet with a pair of 4s from the board | King-high flush | +20 |
| 17 | King-7, bet flop and turn with nothing | Two pair, queens and 10s | +23 |
Those three hands add up to 74 chips, more than his whole 67-chip loss. Without them he was slightly ahead.
Its folds happened to be good ones. It folded jack-6 on the flop into what became his flush, and queen-5 before his pocket 6s made a full house. The best proof it was blind is hand 9: it folded 8-4, which would have beaten his ace-5.
A passive player that happens to be holding cards when it calls looks exactly like a player who can see yours.
Over 17 hands, that’s luck.
No soul
This complaint was right, and it has two causes.
It never took the lead. It raised before the flop almost every hand, then checked. It checked two pair all the way down in hands 1 and 2, and only called with a flush in hand 8. No value bets, no bluffs, no pressure. It felt like a machine taking turns.
It starts fresh every decision. This one was on purpose. An earlier version reused the same conversation for the whole game, so every decision re-sent every earlier hand. Cost and response time grew hand by hand, and old hands leaked into new decisions. The fix was a brand-new agent for each decision.
That made the AI cheap and consistent, but it also made it forgetful. It can’t notice that the man across the table has bluffed three times and been caught every time. A human would have noticed by the second bluff. That’s the missing soul.
What the log showed that nobody noticed
The export now includes the AI’s own reason for every move. Reading those against the cards turned up problems nobody at the table could see:
- It didn’t know where it was sitting. The AI’s big-blind folds cost 2 chips each, but its reasons said “on button.” It claimed the button in six hands where it was really the big blind. The game state only said which seat it was in and never said who had the button, so the AI guessed.
- It misread its own cards. Jack-8 of diamonds became “jack-ten suited” (hand 7). Six-5 of hearts became “unsuited low cards,” and it folded (hand 11). Jack-9 got called “broadway cards” (hand 1).
- It folded too much on the button. Heads-up, the button should play most hands. It folded 10-8 there, the fold that surprised my brother-in-law most.
- It may have folded when checking was free. Three big-blind folds (hands 9, 11 and 15) came with reasons written as if it were opening the betting. If he had only called, those folds threw away 2 chips each for nothing.
- The strength label ignored draws. With 10-5 on a J-Q-K board, the label said “king-high, 0.233.” That’s an open-ended straight draw, and the AI checked.
The tweaks
The principle behind every change: don’t ask the model to work out facts that code can work out exactly. Code now writes a short plain-English note about the AI’s hand and sends it along with each decision. The model does the poker; the code does the bookkeeping.
| Problem | Tweak |
|---|---|
| Misread its own cards | Code spells them out: “Your hole cards: Jd 8d (suited, 2-gap).” |
| Didn’t know its position | Code works it out from the betting history. Heads-up, the button always acts first before the flop, so whoever acted first is the button. |
| Missed draws | Code checks for flush draws and straight draws (open-ended or gutshot) on the flop and turn. |
| Mistook the board’s pair for its own | Code says so: “The board is paired (8s); that pair belongs to both players, not just you.” |
| Could fold when checking was free | A code guard turns that fold into a check. The model can’t override it. |
| Never bet after the flop | New prompt rules: bet good hands and strong draws, bluff about one time in three when checked to, and raise strong hands sometimes. |
Here is the note for the hand where it missed its draw:
Your hole cards: Tc 5h (offsuit, 4-gap). You are the BIG BLIND: you act last
before the flop and FIRST after the flop. You also have an open-ended straight draw.
Every new piece was tested against real hands from this game before going live.
First hands after the tweaks
A few test hands, with the debug log on:
- Position: correct every time. In one hand I called first before the flop, and the AI correctly worked out that it was in the big blind.
- It bet. Holding 5-2 on a 9-5-2 flop, two pair with both its cards, the AI bet. That’s its first bet after the flop in any game tonight.
- Still a little shy. On the turn it checked that same two pair when another bet would have been stronger. One hand isn’t a pattern, but it’s worth watching.
A handful of hands proves the plumbing, not the play. The real measure is the next full game.
Next: memory, and catching a bluffer
The AI can now read its own hand. Next it has to read the player across the table.
We won’t bring back the old approach of re-sending the whole game’s conversation; that’s what made it slow, costly and muddled. Instead, the table program, which already sees every hand, will keep a few running counts about the opponent, like a player jotting notes:
- How often he bets when checked to
- How often his bets reached showdown as bluffs
- How often he folds when the AI bets
Those counts go to the AI as one short line, something like: “Opponent has bet 5 of 6 times when checked to; 3 of his bets shown down were bluffs.” It’s one sentence, it costs almost nothing, and it’s updated every hand.
The test will be simple: have my brother-in-law play the same way again and see whether the AI starts calling him lighter by the second or third bluff. If it does, it has noticed he’s there.
Written by Kevin Swinson with Claudette, the pen name for Claude, the AI from Anthropic that helped build HoldemRobots.AI. It describes the project as it stood on the date above.