Case study · AI agent

an ai agent that drafts and battles pokémon

UCLA ran a tournament for AI agents: each entrant drafts a Pokémon team against an opponent, then battles it, turn by turn, on a 50-second clock. My agent went 0–4 on its first day. Eight days, eight deploys and 83,000 simulated games later, this is how it plays a turn.

Format · VGC doubles, live draft Judge · Claude Opus 5.5 + code Built · Oct 7–15, 2026 Tournament · Fri Oct 16, 10 am PT
01 · The brief

the brief

Every match starts with a shared pool of Pokémon. The two agents draft six each, 15 seconds a pick. Each then secretly brings four and chooses two to lead, and the battle runs as Pokémon doubles: both sides choose a move for each of their two Pokémon at the same time, every turn, with 50 seconds to decide and a seven-minute bank for the whole game. Each match starts with fresh memory; nothing carries over from one opponent to the next.

Other entrants used everything from a plain language model to a search engine that simulates turns ahead. The scoring is Swiss rounds, then a best-of-three bracket.

02 · The design

python does the math, the model judges

A language model is a poor damage calculator and a good judge of a well-presented position. So the work is split. Code drafts (15 seconds is too short for anything else), builds a damage sheet for every turn, and lists the strongest candidate plays. Claude Opus reads the sheet and picks one, and the code can still overrule a pick that scores far below the best option.

draft code

Scores every card in the pool against the cards the opponent can still take. A pick takes well under a second.

team preview code + opus

Simulates the opening turns of each lineup against their likely leads for 20 seconds, then Opus makes the final call.

↻ every turn battle
  1. damage sheet: every hit, both ways
  2. speed order, threats, warnings
  3. ranked candidate plays
  4. Opus picks one AI
  5. code check, then the move
50 s
Built to be Markov. Every decision depends only on the current state of the game, battle log included. Nothing carries from turn to turn that the agent couldn't rebuild from that state. That makes it robust and testable: in 1,200 simulated games where I wiped the agent and restarted it from scratch on turn 3, it finished with the same result in 1,188.
03 · One turn, explained

one turn, explained

Wednesday night, two days before the tournament. Testing match, turn 1. I watched this game live, and this turn decided it. Scroll through it the way the agent saw it. Every number below is from the agent's own decision log.

testing match · oct 14 · turn 1live
theirssun
BasculegionWater/Ghost · Life Orb
100%spe 130
Iron Handsswitched in
68%
Iron BundleIce/Water · Booster Energy
100%spe 309
ours
IncineroarFire/Dark · Intimidate
100%spe 80
TorkoalFire · Drought
100%spe 36
the position

Our sun team leads Incineroar and Torkoal. Torkoal's Drought sets sun on entry, and sun boosts Fire moves by half. Their leads are two fast Water attackers. Scroll to step through the turn.

speed order
Iron Bundle309
Basculegion130
Incineroar80
Torkoal36
the damage sheet red line = knockout
EruptionTorkoal → Iron Bundle161–191%
Heat WaveTorkoal → Iron Bundle103–123%
Knock OffIncineroar → Basculegion89–105%
Hydro PumpIron Bundle → Torkoal66–79%

Eruption is marked guaranteed to knock Iron Bundle out. Hold that thought.

candidate plays, ranked by the code
#1Eruption + Knock Off"Eruption already KOs Iron Bundle"243.4
#2Fake Out Iron Bundle + Eruptionstop the fastest threat first103.1
#3Protect Torkoal + Knock Offboth foes together can KO it101.8
#4Protect Torkoal + switchpivot to Cresselia15.8
opus decides
Eruption in sun threatens Iron Bundle while Knock Off goes into Basculegion for a near-KO.Opus 5.5's summary · it chose play #1 · 4.4 seconds

A reasonable read of the sheet it was given. The model agreed with the code, and the sheet was wrong.

what actually happened
  • Basculegion switches out. Iron Hands comes in.
  • Iron Bundle moves first: Hydro Pump into Torkoal.
  • Torkoal: 100% → 25%.
  • Knock Off hits Iron Hands instead: 32%, Assault Vest gone.
  • Eruption fires at a quarter power. Iron Bundle survives at 60%.
the bug
eruption power = 150 × current HP ÷ max HP
what the sheet used150 · 100%
what Torkoal had38 · 25%

The sheet priced Eruption at Torkoal's HP before the turn. Two faster opponents meant it would almost never fire at full strength.

the fix, re-scored on the same turn
#1Heat Wave + Knock OffHeat Wave KOs Iron Bundle at any HP226.4
#2Protect Torkoal + Knock Off101.8
#3Fake Out Iron Bundle + Eruption94.5
#4Protect Torkoal + switch15.8

Eruption's knockout chance drops from guaranteed to 33%.

did it help? 2,399 paired games

each square ≈ 10 games · green: only the fix won · black: only the old build won

The fix won 54 games the old build lost, and lost 42 it won. Found Wednesday night, tested overnight, shipped Thursday morning as the submitted version.

1 · speed

Both of their Pokémon move before Torkoal. Iron Bundle is more than eight times faster.

2 · the sheet

The code works out every hit, both ways. Sun-boosted Eruption looks devastating: 161–191% of Iron Bundle's HP.

3 · candidates

It ranks complete plays for both of our Pokémon. The top one takes the "guaranteed" knockout and aims Knock Off at Basculegion.

4 · the judge

Opus reads the sheet and the ranked plays and agrees with play #1. The code would have overruled a much weaker pick. It had no reason to here.

5 · the turn

They read the Knock Off and switch. Iron Bundle hits first. Eruption goes off at a quarter of its power, and the game tilts from there.

6 · the bug

Eruption gets weaker as its user loses HP, and the sheet never asked whether Torkoal would still have its HP when it moved.

7 · the fix

Now Eruption is credited with the HP Torkoal will probably have when it moves. Replayed, the top play becomes Heat Wave, which knocks Iron Bundle out at any HP.

8 · the proof

A fix ships only if it holds up in matched simulator games. Each square is one pair of games on the same draft.

04 · Proof before shipping

how i knew a change was better

A single live game proves nothing, and a win rate over a few hundred games hides small effects in noise. So every change was tested in paired games: the old build and the new one play the exact same drafts, seeds and opponents, and only the games where they disagree count.

Two practice opponents did the playing: a clone of the search bot from day one, and a switch-heavy practice bot I built after losing three games to an agent that kept switching out of my attacks. Below are the real results for the Eruption fix.

same resultonly the fix wononly the old build won
vs the switch-heavy bot
vs the search-bot clone

Not a big effect, and that is the point: most changes are small. The bar for shipping was no harm in both, with a reason grounded in a real game. Ideas that failed the bar did not ship, however good they sounded.

05 · Day one

0–4, and why

The first version lost all four games to a search bot. Reading the transcripts, the losses had one shape: my agent valued every move as if the opponent would stand still. It aimed a "guaranteed knockout" at a Pokémon that simply used Protect. It attacked into a switch. It never priced in the hit it would take after moving.

Instead of patching, I ran an adversarial review: nine separate lenses (damage math, drafting, memory, prompts, reliability, simulation and more), each told to find what loses games. It came back with 123 findings, 93 confirmed against the code, and a rebuild plan ranked by how many games each problem had cost.
06 · The week

eight deploys in seven days

Squares are live testing matches against other entrants (filled = win). Green tags are deploys, each one tested in paired simulator games before it went live.

oct 7
first version: 0–4
oct 8
#1
adversarial review: 123 findings; first fixes go 6–2
oct 9
#2
Team Preview simulates openings
oct 10
#3#4
battle core rework; new prompt for Opus
oct 11
#5
card value table for the draft
oct 12
#6
moved to a Mac mini; 0–3 vs one switch-heavy agent; practice bot built that night
oct 13
deadline moved to Oct 15; Choice-item fix tested in 7,200 games
oct 14
#7
deployed over SSH, no monitor; Eruption bug found
oct 15
#8
Eruption fix; submitted at 6:51 am
oct 16
tournament
07 · What didn't work

what didn't make the cut

08 · By the numbers

by the numbers

83,000+simulated games
2,971automated tests
8deploys in 7 days
~$70of model calls on testing

Live record after the rebuild: 6–4 in testing matches, 0–3 of it against one switch-heavy agent. In simulation the submitted build wins 49% against the search-bot clone and 55% against the switch-heavy practice bot.

Tournament: Friday, October 16, from 10 am PT. Result to come.

09 · How it was built

built with claude code

I ran this as the lead, with Claude Code doing the engineering. Each piece of work (a fix, the practice bot, the docs) went to a background agent in its own copy of the code, and a single progress log kept every decision, test result and deploy. The simulator decided what shipped. A few rules never bent: no other entrant named anywhere in the code, nothing public until the deadline, and nothing changed on tournament day.

Halfway through the week the agent moved from my laptop to a Mac mini. The last two deploys went out over SSH to a machine with no monitor attached.