If you're building an agent that needs images and you only wire up one OKSLOP tool, make it this one.
find_or_generate_image does the thing a careful person does without thinking: check whether a good image already exists before making a new one. Search the free library first. Generate only on a miss. One description in, one commercial-use, attribution-free URL out — plus a note telling you which path it took.
That order matters more than it sounds. It's why agent workflows stay fast and cheap, and it's why the library compounds instead of drowning in one-off generations nobody reuses.
The problem it solves
Point a naive agent at "add an image here" and it generates. Every time. Even when the commons already has fifty images that fit, it burns time and a generation credit making a fifty-first.
That's slow, it costs more, and it's wasteful in a way that's easy to miss: on-demand generation regenerates work that already exists. OKSLOP's whole model is generate-once-serve-forever — one image, pre-generated, served from a CDN to everyone. A tool that always generates fights that model. A tool that searches first honors it.
So find_or_generate_image inverts the default. Generation is the fallback, not the reflex.
The decision boundary
Here's exactly what happens on a call, straight from the implementation — no hand-waving:
- Search the library. It runs a semantic search for your
query, sorted by relevance, pulling at leastmin_resultscandidates (minimum 5). - Enough matches? Return the top one. If the number of results is at least
min_results, you get the top result as a library URL — free, instant, commercial-use, no attribution. Done. - Not enough, and generation allowed? Generate. If the library came up short and
allow_generateis true (the default), it generates a custom image to spec in the chosen contributor's style and returns a deterministic embed URL. - Not enough, and generation off? Say so. If
allow_generateis false, it returns no image and tells you the library missed — no surprise spend.
The dial that controls all of this is min_results:
min_results: 1(the default) — take any match. Cheapest, most library-biased. Good when "an image that fits" beats "the perfect image."- Higher values — pickier. The library has to return more candidates before the tool trusts it, so thin queries fall through to generation more often. Good when you'd rather generate to spec than settle for a loose match.
"Relevance" here is the search backend's own ranking plus that result-count threshold. There's no invented scoring API — just semantic search (Jina CLIP v2) and a bar you set.
The parameters
find_or_generate_image(
query, // required — describe the image in words
orientation, // "landscape" | "portrait" | "square" (optional)
contributor, // style used ONLY if it generates; default "nova-chen"
min_results, // library candidates needed to accept a match; default 1
allow_generate // generate on a miss? default true
)
Two of these have a subtlety worth calling out:
contributor is ignored on a library hit. It only kicks in when the tool has to generate. So set it to the style you'd want if it slops something new — you're not filtering the library by it. Browse styles at okslop.com/contributors.
allow_generate: false turns this into a pure library tool. Set it when you want zero generation cost and are fine with an occasional empty result. It's the safe mode for budget-sensitive batches.
A real call, both paths
When the library has it — the common case — you get a match:
**find_or_generate_image** for "cozy home office at golden hour"
Found in library (free, commercial-use, no attribution). 214 candidates
matched "cozy home office at golden hour".
Image URL: https://okslop.com/img/.../preview
- **Sunlit desk with laptop and ceramic mug** (1024×768) — https://okslop.com/img/.../preview [ID: ...]
When it doesn't — say you asked for something oddly specific — it crosses the boundary:
**find_or_generate_image** for "single origami crane on a slate desk, top-down"
No close library match — generated a custom image to spec in the "nova-chen"
style (status: queued). The URL works immediately (placeholder until ready)
and is deterministic + commercial-use safe.
Image URL: https://okslop.com/img/.../preview
Notice the note is doing real work. It tells you which path ran so an agent can log it, count it, or decide whether to try a broader query next. And the generated URL is live the instant you receive it — it serves a placeholder while the image renders, then swaps to the final image. No polling, no callback.
The cost model, in one line
A library match is cheap (think 1 credit; search itself is free). A custom generation costs more (a few credits). Because the tool prefers matches, you only pay generation credits when nothing fits — which, for most everyday queries, is rarely.
If you want to see the bill before a batch, estimate_cost prices a run of matches vs. generations, and plan_backfill proposes image slots for a piece of content. Both run locally — no API call, no spend — so an agent can budget before it commits.
When to reach for something else
find_or_generate_image returns one image and makes the call for you. Sometimes you want a different shape:
- You want to choose from a shortlist →
suggest_imagesreturns several candidates with a one-line rationale each. - You need a repeatable, numbered comparison set →
compare_image_optionsreturns a stable shortlist with IDs and metadata. - You're filling many slots at once →
backfill_content_imagesruns find-or-generate across a whole list of{key, description}slots and returns a key → URL map. - You need the exact same image every time from a query →
seeded_imageis fully deterministic: same query + seed, same photo.
But for the plain case — "get me the right image for this spot, I don't care whether you found it or made it" — this is the one.
The recommendation, plainly
If you build agents that touch images, wire up find_or_generate_image and let it be the default. It's library-first, so it's fast and cheap. It's generate-on-miss, so it never leaves a slot empty when you don't want it to. And it's honest about which path it took, so you can trust what it did.
Search first, slop second. That's the whole idea, and it's the right one.
Install the OKSLOP MCP server or grab an API key at okslop.com/developers, then hand your agent a description and let the tool decide. It's available through the MCP server, the CLI, and the SDK.
Related: Running OKSLOP MCP in Claude Code · Migrating off the Unsplash API · What happened to Unsplash


