Pokémon Agent

local models play FireRed and Emerald
Side project · 2026

Local models running on the desk play Pokémon FireRed and Emerald unassisted, one button press at a time. Nothing leaves the machine, so the only running cost is electricity.

Pokémon Agent screenshot
A live run · the frame, the button it chose, and why

It is easy to make a model look like it is playing a game: give it a "fight this battle" function, a "walk to the gym" function, and it will finish the game without ever making a decision. What is being tested then is the harness, not the model. So this one has a single rule, and everything else follows from it: the only thing the model is ever allowed to do is press one button. There is no macro for a battle turn, a menu, or a route. Every step across Kanto is a press it chose.

No single model does all of this. It is a multi-agent system, and each agent's job is to make the deciding model better informed, never to decide for it. A vision model turns the raw frame into a structured observation; a stronger text model turns that observation into one button; and a set of specialists supply what a screenshot cannot show, reading the console's own memory for route geometry, level caps derived from the game's trainer data, catch and party scoring, and whether a wild encounter is shiny. All of it arrives as advice the deciding model is free to ignore. An audit of where each press came from puts about 99% of them on that model; the remainder is bookkeeping the game itself leaves behind. Nothing in the path is specific to one cartridge, which is the point, the same loop drives FireRed and Emerald runs side by side.

How it works

Stack

Python · mGBA · Ollama, with qwen2.5vl:7b perceiving and qwen2.5:14b or qwen3.6:27b deciding. Every agent in the system runs on one machine on my own GPU: no API key, no cloud model, no per-token bill, and nothing hosted to visit. Three runs can play around the clock and the only thing they consume is electricity.

Next the rest of the Elite Four, and a window-grab host so the same loop can play games that have no emulator to read from.

Runs on my own machine · no public repo.

← all projects