Skip to content
Reference

Wire protocol

The newline-delimited JSON the engine and your bot exchange. The SDK speaks it for you.

You normally never touch this: the SDK’s runner speaks it for you. It is documented for the curious and for anyone testing with --subprocess.

A bot is a process. The engine writes newline-delimited JSON messages to your stdin; you write exactly one JSON line to stdout whenever you receive an act message, and nothing otherwise. Your print() output goes to stderr, which the SDK arranges automatically.

{"type": "hello", "player": 2, "num_players": 5, "num_hands": 100,
"stack": 200, "blinds": [1, 2],
"time_bank_ms": 30000, "increment_ms": 100}
{"type": "hand_start", "hand": 17, "seat": 2, "button": 0,
"stacks": [200, 200, 200, 200, 200], "hole": ["As", "Kd"],
"players": [0, 1, 2, 3, 4]}
{"type": "blinds", "sb_seat": 1, "bb_seat": 2, "sb": 1, "bb": 2}
{"type": "action", "hand": 17, "street": "preflop", "seat": 3,
"action": "raise", "amount": 6, "pot": 9}
{"type": "street", "hand": 17, "street": "flop",
"board": ["7h", "2d", "Qc"]}
{"type": "act", "hand": 17, "seat": 2, "street": "flop",
"board": ["7h", "2d", "Qc"], "hole": ["As", "Kd"],
"pot": 12, "to_call": 4, "min_raise_to": 8, "max_raise_to": 198,
"can_raise": true, "stacks": [194, 198, 196, 190, 200],
"street_bets": [0, 0, 0, 4, 0], "folded": [false, false, false, false, true],
"button": 0, "history": [["preflop", 3, "raise", 6]], "clock_ms": 29140,
"players": [0, 1, 2, 3, 4]}
{"type": "hand_end", "hand": 17, "board": ["7h", "2d", "Qc", "3s", "5s"],
"deltas": [12, -2, -4, -6, 0],
"revealed": {"0": ["As", "Kd"], "3": ["Qh", "Jh"]},
"pots": [{"amount": 24, "winners": [0]}]}
{"type": "match_end", "chips": [140, -80, -20, -40, 0],
"verdicts": ["OK", "OK", "OK", "OK", "OK"]}

Only ever in response to act, one line:

{"action": "fold"}
{"action": "check"}
{"action": "call"}
{"action": "raise", "amount": 14}
{"action": "allin"}

amount uses raise-to semantics: the total your bet for this street becomes, not the increment.

Seat indices are per hand. The button is always seat 0 and the bots move one seat every hand, so your seat changes from hand to hand; hand_start tells you where you are sitting.

Player ids are per game. Every bot at the table gets a player id from 0 to num_players - 1 that never changes during the game. hello tells you your own id as player, and every later message except match_end carries players, a list mapping seat to player id for the current hand. To find who made an action, look up players[seat]. match_end chips and verdicts are listed by player id. Card strings are rank then suit: 2 3 4 5 6 7 8 9 T J Q K A and s h d c.