{"ok":true,"site":{"host":"gengastudio.com","url":"https://gengastudio.com/app","type":"live","desc":"Genga Studio is a cutting room for AI-generated animation. The page publishes every one of its actions as a WebMCP tool, so an agent drives the same buttons you would click.","tools":[{"name":"find_shots","kind":"answer","impl":"imperative","description":"Find shots in the current film by anything a director would say: a sid (B10-S2), a number in the cut (\"shot 37\"), a beat (\"B11\"), a character (\"David Ross\"), a shot type (\"close-up\") or a free description (\"the cemetery\"). Returns up to eight matches with their ordinal, beat, type, one-line summary and whether they already have a keeper still, motion or a source playing in the timeline. When a phrase matches two different shots the confidence comes back \"ambiguous\" — ask which one before acting.","title":"Find shots","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"What the director said: a sid, a number, a beat, a character name, a shot type, or a description."}},"required":["query"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"describe_shot","kind":"answer","impl":"imperative","description":"Read one shot's script and state without changing anything: its beat, act, type, duration, image and motion prompts, dialogue or narration line, the film's style register, the curated keeper, what currently plays in the timeline, how many takes exist of each kind with the newest few paths, comps, and which backend each lane would use with its cost class. Use it before generating so the prompt you send builds on the shot the director actually wrote.","title":"Describe a shot","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description like \"the Ross close-up\"."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"get_context","kind":"answer","impl":"imperative","description":"Report what is on screen right now: the current route and project, whether the Film Editor or a Shot Editor is open, which shot, which tab and generate sub-tab, the selected take, the keeper, what plays in the timeline, any jobs still running, what the project has spent, the film's style register, the WebMCP mode the page is in and the playback speed. Call it first when you are unsure what the director is looking at, or after a navigation, before acting on \"this shot\" or \"the newest one\".","title":"Where am I?","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"list_features","kind":"answer","impl":"imperative","description":"List what Genga Studio can do and where each feature lives in the UI, optionally filtered by a word like \"freeze\", \"comp\", \"opacity\" or \"voice\". With no query it returns every callable tool plus a count per screen; with a query it searches the WHOLE application, including the hundred-odd controls that are not tools, and gives each one its screen path and how a human does it by hand. Then call show_me to navigate there and pulse the control.","title":"List Genga Studio features","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"Optional filter word, e.g. \"freeze\", \"comp\", \"opacity\", \"timeline\", \"backend\". Also matches a screen name."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"show_me","kind":"act","impl":"imperative","description":"Teach a Genga Studio feature by driving to it: navigates to the screen where the feature lives, highlights the actual control with a pulse, and explains how a human does it by hand. Answers \"where is that?\", \"how do I do that myself?\" and \"show me the freeze tool\". Nothing is generated and nothing is changed — this only moves the view. Pass a feature name or plain words like \"freeze tail\", \"cut the film\", \"set the keeper\", \"voice over\".","title":"Show me how","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"feature":{"type":"string","description":"The feature to show: a tool name or plain words, e.g. \"freeze tail\", \"keeper\", \"cut the film\"."},"shot":{"type":"string","description":"Optional shot to demonstrate on, when the feature lives inside the Shot Editor."}},"required":["feature"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"open_shot","kind":"act","impl":"imperative","description":"Open a shot in the Shot Editor so the director can see it, optionally landing on a specific tab (compose, generate, motion, audio, script), a generate sub-tab (still, restyle, animate, chain) and a selected take. The page navigates on screen and the tab is highlighted. Use it to put the right room in front of the human before you change anything, or when they say \"show me shot 37\". Returns the resolved sid and what is now visible.","title":"Open a shot","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"tab":{"type":"string","enum":["compose","generate","motion","audio","script"],"description":"Which workspace tab to land on. Default: leave the tab as it is."},"sub":{"type":"string","enum":["still","restyle","animate","chain"],"description":"Which Generate sub-tab to open (implies tab=generate)."},"take":{"type":"string","description":"A take to select: a path, or \"latest\", \"newest still\", \"newest motion\", \"keeper\", \"plays\"."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"generate_takes","kind":"act","impl":"imperative","description":"Generate new takes for a shot — stills, restyles of an existing take, or animated cel clips. Opens the Generate console, fills it, and submits one job per take with a fresh seed. Count 1–4 (default 3); paid backends need confirm_cost. ANIMATE STARTS FROM THE KEEPER STILL — to animate another, pass source (a path or \"selected\"). Readable text needs model:\"pro\"; attach_reference pins a face or place, restyle edits a frame. Motion results carry situational guidance.","title":"Generate takes","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description like \"the Ross close-up\"."},"lane":{"type":"string","enum":["still","restyle","animate"],"description":"still = new image · restyle = image-to-image on an existing take · animate = motion clip. Default still."},"count":{"type":"integer","minimum":1,"maximum":4,"default":3,"description":"How many takes to submit, 1–4. Words like \"a few\" (3) or \"a couple\" (2) are accepted too."},"prompt":{"type":"string","description":"Prompt text. Omit to use the shot's written image or motion prompt exactly as the director wrote it."},"prompt_mode":{"type":"string","enum":["replace","append"],"description":"replace = use only your prompt (default) · append = add yours to the shot's own prompt."},"source":{"type":"string","description":"Which image to start FROM: a take path, \"selected\", \"third still\" or \"keeper\". Animate defaults to the keeper; restyle to the selected take."},"source_take":{"type":"string","description":"For restyle: the take to restyle. A path, or \"latest\", \"newest still\", \"keeper\". Defaults to the selected take. Same as source."},"denoise":{"type":"number","description":"Restyle strength, 0.35–0.95. 0.55 keeps the layout, 0.85 restyles. Default 0.85."},"region":{"type":"array","items":{"type":"number"},"description":"For animate: the cel region as [left, top, right, bottom]. Omit to animate the full frame."},"seconds":{"type":"number","description":"For animate: clip length in seconds. Defaults to the backend's own clip length and is clamped to what it supports."},"frames":{"type":"integer","description":"For animate: exact frame count, when you need one. Normally leave it and pass seconds instead."},"live_seconds":{"type":"number","description":"For animate: freeze after this many seconds. Only for a model that drifts after N seconds — clips play in full otherwise."},"seeds":{"type":"array","items":{"type":"integer"},"description":"Exact seeds to use, one per take. Omit for fresh random seeds (the usual case)."},"backend":{"type":"string","description":"Force a specific backend id instead of the project's lane default (e.g. \"mock\", \"comfyui\", \"fal\")."},"model":{"type":"string","description":"Force a model. Stills: \"pro\" for readable text, \"flash\" (cheap default). Motion: \"seedance\", \"wan\". A full endpoint id works too."},"confirm_cost":{"type":"boolean","description":"Set true to approve a paid backend. Required whenever the lane resolves to a backend that bills money."},"references":{"type":"array","items":{"type":"object"},"description":"One-off reference images for this call only: [{image, role}], role character/prop/setting/style. attach_reference makes one stick."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"freeze_tail","kind":"act","impl":"imperative","description":"Repair a clip that goes wrong late: keep its good first seconds live and hold the last good frame as a true freeze, instead of rerolling the whole clip. Use it when you can see a clip drift, warp or wander after N seconds — clips otherwise play in full. It is also the held-cel edit anime uses so a gesture reads and the pose sits. Opens Motion edits, selects the clip, sets the seconds kept and presses ❄ freeze tail. A real frozen frame, never a zoom or a drift.","title":"Freeze the tail","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"take":{"type":"string","description":"Which clip: a path, or \"newest motion\", \"latest\", \"plays\". Defaults to the selected clip."},"live_seconds":{"type":"number","description":"Seconds of good motion to keep before the freeze holds. Set it where the clip starts to degrade. Default 1.0."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"trim_clip","kind":"act","impl":"imperative","description":"Cut a motion clip short, keeping only what happens before a given second. Opens the shot's Motion edits tab, selects the clip and presses ✂ so the take ends where the action ends — use it when a generated clip drifts or repeats after the beat lands. Requires end_seconds. Unlike freeze_tail this shortens the take rather than holding a pose. Returns the job and, when it finishes fast, the trimmed take.","title":"Trim a clip","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"take":{"type":"string","description":"Which clip: a path, or \"newest motion\", \"latest\", \"plays\". Defaults to the selected clip."},"end_seconds":{"type":"number","description":"Keep everything before this second and drop the rest. Required."}},"required":["shot","end_seconds"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"select_take","kind":"act","impl":"imperative","description":"Put one take on the Shot Editor's monitor so the director can see it and so the next edit acts on it. Accepts a take path or the words a director uses: \"latest\", \"newest still\", \"newest motion\", \"keeper\", \"plays\" or a position like \"the third still\". The rail scrolls to it and pulses. Call this before freeze_tail, trim_clip, set_keeper or a restyle when the director says \"that one\" or \"the newest\". Returns the selected path, its kind and duration.","title":"Select a take","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"take":{"type":"string","description":"A path, or: \"latest\", \"newest still\", \"newest motion\", \"keeper\", \"plays\", \"selected\", \"third still\"."}},"required":["shot","take"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"set_keeper","kind":"act","impl":"imperative","description":"Mark a still as the shot's keeper — the curated plate. Motion, i2i and compose start from the shot's keeper still. To animate from a different still, set it as keeper first (or pass source to generate_takes). Presses ★ keeper on the take. Stills only; clips are refused (use set_timeline_source for what plays). Takes a path, \"selected\", or a position like \"third still\"; defaults to the selected take. Returns the new keeper as the server confirms it. The old keeper stays in the rail.","title":"Set the keeper","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"take":{"type":"string","description":"Which still to keep. A path, or: \"latest\", \"newest still\", \"newest motion\", \"keeper\", \"plays\", \"selected\", \"third still\". Defaults to the selection."},"note":{"type":"string","description":"Optional curation note recorded with the pick, e.g. \"best eyeline, hands read\"."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"set_timeline_source","kind":"act","impl":"imperative","description":"Choose which take actually plays for this shot in the cut — the ⬆ timeline source override. Any take works: a still, a restyle, a motion clip or a frozen one. Presses ⬆ on the take, and the Film Editor immediately shows the new pick. Pass clear:true to drop the override and fall back to the shot's default (keeper, or the newest motion). Defaults to the selected take. Run cut_film afterwards to see it in a rendered cut.","title":"Set what plays","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"take":{"type":"string","description":"Which take plays. A path, or: \"latest\", \"newest still\", \"newest motion\", \"keeper\", \"plays\", \"selected\", \"third still\". Defaults to the selection."},"clear":{"type":"boolean","description":"True removes the override so the shot falls back to its default source."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"set_shot_timing","kind":"act","impl":"imperative","description":"Retime a shot in the cut: how many seconds it holds, how far its voice-over slides against the picture, and whether the VO is muted. Opens the Film Editor, selects the shot and edits its quick panel, so the strip re-widths in front of the director. Positive vo_offset delays the line, negative pulls it earlier. Anything you leave out is left alone. Takes effect on the next cut_film. Returns the resulting override.","title":"Set shot timing","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"seconds":{"type":"number","description":"How long the shot holds in the cut, in seconds. Overrides the scripted duration."},"vo_offset":{"type":"number","description":"Seconds to slide the voice-over: positive delays the line, negative pulls it earlier."},"mute_vo":{"type":"boolean","description":"True silences this shot's voice-over in the cut; false restores it."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"synthesize_vo","kind":"act","impl":"imperative","description":"Record a voice-over line for a shot. Opens the shot's Audio tab, fills the line, voice and treatment, and presses ▶ synthesize. Defaults to the line the script already gives the shot — its narration or first piece of dialogue — so you usually only pass the shot. `treatment` is what the line is heard through: none (default), radio, phone, megaphone or hall. ElevenLabs v3 tags pass through. Paid voice backends require confirm_cost. Returns job and take.","title":"Synthesize a voice-over","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"text":{"type":"string","description":"The line to speak. Omit to use the shot's own narration or first dialogue line as written."},"voice":{"type":"string","description":"Voice id on the VO backend. Omit for the project's default voice."},"treatment":{"type":"string","enum":["none","radio","phone","megaphone","hall"],"description":"What the line is heard through: none (default), radio, phone, megaphone or hall."},"backend":{"type":"string","description":"Force a specific VO backend id instead of the project's lane default."},"confirm_cost":{"type":"boolean","description":"Set true to approve a paid voice backend. Required whenever the VO lane bills money."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"direct_shot","kind":"act","impl":"imperative","description":"Compile a plain-English direction into Genga Studio's own edit plan and show it on screen as a preview — \"hold his pose for the rest of the line\", \"restyle this warmer\", \"make it two seconds longer\". Types the instruction into the shot's Direct box and compiles it; the deterministic grammar goes first and reads the real voice-over duration. Clips play in full unless the direction asks for a freeze. NOTHING RUNS: it only returns the plan. Show it, then call apply_plan.","title":"Direct this shot","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"instruction":{"type":"string","description":"The direction in plain English, exactly as the director said it."}},"required":["shot","instruction"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"apply_plan","kind":"act","impl":"imperative","description":"Run an edit plan that direct_shot compiled, after the director has approved it. Presses ▶ apply on the plan preview, so the same ops a human would run execute in order: freezes, trims, generations and state changes. Pass the plan object direct_shot returned, unchanged. Returns the jobs it submitted and how each op landed. Only call this once the human has said yes to the preview.","title":"Apply the plan","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot the plan belongs to: a sid, its number in the cut, or a description."},"plan":{"type":"object","description":"The plan object direct_shot returned, unchanged: { ops: [...], note }.","properties":{"ops":{"type":"array","items":{"type":"object"},"description":"The ops to run, in order."},"note":{"type":"string","description":"The plan's note."}},"required":["ops"]}},"required":["shot","plan"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"cut_film","kind":"act","impl":"imperative","description":"Assemble the film as it currently stands into a watchable cut: every shot's chosen source, its duration, its voice-over and offsets, in film order. Sets the scope (the whole film or a single act) and the resolution on the Film Editor, then presses 🎞 cut the film. Use it after a run of picks or retimes so the director can watch the change in context. 720 is the preview, 1080 the final. Returns the job and, when it renders fast, the cut's path and duration.","title":"Cut the film","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"scope":{"type":"string","enum":["full","act1","act2","act3","act4"],"description":"What to assemble: the whole film, or one act. Default full."},"res":{"type":"string","enum":["720","1080"],"description":"Resolution: \"720\" for a preview (default) or \"1080\" for the final."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"get_jobs","kind":"answer","impl":"imperative","description":"Check on generation jobs without waiting: their status, what they produced and, for anything that failed, the tail of the log with the reason. Pass the job ids a generation tool returned, or call it with no arguments for the project's most recent jobs. Use it when the director asks \"is it done yet?\" or after a tool came back with jobs still running. Returns immediately — call wait_for_jobs instead when you want to block until they finish.","title":"Check jobs","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"jobs":{"type":"array","items":{"type":"string"},"description":"Job ids to check (up to 8). Omit for this project's most recent jobs."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"wait_for_jobs","kind":"act","impl":"imperative","description":"Wait for generation jobs to finish, up to 60 seconds, then report what landed. Progress stays visible in the topbar and the Jobs page while you wait. Use it after a generation tool returns jobs that are still running, so the next thing you say to the director is the actual result rather than a promise. Anything still running when the timeout expires comes back as \"running\" — call again or check with get_jobs. Returns each job's status and the takes it produced.","title":"Wait for jobs","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"jobs":{"type":"array","description":"The job ids to wait for (up to 8), as returned by a generation tool (ids, or the job objects a previous wait returned)."},"timeout_s":{"type":"integer","minimum":1,"maximum":60,"default":30,"description":"How long to wait, in seconds. Capped at 60."}},"required":["jobs"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"generate_music","kind":"act","impl":"imperative","description":"Compose a music cue for the film and lay it on the audio bed. Opens a shot's Audio tab, fills the Music console, presses ▶ music, then places the finished piece as a cue — at that shot's start, at a time you name, or at the head of the film. Describe the music the way a director would (instrument, tempo, feeling). Gain is decibels: -8 is a bed under narration, 0 is a hero cue. Paid backends require confirm_cost. Set place false to audition it without touching the cut.","title":"Score a stretch of the film","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"The music, in plain words: instruments, tempo, mood — e.g. 'slow upright bass and brushed snare, elegiac'."},"seconds":{"type":"number","minimum":5,"maximum":120,"default":30,"description":"How long the piece runs. The ElevenLabs music model's floor is 10s; shorter asks are raised to it."},"instrumental":{"type":"boolean","description":"True forbids vocals — the right default for anything sitting under dialogue."},"shot":{"type":"string","description":"Place the cue at this shot's start: a sid (B10-S2), its number in the cut, a beat, or a description."},"start":{"type":"number","description":"Place the cue at this many seconds into the film instead. Ignored when shot is given."},"gain":{"type":"number","description":"Cue level in dB. 0 is unity, negative is quieter. Defaults to -8, a bed under the voice-over."},"fade_in":{"type":"number","description":"Fade the cue up over this many seconds."},"fade_out":{"type":"number","description":"Fade the cue down over this many seconds at its end."},"place":{"type":"boolean","default":true,"description":"False generates the take but leaves the cut alone — audition first, place later with place_cue."},"backend":{"type":"string","description":"Force a music backend id instead of the project's lane default."},"confirm_cost":{"type":"boolean","description":"Set true to approve a paid music backend. Required whenever the music lane bills money."}},"required":["prompt"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"generate_sfx","kind":"act","impl":"imperative","description":"Make a sound effect for one shot and pin it there. Opens that shot's Audio tab, fills the SFX console, presses ▶ sfx, then places the result as a cue at the shot's start plus any offset you give — so it follows the shot when the timing changes. Describe the sound, not the feeling: 'a heavy wooden door slamming in a stone hall'. Gain is decibels; -4 is an accent, -18 is a bed. Paid backends require confirm_cost.","title":"Add a sound effect to a shot","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"prompt":{"type":"string","description":"The sound itself — source, material and space, e.g. 'chalk scraping on brick, close, dry room'."},"seconds":{"type":"number","minimum":1,"maximum":10,"default":3,"description":"How long the effect runs. Keep it tight; the backend's ceiling is 30s."},"offset":{"type":"number","description":"Seconds after the shot's first frame to trigger it. Defaults to 0, right on the cut."},"gain":{"type":"number","description":"Cue level in dB. 0 is unity, negative is quieter. Defaults to -4, an accent over the bed."},"prompt_influence":{"type":"number","minimum":0,"maximum":1,"description":"How literally the model follows the words. Higher is obedient, lower is inventive."},"place":{"type":"boolean","default":true,"description":"False generates the take but leaves the cut alone — audition first, place later with place_cue."},"backend":{"type":"string","description":"Force an SFX backend id instead of the project's lane default."},"confirm_cost":{"type":"boolean","description":"Set true to approve a paid SFX backend. Required whenever the SFX lane bills money."}},"required":["shot","prompt"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"place_cue","kind":"act","impl":"imperative","description":"Lay an existing audio file on the film's music or SFX track. Give it a take path and either a shot (the cue rides that shot's start and moves with it) or a start time in film seconds. Opens the Film Editor's cue strip so the placement is visible. Gain is decibels — 0 unity, -8 a bed. Use it to re-place a take you generated with place false, or to move a piece of music you already have. Returns the cue with its id.","title":"Place an audio cue on the film","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"kind":{"type":"string","enum":["music","sfx"],"description":"Which track the cue rides. Inferred from the path (audio/music/… or audio/sfx/…) when omitted."},"take":{"type":"string","description":"The audio file, project-relative — e.g. audio/music/theme.mp3. A generate_music or generate_sfx take path."},"path":{"type":"string","description":"Alias for take. The project-relative audio file to place."},"shot":{"type":"string","description":"Anchor the cue to this shot's start: a sid, its number in the cut, a beat, or a description."},"start":{"type":"number","description":"Anchor the cue this many seconds into the film instead. Ignored when shot is given."},"offset":{"type":"number","description":"Seconds added to whichever anchor won. Use it to sit a hit just after the cut."},"duration":{"type":"number","description":"Trim the cue to this many seconds. Required when loop is true."},"gain":{"type":"number","description":"Cue level in dB. 0 is unity, negative is quieter. Defaults to -8 for music, -4 for SFX."},"fade_in":{"type":"number","description":"Fade the cue up over this many seconds."},"fade_out":{"type":"number","description":"Fade the cue down over this many seconds at its end."},"loop":{"type":"boolean","description":"Repeat the file until duration is filled — for room tone and ambience beds."},"label":{"type":"string","description":"A short note shown on the cue strip, e.g. 'main theme' or 'door slam'."}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"list_cues","kind":"answer","impl":"imperative","description":"Read the film's cue sheet — every music and SFX cue with the time it fires, the shot it rides, its level in dB and its length. Use it before scoring to see what is already there, after placing to confirm, and to get the cue ids that remove one. A cue whose file is missing is flagged; a cue anchored outside the current scope shows no time.","title":"Read the cue sheet","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"kind":{"type":"string","enum":["music","sfx"],"description":"Only this track. Omit for both."},"scope":{"type":"string","description":"Resolve times against a single act (act1..act4) instead of the whole film."}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"add_cel_layer","kind":"act","impl":"imperative","description":"Animate one region of a shot as a cel layer over a background that stays put — the ink-first grammar: name only what moves (\"only the hand turns the key\"), and the rest of the frame never boils. Draws the region on the cel workbench, fills the motion prompt and submits. Creates the comp from the keeper plate (or `background`, which may be a clip) when the shot has none. Regions are background pixels, snapped to /32. Paid backends need confirm_cost.","title":"Add a cel layer","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"region":{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4,"description":"[left, top, right, bottom] on the background, in its own pixels — or fractions 0-1. Snapped to /32."},"prompt":{"type":"string","description":"Motion prompt for this cel. Name ONLY what moves; the rest of the frame is the background's job."},"frames":{"type":"integer","description":"Cel length in frames at 24fps. Default 49 (about two seconds)."},"comp":{"type":"string","description":"Which comp to add to. Default: the shot's newest, or a new one staged on the keeper."},"background":{"type":"string","description":"Only when creating the comp: \"keeper\", \"newest motion\", \"plays\", or a take path. A clip gives a moving background."},"confirm_cost":{"type":"boolean","description":"True approves a paid motion backend. Required when the motion lane costs money."}},"required":["shot","region","prompt"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"reroll_layer","kind":"act","impl":"imperative","description":"Generate another take of one cel layer, leaving the background and every other layer untouched — the comparison take. Same prompt and a fresh seed by default; pass prompt, seed, backend or model to direct it. Every take a layer has ever had stays in its variants strip, so nothing is overwritten. Opens the workbench, selects the layer and presses reroll. Paid backends need confirm_cost. If a cel ignores its plate, switch model and rerun.","title":"Reroll a cel layer","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"layer":{"type":"string","description":"Which layer: its id (L1, L2…), \"newest\" for the last one added, or \"selected\"."},"prompt":{"type":"string","description":"A new motion prompt for this cel. Default: keep the layer's own prompt."},"seed":{"type":"integer","description":"Fix the seed to reproduce a take. Default: a fresh random seed."},"backend":{"type":"string","description":"Motion backend id, e.g. \"mock\" or \"fal\". Default: the project's motion lane."},"model":{"type":"string","description":"Model id on that backend. Default: the backend's own default."},"comp":{"type":"string","description":"Which comp the layer belongs to. Default: the shot's newest comp."},"confirm_cost":{"type":"boolean","description":"True approves a paid motion backend. Required when the motion lane costs money."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"restyle_background","kind":"act","impl":"imperative","description":"Change the comp's background plate while every cel layer stays exactly where it is. mode \"edit\" keeps this plate and follows guidance (strength 0.55 holds the staged geometry, 0.85+ redesigns); mode \"regen\" paints a brand-new plate from a full image prompt. Every previous plate stays toggleable in the comp's background history. Still plates only — a clip background is footage, so animate a new clip and set_background instead.","title":"Restyle the plate","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"prompt":{"type":"string","description":"Edit guidance (\"warmer, dusk light\") for mode edit, or the full image prompt for mode regen."},"mode":{"type":"string","enum":["edit","regen"],"description":"\"edit\" keeps this plate and guides it; \"regen\" paints a new one. Default edit."},"strength":{"type":"number","minimum":0.35,"maximum":0.95,"description":"Edit mode only: how much may change. 0.55 keeps the staging, 0.85+ redesigns. Default 0.55."},"comp":{"type":"string","description":"Which comp to restyle. Default: the shot's newest comp."},"confirm_cost":{"type":"boolean","description":"True approves a paid image backend. Required when the still or i2i lane costs money."}},"required":["shot","prompt"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"set_background","kind":"act","impl":"imperative","description":"Point a comp at a different background — any take, still or clip. A still is the classic cel plate that never shimmers; a clip gives a MOVING background under the cel layers, which is how a comp holds camera motion without the figures boiling. Every layer keeps its region and its takes, the old background stays toggleable in the history, and the composite re-renders. Accepts a path or \"newest motion\", \"keeper\", \"plays\".","title":"Set the comp background","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"take":{"type":"string","description":"The new background: a take path, or \"keeper\", \"newest still\", \"newest motion\", \"plays\"."},"comp":{"type":"string","description":"Which comp to repoint. Default: the shot's newest comp."}},"required":["shot","take"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"set_layer","kind":"act","impl":"imperative","description":"Adjust one cel layer in place: opacity, stacking order (\"front\", \"back\" or an explicit z), matte mode (\"window\" is a feathered rectangle, \"figure\" cuts a per-frame anime matte so only the figure lands on the plate) and its region. Everything you pass is written in ONE edit, so the composite re-renders once rather than once per field. The cel itself is not regenerated — use reroll_layer for that.","title":"Adjust a cel layer","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"layer":{"type":"string","description":"Which layer: its id (L1, L2…), \"newest\" for the last one added, or \"selected\"."},"opacity":{"type":"number","minimum":0.1,"maximum":1,"description":"How strongly the cel reads over the background. 1 is solid, 0.5 is a ghost."},"z":{"type":"string","description":"Stacking: \"front\", \"back\", or a number. Higher z draws over lower z."},"matte":{"type":"string","enum":["window","figure"],"description":"\"window\" = feathered rectangle; \"figure\" = per-frame anime matte, only the figure lands."},"region":{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4,"description":"Move or resize the cel. [left, top, right, bottom] on the background, in its own pixels — or fractions 0-1. Snapped to /32."},"comp":{"type":"string","description":"Which comp the layer belongs to. Default: the shot's newest comp."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"remove_layer","kind":"act","impl":"imperative","description":"Take one cel layer out of a comp. The background and the other layers are untouched, and the composite re-renders without it. The layer's generated clips stay on disk as takes, so this is a composition decision, not a delete — restage it with add_cel_layer if you change your mind. Defaults to the newest layer when none is named.","title":"Remove a cel layer","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"layer":{"type":"string","description":"Which layer: its id (L1, L2…), \"newest\" for the last one added, or \"selected\"."},"comp":{"type":"string","description":"Which comp the layer belongs to. Default: the shot's newest comp."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"render_comp","kind":"act","impl":"imperative","description":"Render the comp into one clip: the background (a still plate, or a clip playing under everything) with every cel layer merged through its matte, at the comp's duration. Runs on the CPU pool and costs nothing. Pass promote:true to also make the finished composite what this shot plays in the cut, which is the usual last step of a cel build. Returns the job and, when it lands quickly, the rendered take.","title":"Render the composite","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"comp":{"type":"string","description":"Which comp to render. Default: the shot's newest comp."},"promote":{"type":"boolean","description":"True also sets the finished composite as the shot's timeline source (the ⬆ button)."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"list_layers","kind":"answer","impl":"imperative","description":"Read a shot's compositions without changing anything: each comp's background (and whether it is a still plate or a moving clip), its duration, how many alternative plates are stored, and every cel layer with its region, prompt, z order, opacity, matte mode and how many takes it has. Call it before reroll_layer or set_layer so you name a layer that exists, or to answer \"what is in this comp?\".","title":"List a shot's cel layers","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"comp":{"type":"string","description":"Only this comp. Default: every comp on the shot."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"list_backends","kind":"answer","impl":"imperative","description":"Report every generation backend this server knows: its id and adapter type, which lanes it can serve (still, i2i, motion, vo, music, sfx, direction), whether it is enabled, whether a key is stored, and whether it costs money per job. Nothing is probed, so it is instant and never bills. Call it before naming a backend in generate_takes or set_lane_default, or to answer \"what can this machine actually run?\". Also lists the motion and image models with their price and what each is good at.","title":"List generation backends","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"set_lane_default","kind":"act","impl":"imperative","description":"Point one generation lane at a backend (and optionally a model) for this project, so every later generate that leaves the console blank runs there — the \"(project default)\" the model picker shows. Lanes are still, i2i, motion, vo, music, sfx and direction. Opens the Settings lane table and changes the row on screen. Hosted demos allow this to the admin only; the server's refusal is relayed verbatim.","title":"Set a lane's default backend","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"lane":{"type":"string","enum":["still","i2i","motion","vo","music","sfx","direction"],"description":"Which lane: still, i2i, motion, vo, music, sfx or direction."},"backend":{"type":"string","description":"The backend id to make default, e.g. \"mock\", \"fal\", \"elevenlabs\". Use list_backends to see them."},"model":{"type":"string","description":"Model (or voice) id on that backend. Omit to leave the backend's own default."}},"required":["lane","backend"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"export_timeline","kind":"act","impl":"imperative","description":"Hand the cut to another program. \"otio\" is OpenTimelineIO JSON, which opens natively in Resolve, Nuke Studio and Kdenlive and carries each clip's Genga Studio lineage in its metadata; \"edl\" is a CMX3600 edit decision list, the universal conform format. Nothing is rendered and nothing changes — this compiles the current film and returns a download URL plus the first lines, so you can check the cut before opening it downstream.","title":"Export the timeline","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"format":{"type":"string","enum":["otio","edl"],"description":"\"otio\" for OpenTimelineIO JSON (default), \"edl\" for a CMX3600 edit decision list."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"render_timeline","kind":"act","impl":"imperative","description":"Render the compiled timeline through the lifted FreeCut engine — the clip model with real source in/out points, not the shot-slot assembler that cut_film uses. Optionally scope it to the first N seconds so a check is quick. Returns the job. The engine is an optional dependency: when it is not configured — and on the hosted studio it never is — this answers \"engine offline\" cleanly rather than failing, and cut_film remains the way to see the film.","title":"Render through the engine","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"scope_sec":{"type":"number","minimum":1,"description":"Render only the first N seconds. Omit for the whole film."},"container":{"type":"string","enum":["mp4","webm"],"description":"Output container. Default mp4."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"create_project","kind":"act","impl":"imperative","description":"Start a new, empty film in Genga Studio and open its Film Editor. Give it a title; the id is a slug derived from that unless you pass one. The new project inherits this instance's lane defaults and a style register — the house anime look, applied to every still, so shot prompts never carry style words. Hosted demos cap how many films one visitor may start per day. Follow it with write_script to fill the film with shots.","title":"Start a new film","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"title":{"type":"string","description":"What the film is called, e.g. \"The Bread Riot\". Shown on the project card."},"id":{"type":"string","description":"URL slug for the project. Lowercase letters, digits and dashes. Derived from the title when omitted."},"fps":{"type":"number","minimum":1,"maximum":60,"description":"Frames per second for the cut. Default 24; leave it alone unless the director asks."},"style":{"type":"string","description":"The film's look: anime-cel (default), anime-noir, anime-pastel, or a custom prefix sentence. Change it later with set_style."}},"required":["title"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"write_script","kind":"act","impl":"imperative","description":"Write a film's whole shot list in one call — the list IS the cut, in order. Each image_prompt describes setting, subject, framing and light. Do not add style words (hand-painted, caricature, cartoon, watercolour) and never ask for text in frame; the project's style register is applied to every still automatically. Narration under 25 words, dialogue under 12. Up to 40 shots, 2-20 seconds each, 300 seconds total. Use replace to throw out the old script.","title":"Write the script","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shots":{"type":"array","minItems":1,"maxItems":40,"items":{"type":"object","properties":{"sid":{"type":"string","description":"Shot id like B01-S3 (beat, then shot within it). Omit and they are numbered for you."},"act":{"type":"integer","minimum":1,"description":"Which act this shot belongs to, 1-4. Shots with no beat get one beat per act."},"beat":{"type":"string","description":"Beat id like B02 — a scene inside an act. Optional; the act supplies one."},"type":{"type":"string","enum":["STILL","HERO"],"description":"STILL for a plain shot, HERO for the one the eye lands on. Default STILL."},"seconds":{"type":"number","minimum":2,"maximum":20,"description":"How long the shot holds, 2 to 20 seconds. Default 6. The whole film must stay under 300."},"register":{"type":"string","description":"The colour and light register of this run of shots, e.g. \"R2 (warm lamplight, the bakery)\"."},"image_prompt":{"type":"string","description":"Setting, then \"Subject: …\", then framing and light. No style words: the project's style register supplies the look."},"negative":{"type":"string","description":"Extra bans for this shot only. The project's style register already bans text, lettering and photorealism everywhere."},"motion_prompt":{"type":"string","description":"The one thing that moves, if anything: \"only the wig trembles\". Leave it out for a held still."},"narration":{"type":"string","description":"Narration over the shot. Twenty-five words at most — it has to fit the hold."},"dialogue":{"type":"array","description":"Lines spoken in the shot, in order. Twelve words each at most.","items":{"type":"object","properties":{"character":{"type":"string","description":"Who speaks, e.g. \"MARGOT\"."},"line":{"type":"string","description":"What they say. Twelve words at most."}}}},"sfx":{"type":"string","description":"One sound effect, in words: \"a distant crowd, one cart wheel\"."},"ambient":{"type":"string","description":"The bed under the shot: \"street noise, rain on stone\"."},"cut":{"type":"string","description":"How this shot leaves: \"hard\", \"freeze then cut\"."},"render_notes":{"type":"string","description":"A rule for whoever renders it: \"no visible faces anywhere in the film\"."}},"required":["image_prompt"]},"description":"The shots, in the order they play. Each needs an image_prompt; everything else has a sensible default."},"project":{"type":"string","description":"Project id to write into. Defaults to the film that is open."},"replace":{"type":"boolean","description":"True deletes every shot this script does not name — a rewrite, not an edit. Default false."}},"required":["shots"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"set_project_cast","kind":"act","impl":"imperative","description":"Register who is in the film so shots can be found by character later: \"the Margot close-up\" resolves because the cast index knows Margot is the baker. Each entry is a name plus a short descriptor of the role, and aliases are derived from both. Write it right after write_script, using the same names the prompts use. Replaces the whole cast each time, so send everyone at once.","title":"Name the cast","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"characters":{"type":"array","minItems":1,"maxItems":24,"description":"Everyone in the film. Send them all: this replaces the cast rather than adding to it.","items":{"type":"object","properties":{"name":{"type":"string","description":"The character's name as the prompts write it, e.g. \"Margot\"."},"descriptor":{"type":"string","description":"The role in a few words: \"the baker who starts it\". Becomes searchable aliases."},"id":{"type":"string","description":"Stable id. Derived from the name when omitted."},"aliases":{"type":"array","items":{"type":"string"},"description":"Extra ways the director might say this character: \"the baker\", \"her\"."}},"required":["name","descriptor"]}},"project":{"type":"string","description":"Project id. Defaults to the film that is open."}},"required":["characters"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"list_projects","kind":"answer","impl":"imperative","description":"List every film on this server: its id, its title, how many shots it holds and whether it is paused. Use it to find out whether the film the director means already exists before starting another one, and to get the project id the other tools take. Reads only; nothing is opened and nothing changes.","title":"List the films","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"play_cut","kind":"act","impl":"imperative","description":"Play an assembled cut full screen in the screening room, from anywhere in it. Picks the cut (newest by default, or a file name or an index from newest), opens the Film Editor, opens the room over it and starts playing. `from` takes seconds, \"1:05\", a shot sid, \"act2\", \"start\"/\"end\", or a description like \"the lighthouses\". The room shows the cut's shot list as a chapter strip. Returns the shot now on screen. Use stop_playback to close it.","title":"Watch the film","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"project":{"type":"string","description":"Project id. Defaults to the film that is open."},"cut":{"type":"string","description":"Which cut: \"latest\" (default), a file name, or an index from newest where 1 is newest."},"from":{"type":"string","description":"Where to start: seconds (65), \"1:05\", a shot sid (\"B03-S2\"), \"act2\", \"start\", \"end\", or a description of the shot."},"to":{"type":"number","description":"Stop and hold at this many seconds. Leave it out to play to the end."},"muted":{"type":"boolean","description":"Start muted. Browsers allow a muted clip to autoplay when a normal one is refused."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"play_take","kind":"act","impl":"imperative","description":"Put a single take on the big screen: full-viewport playback of one shot's clip, or a still held for the shot's duration with a progress bar. `take` accepts a path or the usual words: \"latest\", \"newest motion\", \"newest still\", \"keeper\", \"plays\" (what is in the cut). Use it when the director wants to look hard at one shot rather than the whole film. stop_playback closes it.","title":"Watch one take","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"take":{"type":"string","description":"Which take: a path, or \"latest\", \"newest motion\", \"newest still\", \"keeper\", \"plays\". Defaults to what plays."},"from":{"type":"string","description":"Start this many seconds in, or \"0:02\". Defaults to the head of the take."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"stop_playback","kind":"act","impl":"imperative","description":"Stop whatever is playing and close the full-screen screening room, putting the director back on the page underneath with nothing lost. Also clears the ?screen and ?t deep-link parameters. Safe to call when nothing is playing.","title":"Close the screening room","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"preview_timeline","kind":"act","impl":"imperative","description":"Play the Timeline's live preview: the film compiled straight from the clip model, with no render step, so it reflects edits the instant they are made. Seeks to `from` (seconds, \"1:05\", a shot sid, \"act2\", or a description) and presses play. Picture and sound both: the VO, music and SFX clips play with it. A browser that has seen no click yet may hold the sound back — the page says so under the monitor, and ▶ there releases it.","title":"Preview the timeline","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"project":{"type":"string","description":"Project id. Defaults to the film that is open."},"from":{"type":"string","description":"Where to start: seconds (65), \"1:05\", a shot sid (\"B03-S2\"), \"act2\", \"start\", \"end\", or a description of the shot."},"play":{"type":"boolean","description":"Start playing (default true). False seeks and holds on the frame."},"scope_sec":{"type":"number","description":"Set the render-scope dropdown to this many seconds, for a following render_timeline."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"plan_motion","kind":"act","impl":"imperative","description":"Plan how to spend a dollar budget on animating this film. Ranks every shot by how much movement would buy it — HERO shots, shots with a motion prompt, the longest holds, later acts as climaxes, shots that already have a clip pushed down — then fits the budget, picking a model per shot from the registry of cost and use cases. Reads only. Faithfulness problems are usually the model, not the prompt: switch to the fallback and rerun.","title":"Plan a motion budget","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"project":{"type":"string","description":"Project id. Defaults to the project on screen."},"budget_usd":{"type":"number","description":"Dollars to spend on motion, e.g. 4. The plan stops when the next clip would pass it."},"seconds_per_clip":{"type":"number","description":"Clip length in seconds. Defaults to the backend's own default and is clamped to what it supports."},"prefer":{"type":"array","items":{"type":"string","enum":["hero","motion_prompt","longest","climax"]},"description":"Criteria to weight double: hero, motion_prompt, longest, climax."},"max_shots":{"type":"integer","description":"Cap the plan at this many shots even if the budget allows more."},"backend":{"type":"string","description":"Price the plan against a specific backend id instead of the project's motion default."}},"required":["budget_usd"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"apply_motion_plan","kind":"act","impl":"imperative","description":"Spend a motion budget: animate each shot of a plan_motion plan in order, on screen, one clip per shot, stopping the moment the next clip would pass the budget. Pass the plan back verbatim, or the same arguments to re-plan and run in one turn. Paid backends need confirm_cost. Returns the jobs and takes per shot with the running total; clips play in full at the backend's clip length.","title":"Run a motion plan","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"project":{"type":"string","description":"Project id. Defaults to the project on screen."},"plan":{"type":"array","description":"The items from plan_motion, in order. Omit to re-plan from budget_usd.","items":{"type":"object","properties":{"shot":{"type":"string","description":"The shot sid."},"source":{"type":"string","description":"Which still to animate: a take path, or \"selected\". Defaults to the shot's keeper."},"seconds":{"type":"number","description":"Clip length in seconds."},"est_usd":{"type":"number","description":"Estimated dollars for this clip."},"why":{"type":"string","description":"Why this shot earned a clip."}},"required":["shot"]}},"budget_usd":{"type":"number","description":"Dollars to spend. Required when no plan is passed; also the hard stop while running."},"seconds_per_clip":{"type":"number","description":"Clip length in seconds. Defaults to the backend's own default."},"prefer":{"type":"array","items":{"type":"string","enum":["hero","motion_prompt","longest","climax"]},"description":"Criteria to weight double: hero, motion_prompt, longest, climax."},"max_shots":{"type":"integer","description":"Cap the run at this many shots."},"backend":{"type":"string","description":"Force a backend id instead of the project's motion default."},"confirm_cost":{"type":"boolean","description":"Set true to approve a paid backend. Required whenever the motion lane bills money."}},"required":["budget_usd"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"set_style","kind":"act","impl":"imperative","description":"Set the style register — the look the server puts on every still and restyle in this film, so no shot prompt has to carry style words. Pick a named preset (anime-cel, anime-noir, anime-pastel) or write a custom prefix sentence of your own. `avoid` is the negative sent with every generation, and it also strips those words out of prompts that already carry them. Shots generated before the change keep the look they were made with; regenerate to bring them over.","title":"Set the film's look","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"preset":{"type":"string","enum":["anime-cel","anime-noir","anime-pastel"],"description":"A named house look: anime-cel (default), anime-noir for night, anime-pastel for daylight."},"prefix":{"type":"string","description":"Custom look, as one sentence put in front of every prompt: \"Cinematic anime film still, 1970s rotoscope …\"."},"avoid":{"type":"string","description":"Comma-separated negative applied to every still: \"text, lettering, photorealistic, western cartoon\"."},"refs":{"type":"array","items":{"type":"string"},"description":"Style-reference frames the model matches, as paths. Empty array turns reference conditioning off."},"project":{"type":"string","description":"Project id whose look this is. Defaults to the film that is open."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"attach_reference","kind":"act","impl":"imperative","description":"Attach a reference image to a shot so every still and restyle generated for it is sent that picture with the prompt. Say what it is for: character (match the face and costume), prop (match the object), setting (match the room), style (match line and palette only). The image can be a take path, words like \"keeper of B02-S2\", or an http(s) link, which is downloaded into the project. Four per shot. Shows in the Generate tab's References strip. Backends that take no image input skip them.","title":"Attach a reference image","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot the reference belongs to: a sid (B10-S2), its number in the cut, a beat, or a description."},"image":{"type":"string","description":"A take path, an http(s) image url, or words: \"keeper of B02-S2\", \"newest still of B04-S2\", \"plays\", \"latest\"."},"role":{"type":"string","enum":["character","prop","setting","style"],"description":"What to match: character (face, costume), prop (object), setting (place), style (line and palette only). Default character."},"note":{"type":"string","description":"Optional reminder of why this picture is attached, e.g. \"her coat is grey, not black\"."}},"required":["shot","image"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"remove_reference","kind":"act","impl":"imperative","description":"Take a reference image off a shot, so later generations stop being conditioned on it. Name the image (a path or file name), or a role (character, prop, setting, style) to drop every reference in that role, or pass image:\"all\" to clear them. The picture itself stays in the project's takes — only the attachment goes.","title":"Remove a reference","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."},"image":{"type":"string","description":"Which reference to drop: a path or file name, a role name, or \"all\" for every one on the shot."},"role":{"type":"string","enum":["character","prop","setting","style"],"description":"Drop every reference in this role instead of naming a file."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"list_references","kind":"answer","impl":"imperative","description":"Read the reference images attached to a shot and what each one is for, without changing anything. Use it before generating to see whether a face, a prop or a room is already pinned to a picture, and before attaching a fourth (four is the limit).","title":"List the shot's references","annotations":{"readOnlyHint":true,"untrustedContentHint":false,"consequentialHint":false},"inputSchema":{"type":"object","properties":{"shot":{"type":"string","description":"The shot: a sid (B10-S2), its number in the cut, a beat, or a description."}},"required":["shot"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]},{"name":"move_audio","kind":"act","impl":"imperative","description":"Slide one piece of audio along the film — a shot's voice-over, or a music or SFX cue — the way dragging it on the Timeline does. `at` puts it that many seconds into the film; `delta` slides it from where it sits (negative pulls it earlier). Use it to lift a cue off a line it is stepping on: the result says where it landed and what it still overlaps. A shot's lines share one offset, so they travel together.","title":"Move audio on the timeline","annotations":{"readOnlyHint":false,"untrustedContentHint":false,"consequentialHint":true},"inputSchema":{"type":"object","properties":{"target":{"type":"string","description":"What to move: a shot id for its VO, a cue id from list_cues, or part of the file name."},"at":{"type":"number","description":"Put it this many seconds into the film. Wins over delta."},"delta":{"type":"number","description":"Slide it this many seconds from where it is now; negative pulls it earlier."},"snap":{"type":"boolean","description":"Let it land on a cut or the playhead when it is close (default true)."},"project":{"type":"string","description":"Project id. Defaults to the film that is open."}},"required":["target"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app","pages":["/app","/","/app/jobs","/app/settings"]}],"category":"AI & Agents","favicon":"/favicons/gengastudio.com.png","apiSurface":"spec","toolCount":50}}