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
image model and a chat model with function callingimage_generation_boonTurn it on
- 1
Register an image model
Add a model of type
imagethat serves an OpenAI-compatible/images/generationsendpoint, and set its price per image. See Images, audio and speech. - 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
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.

This works on streaming and non-streaming requests, and the response carries x-obleth-boons: image_generation.
What the model sees
- A
generate_imagetool withprompt,size(one of the Allowed sizes) andn(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 label | Field | Default |
|---|---|---|
| Image generation on | image_generation_enabled | false |
| Image model | image_generation_model | none; "" clears it, which turns the boon off |
| Allowed sizes | image_generation_allowed_sizes | 512x512, 1024x1024; an empty list puts the default back |
| Images per call | image_generation_max_images_per_request | 2, clamped to 1–4; 0 keeps the stored value |
| Image timeout | image_generation_timeout_ms | 120000 ms, per generation |
| Tool description | image_generation_tool_description | built-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_formatwith the structured output boon keeps its JSON: images are not attached, and the response carriesx-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.
