BBC Micro AI Agent Experiment
Vacation side project: build an AI agent with one mission: write code for the BBC Micro - an 8-bit computer from 1981.
Now, the BBC Micro Bot community has spent years creating BBC BASIC one-liners that express amazing creativity in under 500 characters. We did not use any BBC Micro Bot programs in this experiment, nor attempt that level of finesse, however.
Instead, our agent gives the model some context about the machine, access to a BBC Micro emulator and VLM critic of the graphics output.
Click any image to open agent output in BBC BASIC editor:
Simon Willison has been asking LLMs to write an SVG of a pelican riding a bicycle since 2024. It seemed only fair to make the BBC Micro attempt it, in four colours, at 320x256. However, our harness gives the models the advantage of an emulator to run against and a critic marking each attempt.
#Agent architecture
The agent is a simple loop with feedback. We used OpenRouter to test the same harness across a fairly random selection open-weight and proprietary models: GPT‑5.6 Sol, Kimi K3, Gemini 3 Flash, DeepSeek V4 Flash, and Gemma 4 26B A4B. Plan the scene, write the program, observe what happened, fix it, repeat. Observing is two questions asked in order: did it run, and does it look right?
#1. Plan
The model calls plan and describes the scene in text - the shapes it intends, their colours, sizes and positions as well as outlining it in pseudocode.
#2. Write
Then the whole program, in one reply. Every attempt is a fresh few hundred characters of BASIC, written from scratch after reading the last critique. Two smaller tool calls are available here: lookup fetches a reference page (e.g. the PLOT map, VDU codes, size tricks), and count_chars gives the canonical length, counted after tokenising, where every BASIC keyword costs one character.
#3. Act - BBC Micro emulation
run_check sends the program to the beebjit emulator for 30 emulated seconds. It returns a screenshot if the program runs successfully, or else the model gets the BASIC error message and error line (e.g. "Division by zero at line 30"). A program that crashed goes straight back to be rewritten - it never reaches the critic, because there is nothing on the screen worth paying to look at.
#4. Observe
The Qwen3 VL VLM critic drives refinement of the image. On Kimi's first attempt of a pelican on a bicycle it said:
The bird lacks a pelican's characteristic throat pouch; the bicycle is
missing pedals, a chain, spokes, and handlebars; the bird's legs don't reach
the pedals.
**INTENT SCORE: 4/10**
pelican riding | ![]() attempt 1 | ![]() attempt 3 | ![]() attempt 5 | ![]() attempt 7 | ![]() final |
|---|
Thanks to this observation stage in our agentic loop, Kimi's program output image goes from a one-shot seagull to genuine pelican-ness in the subsequent iterations (above)
#5. Finish or loop again
If the critique warrants another go and turns remain, the agent loops back. When it calls submit - or runs out of turns - the session ends, but the model does not choose what ships: the harness keeps the highest-scoring attempt of the whole run.
#Future improvements
The driver behind this investigation was the economics of popping up a website that generated BBC Micro programs. Of course, OpenAI Codex or Claude Code with frontier models do a great job of this, it but feels like a sledgehammer to crack a nut:
| cat | bus | sunset | house | city | |
|---|---|---|---|---|---|
Claude Code | ![]() | ![]() | ![]() | ![]() | ![]() |
The questions for me was really how efficiently we can implement it. The lowest cost inference options being free-tier AI models on the cloud, or even better (from my perspective) smaller models on the edge that could run on the local machine, even in the web browser itself. The fact that Gemma4 26B A4B was quickly able to generate executable BBC BASIC programs with some passable images makes me think this is a worthwhile avenue to pursue.
#Where is the time going?
Of course there is plenty of headroom to optimize the agent itself:
If we look at the Kimi Pelican example, it took twelve model calls over 295 seconds: a long block of planning, a detour to look up the graphics ROM reference after seeing the first render, then nine write-run-look cycles. In the timeline, the emulator is the row of thin red slivers, drawn a little wider than life so they show up at all - 0.23 seconds a go, 0.7% of the session, roughly eighty times less than one model call.
- Stop when the score plateaus. The best models bank a good picture in four turns; the worst spend twelve and wobble. Showing the agent its own score history, and ending the run when it flattens, should buy the same quality at half the calls.
- Look more cheaply. The critic is 15% of wall clock and runs on every changed render. Scoring every second attempt, or using a small vision model for interim looks and a large one only to judge, is untested.
- Send fewer tokens. The drawing reference goes out with every call. Moving the rarely-used half behind
lookupwould cut input tokens meaningfully - at the risk that weak models never fetch it. - Write context per capability, not in general. The one experiment so far cut both ways: rewriting the dithering guidance as a copy-exact recipe left a strong model unchanged and made a weak one markedly worse, because it reached for the feature more and corrupted it more. Context that helps every tier is harder than it looks, and has to be measured per model.
- Change the examiner. Every score here comes from one critic, from the same family as the winner. Swapping critics would show how much of the ranking is the picture and how much is the marker.


































