{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schemas.sogni.ai/creative-agent/2026-07-18.1/tools/generate_image.schema.json",
  "title": "generate_image arguments",
  "schemaVersion": "2026-07-18.1",
  "description": "Generate a new image from a text description. Usually this is text-only: do NOT use this tool when the user expects an existing image to be reused or preserved in the result. That includes (a) people from My Personas, and (b) uploaded assets such as logos, brand marks, mascots, product shots, photos, screenshots, sketches, character designs, or other reference images they want carried through. Use edit_image with sourceImageIndex=-1 (or the appropriate generated index) instead. Exception: when the user explicitly requests Z-image, Z Image, Z-image Turbo, or Krea 2 Turbo for an uploaded-image enhancement/image-to-image request, use this tool with model=\"z-turbo\", model=\"z-image\", or model=\"krea-2-turbo\", sourceImageIndex=-1, and starting_image_strength because edit_image does not expose those base image-to-image models.",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "prompt": {
      "type": "string",
      "description": "Text description of the image (50-200 words). POSITIVE phrasing only. Be specific and vivid — reference real artists, franchises, and aesthetics by name.\n\nLITERAL PROMPT OVERRIDE: If the user explicitly says not to modify the prompt, or to use it exactly/verbatim/as-is, copy the identified prompt text verbatim instead of applying these construction rules unless a hard requirement is missing.\n\nPROMPT ORDER (follow this structure): [SUBJECT] → [ATTRIBUTES] → [ACTION/POSE] → [CAMERA/FRAMING] → [ENVIRONMENT] → [LIGHTING] → [STYLE/MEDIUM] → [MATERIALS/TEXTURES] → [SECONDARY DETAILS]. Always lead with the main subject and its concrete, observable attributes — never start with mood or atmosphere. Put the most visually decisive details early.\n\nSPECIFICITY: Use concrete nouns and observable adjectives (\"weathered leather jacket\", not \"cool outfit\"). Specify framing (close-up, medium shot, full body, wide shot), angle (eye level, low angle, high angle, overhead), lighting type (\"soft overcast daylight\", \"warm golden-hour sunlight\", \"moody neon spill with deep shadows\"), and medium/style (\"photorealistic editorial photography\", \"cinematic still frame\", \"clean anime illustration\"). Include materials and textures when relevant (\"brushed aluminum\", \"wet asphalt reflections\", \"heavy wool texture\").\n\nDEFAULTS (fill in when user is underspecified): Framing: medium shot for portraits, wide shot for environments, full-body for fashion/outfits. Angle: eye level unless dramatic perspective requested. Lighting: soft natural light for realism, clean studio light for product shots. Style: photorealistic for realistic models, matching the model's native style for stylized models (e.g. anime illustration for pony/animagine). Reference real artists and franchises by name (\"in the style of Monet's Water Lilies\", \"Wes Anderson symmetrical pastel composition\", \"cyberpunk Blade Runner neon city\", \"shot on 85mm f/1.4 with shallow depth of field\").\n\nAVOID: Starting with abstract mood words alone. Burying the subject after a long style preamble. Stacking incompatible styles. Overloading with competing focal points. Vague phrases like \"very cool\" or \"epic vibes\".\n\nCHARACTER / MASCOT SHEETS: When the user asks for a character sheet, mascot sheet, model sheet, turnaround, expression sheet, or reusable character reference board, create ONE comprehensive professional reference-board image, not separate variations. Include a large hero pose, front / 3/4 / side / back turnaround views, an expression row, action/personality poses, accessories or props, color palette swatches, and compact notes such as personality, fun facts, or brand usage when appropriate. Preserve exact user-provided brand names, slogans, logo text, and requested copy verbatim; incidental tiny notes may be generated by the image model if the user did not provide exact wording. Keep the character consistent across every panel and use clean readable typography.\n\nBATCH VARIATIONS: When numberOfVariations > 1, the prompt must describe ONE subject in ONE scene — never mention counts, \"versions\", \"different\", or \"multiple\" in the prompt text. NEVER describe multiple copies or duplicates of the subject in a single image (no grids, collages, or side-by-side). Use Dynamic Prompt syntax to vary ONE dimension across separate images. Example: user asks \"4 cats in different spots\" → numberOfVariations=4, prompt=\"a black cat {lounging in a sunlit window|prowling through autumn leaves|sitting on a vintage bookshelf|curled up by a fireplace}\" — each output is ONE cat in ONE spot. Vary setting, style, lighting, expression, or composition — never override what the user specified. Preserve any requested orientation, aspect ratio, or exact pixel dimensions across every variation.\n\nSELECTION-GATED IMAGE STAGES: If the user asks for multiple image options/takes/versions and says they will pick one before a later dance, animation, or video, this tool call is still the first step. Generate the complete image batch now with the exact requested count, Dynamic Prompt options for each output, and the final video/image aspect ratio. Do not ask the user to choose before the images exist, and do not call video tools until after the user selects an image.\n\nLINKED VARIANTS: If multiple details must stay paired per output — visual style, outfit, label text, symbol, setting, character, prop, location, or before/after keyframe details — use ONE top-level Dynamic Prompt branch with one complete prompt per output. Do NOT use separate Dynamic Prompt groups for details that must stay together; unpaired groups can mix attributes. If the user asks for per-variant facial, identity, or appearance changes, repeat that guidance inside EVERY option. When the user names a subject or character, write that name or stable role inside every Dynamic Prompt option; a shared prefix outside the branch is not enough because each option must stand alone. Correct shape: \"{full prompt for variant 1 with all paired details|full prompt for variant 2 with all paired details|...}\".\n\nSCREENPLAY / STORYBOARD BATCHES: For multi-scene commercials, storyboards, or shot lists, numberOfVariations must equal the scene count and the prompt MUST be a SINGLE top-level dynamic branch containing one full scene prompt per option, e.g. \"{scene 1 full prompt|scene 2 full prompt|scene 3 full prompt}\". This is the required way to batch scenes with materially different content while still rendering one image per scene. If recurring characters appear, use stable character names and repeat the same visual anchors in every scene option where they appear (age range, build, hairstyle, outfit silhouette, color palette, signature prop/accessory, posture). Do not rename, merge, redesign, or drift characters between scene keyframes unless the user asks. Include speaker-tagged dialogue details when dialogue affects the keyframe, e.g. CHARACTER: \"We made it.\" NEVER set numberOfVariations=N with only scene 1's prompt — that creates N duplicate versions of scene 1, not N scenes. If the scene count is 16 or fewer, do it in ONE call. Do NOT generate scene 1 first or split into smaller batches unless the user explicitly asks.\n\nCOMPOSITE GPT IMAGE 2 STORYBOARD SHEETS: When numberOfVariations=1 and the user asks for one composite video storyboard/keyframe sheet, the prompt must be a compiled storyboard prompt, not a concept summary. Include a SCENES: section with exactly the requested number of concrete entries named SCENE_01, SCENE_02, etc. Every scene entry must include Visual/Action, Camera/Motion, Dialogue/VO (or [no dialogue]), Audio/SFX, and any visible text or reference usage for that scene. Do not provide only the source brief or generic layout instructions; malformed compiled storyboard prompts are blocked by quality audit.\n\nVIDEO KEYFRAMES: When generating images intended as first+last frames for video (animate_photo with frameRole=\"both\"), use numberOfVariations=2 with Dynamic Prompts to create both frames in one call. Make each frame a distinct scene that creates a compelling transition. The video handler will inspect both generated frames and build a scene-aware transition prompt, so focus this image prompt on producing strong start/end visuals. Example: \"a serene lake {at dawn with mist rising and soft pink sky|at dusk with fireflies and deep blue twilight}\"."
    },
    "model": {
      "type": "string",
      "enum": [
        "gpt-image-2",
        "gpt-image-2.5-sunburst",
        "gpt-image-2.5-flare",
        "z-turbo",
        "z-image",
        "krea-2-turbo",
        "dark-beast-krea2",
        "dark-beast-z-turbo",
        "chroma-v46-flash",
        "chroma1-hd",
        "chroma-detail",
        "pony-v7",
        "qwen-2512",
        "qwen-2512-lightning",
        "albedo-xl",
        "animagine-xl",
        "one-obsession-v22",
        "anima-pencil-xl",
        "art-universe-xl",
        "hyphoria-real",
        "analog-madness-xl",
        "cyberrealistic-xl",
        "real-dream-xl",
        "faetastic-xl",
        "zavychroma-xl",
        "pony-faetality",
        "dreamshaper-xl"
      ],
      "description": "DO NOT SET THIS PARAMETER unless the user names a specific model, asks for a very complex image render, asks for a video storyboard/storyboard sheet/contact sheet/panel layout image, asks for anime without naming a model, requests permitted NSFW/nudity content, or explicitly asks for Z-image/Z-image Turbo/Krea 2 Turbo image-to-image. The app auto-selects based on quality settings. Set \"gpt-image-2\" when the user explicitly asks for legacy GPT Image 2. Set \"gpt-image-2.5-sunburst\" by default for complex single-image renders that need very strong text rendering, dense labels, crisp typography, multi-panel composition, timing notes, foley notes, professional storyboard-sheet layout, or a comprehensive character/mascot/model sheet with turnarounds, expressions, accessories, palette swatches, and brand notes. Set \"one-obsession-v22\" when the user asks for an anime or anime-style image and has not named a specific image model. Set \"z-turbo\" when the user asks for Z-image Turbo; set \"z-image\" when they ask for Z-image without Turbo. Set \"krea-2-turbo\" when the user asks for Krea 2 Turbo. If the user names another image model, honor that requested model instead. A model preference usually does not change which tool to use; the Z-image and Krea 2 Turbo image-to-image exception uses sourceImageIndex plus starting_image_strength on this tool. NSFW rule: \"gpt-image-2\"/Qwen image models CANNOT do nudity. For permitted NSFW/nudity content, prefer \"dark-beast-krea2\", then \"dark-beast-z-turbo\"; \"chroma1-hd\", \"pony-v7\", \"chroma-detail\", \"chroma-v46-flash\", and \"z-turbo\" are compatible fallbacks. GPT Image 2.5 adds two distinct models: use \"gpt-image-2.5-sunburst\" for an explicit Sunburst request and \"gpt-image-2.5-flare\" for an explicit Flare request. For GPT Image 2.5 without a named variant, use Flare. Preserve explicit GPT Image 2.0 as \"gpt-image-2\". Sunburst is positioned for difficult images and precise edits; Flare for faster everyday generation. Both generate and edit. Model choice is independent of rendering quality."
    },
    "width": {
      "type": "number",
      "description": "Output image width in pixels. Default: 1024. Supported bounds depend on the selected image model: Z-Image/Z-Image Turbo, Dark Beast Z-Image Turbo, Chroma, and legacy/specialized image models support 256-2048 on either edge; Krea 2 Turbo, Dark Beast KREA 2, and Qwen image models support 256-2560 on either edge; One Obsession v22 supports 256-1920 on either edge; GPT Image 2 supports flexible dimensions up to 3840px on either edge with max 3:1 aspect ratio and a total pixel budget from 655,360 to 8,294,400. Set when the user specifies a width, exact pixel dimensions, or a named resolution (e.g., \"1280 wide\", \"1280x720\", \"720p\", \"1080x1920\", \"3840x2160\"). If the user gives only one dimension, set only that dimension and preserve/infer the sensible aspect ratio. User-requested dimensions override the default media quality, including Pro. Non-multiple-of-16 values are accepted when in bounds; the renderer snaps to the nearest supported size internally, so do not ask the user to adjust by a few pixels."
    },
    "height": {
      "type": "number",
      "description": "Output image height in pixels. Default: 1024. Supported bounds depend on the selected image model: Z-Image/Z-Image Turbo, Dark Beast Z-Image Turbo, Chroma, and legacy/specialized image models support 256-2048 on either edge; Krea 2 Turbo, Dark Beast KREA 2, and Qwen image models support 256-2560 on either edge; One Obsession v22 supports 256-1920 on either edge; GPT Image 2 supports flexible dimensions up to 3840px on either edge with max 3:1 aspect ratio and a total pixel budget from 655,360 to 8,294,400. Set when the user specifies a height, exact pixel dimensions, or a named resolution (e.g., \"720 high\", \"1280x720\", \"720p\", \"1080x1920\", \"2160x3840\"). If the user gives only one dimension, set only that dimension and preserve/infer the sensible aspect ratio. User-requested dimensions override the default media quality, including Pro. Non-multiple-of-16 values are accepted when in bounds; the renderer snaps to the nearest supported size internally, so do not ask the user to adjust by a few pixels."
    },
    "numberOfVariations": {
      "type": "number",
      "description": "Number of variations (1-16). Use the user's exact requested count in one call whenever they ask for multiple images/options/takes/versions, including images that will feed a later video after the user picks one. For screenplay/storyboard batches, this must equal the scene count AND the prompt must contain one Dynamic Prompt branch with one full scene prompt per scene; never set numberOfVariations=N with only one scene prompt. Default: 1.",
      "minimum": 1,
      "maximum": 16
    },
    "negativePrompt": {
      "type": "string",
      "description": "Things to avoid in the generated image. Only set when the user explicitly mentions what to avoid. E.g., \"no watermarks, no text, no blurry edges\"."
    },
    "starting_image_strength": {
      "type": "number",
      "description": "Image-to-image source guidance strength (0.0-1.0). Only set when a source image is available and the model supports img2img. For Z-Image/Z-Image Turbo, Krea 2 Turbo, or source-preserving enhancement requests, use 0.75 with sourceImageIndex so the source image remains a strong guide while allowing higher-resolution reconstruction. Use lower values only when the user explicitly asks for a lighter guide/subtle variation; higher values are more creative and can deviate further from the source."
    },
    "sourceImageIndex": {
      "type": "number",
      "description": "Which result image to use as starting image for img2img (0-based index). -1 = original upload. Omit to auto-select latest result. Only relevant when starting_image_strength is set."
    },
    "seed": {
      "type": "integer",
      "description": "Random seed for reproducibility. Use -1 for random (default). Set a specific seed when the user wants to reproduce a previous result."
    },
    "guidance": {
      "type": "number",
      "description": "Guidance scale override. Higher values = more prompt adherence. Model-specific defaults are used if omitted. Only set when the user explicitly requests a guidance value."
    },
    "gptImageQuality": {
      "type": "string",
      "enum": [
        "low",
        "medium",
        "high",
        "xhigh",
        "max"
      ],
      "description": "Optional GPT Image rendering quality. Only set it when the user explicitly asks for low/fast, medium/balanced, high/final, xhigh/extra high, or max/maximum quality; xhigh and max require GPT Image 2.5 Sunburst or Flare. Provider-chosen (auto) quality is never used. Otherwise omit it and let the host app media quality setting map Fast to low, HQ to medium, and Pro to high. The same quality label does not promise equivalent results across models."
    },
    "outputFormat": {
      "type": "string",
      "enum": [
        "png",
        "jpg",
        "jpeg",
        "webp"
      ],
      "description": "Optional output file format for generated images. Set only when the user explicitly requests PNG, JPG/JPEG, or WebP. Hosts should normalize \"jpeg\" to the Sogni project format \"jpg\"."
    },
    "aspectRatio": {
      "type": "string",
      "description": "Do NOT set unless the user explicitly requests an aspect ratio, format, orientation, or exact pixel dimensions. When a reference/source image is used and the user did not ask to change its shape, omit this field so the handler preserves the selected source image's own ratio.\n\nFormats: \"16:9\", \"9:16\", \"4:5\", \"1:1\", \"4:3\", \"3:2\", \"21:9\", or exact pixels like \"1920x1080\".\n\nCRITICAL: When the user specifies exact pixel dimensions (e.g., \"1280x720\", \"1080x1920\", \"1920x1080\", \"3840x2160\") or an orientation-qualified named resolution (e.g., \"720p landscape\", \"720p portrait\"), use the exact pixel format, NOT a ratio like \"16:9\" or \"9:16\". Exact user-requested dimensions override the selected default media quality, including Pro/HQ defaults. A bare named video resolution like \"720p resolution\" is only a resolution tier/short-side request; do not turn it into landscape pixels and do not set aspectRatio unless the user also states landscape, portrait, vertical, horizontal, or exact pixels. If requested pixels are in bounds but not on the model's pixel step, still pass the user's exact pixel request; the handler snaps to the nearest supported size internally. Only use ratio format when the user says a generic format name without pixel dimensions.\n\nMappings (use ONLY when user does NOT specify pixel dimensions): landscape/widescreen/YouTube/cinematic → \"16:9\". portrait → \"9:16\". TikTok/Reels/IG Reels → \"1080x1920\". ultrawide/cinema scope → \"21:9\". Instagram post → \"4:5\". square → \"1:1\". standard/TV → \"4:3\". 720p landscape → \"1280x720\". 720p portrait → \"720x1280\". 1080p landscape → \"1920x1080\". 1080p portrait/HD portrait → \"1080x1920\". 4K landscape → \"3840x2160\". 4K portrait → \"2160x3840\". Never set for generic requests like \"make a video\".\n\nSet this whenever the user specifies an image or downstream video orientation/aspect ratio such as 9:16, 16:9, portrait, vertical, landscape, widescreen, TikTok/Reels/Shorts, or exact pixels. This includes selection-gated image batches that will feed a later video or dance after the user picks one. For GPT Image 2 exact size requests, preserve exact pixel intent when possible and prefer popular GPT sizes such as 1536x1024, 1024x1536, 2048x1152, 3840x2160, and 2160x3840. Sogni does not expose transparent output for GPT Image 2.0. For transparent assets, select GPT Image 2.5 Sunburst or Flare with gptImageBackground=transparent and PNG or WebP output."
    },
    "gptImageBackground": {
      "type": "string",
      "enum": [
        "auto",
        "opaque",
        "transparent"
      ],
      "description": "GPT Image background: auto or opaque; transparent is supported by GPT Image 2.5 Sunburst and Flare with PNG or WebP output. JPEG cannot preserve transparency."
    },
    "gptImageOutputCompression": {
      "type": "integer",
      "minimum": 0,
      "maximum": 100,
      "description": "Optional GPT Image JPEG/WebP output compression, from 0 to 100. Omit for PNG."
    },
    "loras": {
      "type": "array",
      "minItems": 1,
      "maxItems": 8,
      "items": {
        "type": "string",
        "minLength": 1
      },
      "description": "Ordered LoRA IDs to apply to a compatible image model. Use only when the user explicitly requests LoRAs or asks for an effect one of these names directly. Stack up to 8 in one request; order matters because the adapters apply in sequence and do not commute. Keep this array positionally aligned with loraStrengths. The first render with an uncached LoRA takes longer to start while the worker downloads it.\n\nAccepted only by the five Krea 2 based models: krea2_turbo_fp8_scaled (text-to-image), krea2_identity_edit_v1_2 and krea2_identity_edit_sogni_v0_3_alpha (identity edit), and the dark_beast_krea2_fp8 / dark_beast_krea2_identity_edit_v1_2 community variants.\n\nBipolar sliders — each id names its POSITIVE direction, a negative strength applies the opposite, and 0 disables it: krea2-detail-enhancer, krea2-scene-complexity, krea2-realism (+ = photoreal), krea2-amateur, krea2-candid, krea2-zoom (+ = zoomed in), krea2-skin-detail, krea2-wetness, krea2-age, krea2-height, krea2-weight, krea2-hourglass-figure, krea2-breast, krea2-chest-firmness, krea2-nipple-projection, krea2-warm-light, krea2-afterlight (+ = golden), krea2-skin-tone (+ = darker), krea2-purple-grainy (+ = grainy and muted). Positive-only fine-tunes: krea2-realism-engine (photographic realism), krea2-bloomgirls (polished influencer look), krea2-mystic-x (uncensored adult), krea2-aberrant (industrial body horror), krea2-filter-bypass-2 and krea2-filter-bypass-3 (restore expressions, anatomy and poses the base model flattens; try the 2-vector first). Exact per-LoRA ranges, maturity flags and the full contract: GET /v1/loras/comfy?modelId=<model>. Personal imports use authenticated GET /v1/loras/personal/catalog: use an owned ready personal- id, its modelIds, strength range and requirements. Never invent ids or silently omit a requested personal LoRA."
    },
    "loraStrengths": {
      "type": "array",
      "minItems": 1,
      "maxItems": 8,
      "items": {
        "type": "number"
      },
      "description": "Strength for each LoRA in loras, in the same order. Omitting the array uses 1.0 for every LoRA, which is not each LoRA's catalog default — krea2-chest-firmness, krea2-nipple-projection and krea2-height default to 0 (no effect) — so prefer explicit values. Do NOT clamp to 0-1: most Krea 2 LoRAs are bipolar, so krea2-warm-light warms the grade at 2 and cools it at -2. Usable bands vary per LoRA — roughly -2..5 for krea2-detail-enhancer, -3..3 for krea2-warm-light, 3..9 for krea2-candid, 0.5..1 for krea2-realism-engine, 1..2 for the filter-bypass pair. Scale the magnitude to how strongly the user asked; the server clamps out-of-range values, and pushing past a LoRA's recommended band costs image quality rather than adding effect. Preserve explicit user values. Example: loras=[\"krea2-detail-enhancer\",\"krea2-amateur\"], loraStrengths=[3,-2]."
    }
  },
  "required": [
    "prompt"
  ]
}
