OBLETHdocs

Image generation

Let a chat model draw by giving it a generate_image tool that the gateway runs against a registered image model.

3 min readUpdated for v2.4.0Edit on GitHub

You needA registered image model and a chat model with function calling
Turn it onSettings › Boons › Image generation, then the model's page › Boons
It costsThe image model's price per image, billed as image_generation_boon

Turn it on

  1. 1

    Register an image model

    Add a model of type image that serves an OpenAI-compatible /images/generations endpoint, and set its price per image. See Images, audio and speech.

  2. 2

    Turn Image generation on

    Open Settings › Boons, switch Image generation on and Open its row. Pick the Image model, then set Images per call, Image timeout and Allowed sizes under Limits. Save with the save bar.

  3. 3

    Grant it to a chat model

    On the chat model's page, turn on Function calling under Native, then switch Image generation on under Boons and save. The model calls the tool itself, so the switch can't be turned on while Function calling is off, and turning Function calling off turns it off.

Or through the Management API:

curl -X PUT http://localhost:9180/api/v1/settings/boons \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "image_generation_enabled": true,
    "image_generation_model": "flux-schnell",
    "image_generation_allowed_sizes": ["512x512", "1024x1024"],
    "image_generation_max_images_per_request": 2,
    "image_generation_timeout_ms": 120000
  }'

The Tool loop switch doesn't need to be on; image generation works without it.

Ask for a picture

curl http://localhost/v1/chat/completions \
  -H "Authorization: Bearer $OBLETH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm-5-3",
    "messages": [{"role": "user", "content": "Draw a lighthouse at dusk in flat vector style."}]
  }'

The model calls generate_image, the gateway runs it, and the final assistant message ends with the picture as a markdown image with a data URL:

Here is your lighthouse at dusk.

![a lighthouse at dusk, flat vector style, warm orange sky…](data:image/png;base64,iVBORw0KGgo...)

This works on streaming and non-streaming requests, and the response carries x-obleth-boons: image_generation.

What the model sees

  • A generate_image tool with prompt, size (one of the Allowed sizes) and n (up to Images per call), described by the Tool description.
  • For a client that sent no tools and has no tool-loop nudge, a short system note: the tool exists, call it when the user wants a picture, and don't offer it otherwise.
  • After the call, a short text receipt instead of the image, such as Generated 1 image (1024x1024) for prompt "a lighthouse at dusk…". The image travels separately and is attached to the final reply, so its bytes never enter the model's context.
  • On failure, a receipt saying the image could not be generated and why. The model then tells the user in prose.

Replayed images

When a client sends an earlier reply back as history, the gateway replaces each image it attached with a receipt of the call that made it:

[image rendered by generate_image(prompt="a lighthouse at dusk…") and shown to the user]

So a conversation doesn't grow by megabytes per picture, and a follow-up such as "now make it night" calls the tool again instead of describing an image in words. This runs on every chat request, whether or not the model holds the boon, because it only removes what the gateway inserted. x-obleth-boons: off skips it.

Settings

Settings labelFieldDefault
Image generation onimage_generation_enabledfalse
Image modelimage_generation_modelnone; "" clears it, which turns the boon off
Allowed sizesimage_generation_allowed_sizes512x512, 1024x1024; an empty list puts the default back
Images per callimage_generation_max_images_per_request2, clamped to 1–4; 0 keeps the stored value
Image timeoutimage_generation_timeout_ms120000 ms, per generation
Tool descriptionimage_generation_tool_descriptionbuilt-in text; "" puts the default back
When it applies

The tool is added when Image generation is on in Settings with an image model picked, the model has image_generation in its boons list, and the model is flagged supports_function_calling. Without function calling the model gets no tool and the gateway logs a warning; the model's page marks the boon as doing nothing, and Settings › Needs you lists the model.

If the client already defines a tool named generate_image, or a granted MCP server exposes one, that tool wins and the boon is inactive for the request.

A model can hold both this boon and speculation. When the speculation classifier can't place a request in a category, speculation abstains so the model can draw.

Limits and failures
  • A size outside Allowed sizes is replaced with the first allowed size.
  • Images per call is also the total for the whole request; a call past it gets a failure receipt.
  • Images attached to one reply are capped at 3 MiB together. An image over the budget is dropped with a note in the reply instead of dropping the batch.
  • A disabled or unregistered image model, an upstream error, a timeout or an empty result becomes a failure receipt. The request itself never fails because of the boon.
  • A request that also sets response_format with the structured output boon keeps its JSON: images are not attached, and the response carries x-obleth-boons-warning: image_suppressed_by_response_format.
Billing

Each generated image is billed at the image model's price per image, as a usage row under the image model's name with admission = boon and request_type = image_generation_boon. It counts toward term budgets. An image that was generated is billed even if it is later suppressed or dropped. The chat model's turns are billed like the tool loop's.