Ethan Sheehan
All work — 2026

Pokémon TCG Agent

Kaggle Pokémon TCG AI Battle, summer 2026. The agent was three behaviour-cloned networks and a shallow search; the product was the measurement instrument that reversed six of our own decisions before they shipped.

RoleEnvironment and evidence, two-person team
Grouped bar chart of four reinforcement-learning arms: each temperature-1 sampled-policy gain of several percentage points stands beside an argmax gain of about zero, with the no-reward control lowest
Four RL arms, 140,000 games each. Sampled-policy gain against the served argmax gain.
Games per arm
140,000
Sampled gain
+7.48 pp
Argmax gain
+0.20 pp
01

Measure the policy you ship

Kaggle Pokémon TCG AI Battle, summer 2026, a two-person team. My half was environment and evidence: the SPRT gauntlet every candidate had to pass, the top-ladder episode miner and meta model behind the encoder, ladder forensics, the deck sweep, and compliance. The agent itself was three behaviour-cloned networks combined by mean-softmax, with a two-turn minimax allowed to override only on engine-proven lines. The agent is not the story. The instrument is: six times it reversed a decision we had already made, and each reversal came from a measurement we would not have taken without it. Zero crashes across all gates.

02

Six reversals

The first warning: a shared heuristic pilot ranked decks inverted against the real ladder, Spearman −0.43. Everything went through the gauntlet after that.

A deck change that screened as a clear gain died to its own control; the incumbent, re-measured, moved by about as much from sampling alone.

The search layer's +62 Elo was +13 Elo [0, +25] once re-gated with everything else held identical.

Ladder readings are not comparable across maturity. The plot below covers it.

Deck or agent? Scoring our own replays cell by cell capped the deck dimension at +16 Elo against the ~+180 we needed. The budget went to the pilot, not the list.

An ensemble is its members: the RL pool shared checkpoints with the evaluation board under different names, and one contaminated cell carried most of an apparent gain.

The RL that worked and was worth nothing. The objective optimises a distribution; the shipped agent plays its mode.

03

Sampled vs argmax

Policy gradient on the ensemble's final scoring layer, 140,000 games per arm. Each reward arm improved the temperature-1 sampled policy, the best by +7.48 percentage points at z = 13.43. The same weights played argmax, as we actually served them, gained +0.20. The gain was real, reproducible, and invisible to the agent we shipped. We had optimised the distribution the objective sees and deployed its mode. The fix was not more training; it was measuring the served policy before believing any of it.

04

Ladder bias

Every submission enters the ladder young, and young readings lie low. Across our own submissions the bias against the settled rating ran −142 at n = 5 and flattened to −8 by n = 50. One identical tarball shipped twice read 393 points apart at low n and converged to 0.0. That plot bought a standing rule: never compare two ladder readings taken at different n. It also retired a resubmission-lottery strategy that looked like free rating and was noise.

Line of rating bias against games observed, rising from minus 142 points at 5 games towards the settled rating by 50 games
Ladder bias against settled rating over our own submissions: −142 at n = 5, −8 at n = 50.
05

Compute

1.6 vCPU, 600 s per game, no GPU. A timeout or an illegal action is an instant loss, so the agent ran inside a never-crash shell with a time manager, and zero crashes across every reported gate was a requirement rather than a statistic. Three behaviour-cloned networks of about 500k parameters each, combined by mean-softmax, with a two-turn minimax that may only override the ensemble on engine-proven win or loss lines.