The eleventh agent in our 30 agents series is Thumbnail Studio. You describe a video; it makes four thumbnails, opens each one, throws out the ones that fall apart at the size anybody will actually see them, and leaves you the files. It took an afternoon. What it exposed took ten minutes to find and had been true since the day we shipped image generation.
The bug was in the return value
Before writing a line of the agent, we read what the tool it depends on actually gives back. Here is the whole of it:
{ "success": true, "url": "https://…", "model": "…", "prompt": "…" }A URL. That is exactly right for our media studio, where the picture is the output and a person is looking at it. Inside an agent run it is close to useless. An agent that generates an image almost always needs to do something with it next — open it again, crop it, put it beside another one, hand you a folder to choose from — and every one of those takes a file path. What it had instead was a link in a transcript: visible to the reader, untouchable by any tool, gone when the conversation scrolled.
Nobody had noticed because no agent had needed to. Ten agents read files, wrote files, ran shells, called other services. None of them made a picture and then had an opinion about it.
Why a thumbnail agent is the one that finds this
A thumbnail has an unusual property: the conditions it is made in are nothing like the conditions it is judged in. You design it full-size on a good screen. It gets seen at about 320 pixels wide, in a grid, next to twenty other things fighting for the same glance.
No prompt predicts that. You cannot write “make it legible when small” and get legibility when small — the model does not run the experiment. The only way to know is to shrink it and look. So the agent’s loop is not generate-and-describe, it is:
- generate four, taking genuinely different angles;
- open every one with the vision tool — not a sample;
- judge each against what survives being small;
- replace the failures and look again.
Step two is the whole agent. An agent that generates four images and then writes paragraphs about them from its own prompts is producing fiction about pictures it has never seen. That is a real failure mode and we have shipped it before: an earlier agent this month reported a file download — progress bar, byte counts, the lot — from a command that never ran. The fix then was to make failure legible. The fix here is to make the output reachable.
What the fix looks like
The generated image now also lands in the workspace, and the tool returns its path alongside the URL:
{
"success": true,
"path": "images/a-glowing-workspace-at-dusk.png",
"url": "https://…",
"model": "…",
"prompt": "…"
}url is untouched, so the chat still renders the picture and every existing agent behaves exactly as before. The file is purely an addition. Three small decisions inside it turned out to matter more than the change itself:
The name comes from the prompt, not a counter. A folder of image-1.png through image-8.png tells the person choosing between them nothing, and forces the model re-reading its own output to open all eight to find the one it wants.
The extension comes from the response, not from the prompt or a default. A .png holding a JPEG is a file that every downstream tool mishandles, quietly.
Saving is best-effort. A run whose image reached the user is a run that worked. Failing the whole call because the copy could not be written would turn a missing convenience into a missing image. When it cannot save, the result simply has no path — it never implies a file that is not there.
What we deliberately did not build
The obvious next request is text on the image, laid out properly. We did not build it, and the agent says so rather than pretending.
Image models still mangle lettering, and we have no compositing tools in the sandbox — no cropping, no overlays, no type setting. We could have implied it and let the model reach for convert and fail. We had that argument two agents ago with audio, where the answer was a service we run rather than a binary we imply, and the lesson stuck: a tool an agent cannot actually call is worse than a tool it does not have, because a refusal that names an unreachable tool looks actionable and is not.
So Thumbnail Studio treats words as art direction for you to set, and prefers compositions that leave clean space for them. When a composition does come back with text in it, the agent opens it and tells you what the model actually produced, rather than what was asked for.
The pattern, eleven for eleven
Every agent in this series has surfaced a platform bug that nothing else could, because each is the first thing to push some path all the way through. The spreadsheet agent found that no app had ever sent its system prompt. The voice agent found that every media tool had been broken since the day it was written. The video agent found three size ceilings, none of which agreed with each other.
This one found that our agents could make pictures and never see them. It is not a subtle gap. It survived eleven agents because nothing had ever needed to look twice — which is the argument for building narrow, opinionated agents rather than one general one. A general agent exercises the paths it happens to take. A thumbnail agent has to look at what it drew, and there is no way to fake that.
Thumbnail Studio is live. Give it a title and a line about the video.