Generate Images
Image Generation lets a deployed agent turn a prompt into one or more images. Agent steps call the typed ctx.sapiom.contentGeneration.images capability; Sapiom supplies the authenticated cloud connection when the deployed agent runs.
Choose the generation pattern
Section titled “Choose the generation pattern”| What the agent needs | Recommended operation or input |
|---|---|
| Generate and wait in the current step | contentGeneration.images.create(...) |
| Suspend the workflow while generation finishes | images.launch(...) plus pauseUntilSignal(...) |
| More than one image | Set count |
| A durable private asset | storage: { visibility: "private" } |
| An asset intended for public sharing | storage: { visibility: "public" } |
| A video rather than an image | ctx.sapiom.contentGeneration.video.create or .launch |
Use create for an ordinary blocking step. Use launch when the workflow should pause and resume on the completed generation instead of holding the launching step open.
Generate and persist images
Section titled “Generate and persist images”const generation = await ctx.sapiom.contentGeneration.images.create({ prompt: "Editorial illustration of a solar-powered city block at sunrise, clean geometric forms", aspectRatio: "16:9", count: 2, storage: { visibility: "private" },});
const images = generation.images ?? [];if (images.length === 0) { throw new Error("Image generation returned no images");}
return { resolvedModel: generation.resolvedModel, images: images.map((image) => { if (image.storageError) { throw new Error(`Image persistence failed: ${image.storageError}`); }
return { fileId: image.fileId ?? null, temporaryUrl: image.url, width: image.width ?? null, height: image.height ?? null, }; }),};The result includes the resolvedModel and an optional images array. Each image has a provider-hosted url and can include dimensions and content type. Treat the provider URL as temporary.
When storage succeeds, retain fileId as the durable reference. A returned downloadUrl is convenient but short-lived; mint a fresh one later with ctx.sapiom.fileStorage.getDownloadUrl(fileId). Persistence is per output, so inspect storageError on every image rather than assuming the whole batch stored successfully.
Control the output without pinning a provider
Section titled “Control the output without pinning a provider”Omit model unless the agent needs a specific Sapiom routing alias. Prefer the neutral fields—aspectRatio, count, seed, negativePrompt, referenceImage, and outputFormat—over provider-specific passthrough values. A field unsupported by the selected model is rejected rather than silently ignored.
Generation is not guaranteed to be visually identical across models or service updates. Use a deterministic seed only where the selected model supports it, and test downstream code against the returned shape rather than pixel identity.
Dispatch generation
Section titled “Dispatch generation”images.launch returns a handle with a request ID, resolved model, wait(), and the signal metadata required by pauseUntilSignal:
const handle = await ctx.sapiom.contentGeneration.images.launch({ prompt: input.prompt, storage: { visibility: "private" },});
return pauseUntilSignal(handle, { resumeStep: "use-image" });Declare the matching static pause edge on the launching step. The resumed step receives a plain result payload with outputs, not the live handle or the same images wrapper returned by create(). Import the installed result type instead of hand-writing that payload.
Test the behavior locally
Section titled “Test the behavior locally”Local Run replaces image generation with deterministic data and does not generate or store an image. Override the exact path when the step requires a stored output or a particular failure:
{ "version": 1, "steps": { "generate-hero": { "contentGeneration.images.create": { "images": [ { "url": "https://fixtures.example/hero.png", "contentType": "image/png", "width": 1280, "height": 720, "fileId": "file-hero-local", "downloadUrl": "https://fixtures.example/hero-download", "downloadUrlExpiresAt": "2099-01-01T00:00:00.000Z" } ], "resolvedModel": "stub-model" } } }}contentGeneration.images.launch can use its own override or the shared create result. After the run, assert the terminal output and require both unusedStubs and stubWarnings to be empty. A passing fixture does not prove live model availability, visual quality, storage, latency, or usage.
Manage usage and retention
Section titled “Manage usage and retention”Image count, model route, dimensions, and persistence can affect runtime usage. Generate only the variants the decision needs, avoid retrying a satisfactory output, and request storage only when the result must survive the provider URL.
Use the signed-in capability catalog for current models, limits, and pricing. Do not copy a model inventory or fixed rate into the agent.
© 2026 Sapiom, Inc.