make_ugc
Optional convenience workflow for one finished vertical UGC video from a script. Use it when the user wants the server to choose takes and timing, join a long monologue, and optionally burn captions. Use the direct generate_image, generate_video and generate_audio tools instead when the agent needs custom models, modes, shot structure, intermediate assets, or a different composition. Use image for a person photo, product_image for a product photo, or character for a saved character. Use scene for where it happens (a beach, a gym, in bed, a car); without a place the video is set in an ordinary room. Call quote_ugc with the exact same input first; it costs no credits. Ask before setting captions:true. After submission, keep calling get_run_status until it returns the finished video URL. Files it lists under So far are intermediate, not the result.
When the user wants to provide a product photo, portrait, screenshot, or image reference, check tools/list. If open_upload_panel is available, offer it first: call open_upload_panel with {}, show its inline panel or returned browser link, and wait for the user to finish. Then call get_uploads with the returned session_id and use the exact ready image_url in refs, first_frame, last_frame, or the matching skill image field. Do not start a reference-dependent generation until the required images are ready. The panel accepts still PNG, JPEG, and WebP, up to 10 images and 25 MB each. Images expire 24 hours after the panel is created; show the returned expiry, request a new upload if expired, and never make a permanent copy. Uploading uses no generation credits. Do not ask the user for base64, shell commands, or a public hosting service; do not continuously poll while waiting for them. Only call these tool names when discovered. If they are missing from the connected tool catalog, call upload_image with {} to open the same panel; use the returned panel: upload_key with upload_image to retrieve images after the user finishes. If that reports the panel is unavailable, use upload_image only for an already accessible file or URL. Do not build an upload page or request a local folder as a substitute for the existing panel. Never invent access to a chat attachment: if you cannot read it, explain that and offer the panel when available. Browser fallback works without inline UI support; do not promise an inline panel in every client. Inspect the native image previews returned with retrieved uploads before describing them or writing image-specific prompts. Never infer what the image shows from an email domain, account metadata, or filename. Use the original URLs for generation, not preview bytes. If the session ID was lost, call get_uploads with {} to list recent sessions, or upload_image with {"upload_key":"panel:recent"} for cached catalogs; retrieve the matching session before asking for re-upload. Account-wide recent uploads may belong to other conversations, so clarify ambiguous selection. Uploading stores an image; it does not attach it to a generation automatically. If the user already requested a generation with these images, continue that request using the returned URLs; do not stop at "upload complete" or ask again whether to use them. If make_ugc fits the requested outcome, pass a person photo as image or a product photo as product_image, then call quote_ugc before spending. Otherwise compose the direct generators: for generate_image, put the relevant image_url values in refs; for generate_video, use refs for product/person/appearance references, or first_frame for animating a still (last_frame only for an explicitly requested ending frame), and never combine refs with frame fields. Preserve the user's intended image roles and model limits; ask only if the role or selection is unclear. Include the URL in the tool arguments, not only in the prompt. Do not substitute a newly generated image for the uploaded reference. If the request was upload-only, report readiness and wait for a generation request; uploading alone does not authorize spending credits. After submitting, poll get_run_status and return the result.
IMAGES: pass an https URL. If you only have raw bytes or a data: URL, call upload_image FIRST and pass the URL it returns. Never paste base64 into these arguments, the client prints tool arguments in the conversation, so a base64 image becomes a wall of text for the user and is re-sent on every retry.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| look | No | natural | |
| name | No | Name/age/vibe hint, e.g. 'Sophia, 28'. | |
| image | No | A photo of the person, an https URL. The face is locked to it. If you only hold bytes, call `upload_image` first and pass the URL it returns; base64 is still accepted here but it is printed into the user’s chat and re-sent on every retry. | |
| music | No | ||
| scene | No | WHERE the video happens, in a few words: 'on a sunny beach, sea behind her', 'in a gym by the weights', 'in bed at night with a lamp on', 'in a parked car'. Set it whenever the user names a place. Without it the video is set in an ordinary room. | |
| person | No | Describe the person in words. Omit if you pass image or character. | |
| script | No | What the person SAYS (lip-synced), any length. A one-liner makes one clip; a full monologue makes the full multi-take video automatically, never trimmed. Usually the only field you set. EXCEPTION: when you also pass product_image the video is a SINGLE take of at most 15s, so the script must be 46 words or fewer. | |
| captions | No | Burn in TikTok/Hormozi captions. OFF unless set true, ASK the user whether they want captions (and which caption_style) before generating; never add captions unprompted. | |
| duration | No | IGNORED when `script` is set: length follows how long the words take to say (~2.9 words/sec; one take: up to 15 words → 5s, up to 31 → 10s, up to 46 → 15s; longer scripts become several takes sized the same way). A video is never stretched to reach a requested duration; silence between takes and at the end is cut, so the final video runs about as long as the speech. To get a longer video, write more words (~2.8 words per extra second). The response's take_plan shows the takes. Only used for a silent `scene_action` clip, which has no words to measure. | |
| broll_url | No | A b-roll / gameplay / product video overlaid on the lower half while the person narrates. | |
| character | No | Reuse a saved character: its character_id (char_…) OR its character_sheet_url from list_characters. | |
| aspect_ratio | No | 9:16 | |
| scene_action | No | A silent action clip (dancing, b-roll, vibes), no dialogue. Use instead of script; needs a `character`. | |
| caption_style | No | hormozi | |
| product_image | No | A photo of a PRODUCT to show/hold/wear, an https URL. If you only hold bytes, call `upload_image` first and pass the URL it returns: base64 travels inside this tool call, is printed into the user’s chat, and is re-sent on every retry. Turns the video into a product ad; needs a `character` to hold it, and limits `script` to ONE take of at most 15s (46 words). |