Tools: graphics
These tools let an agent write a motion graphic, look at it without placing it, and put it on the timeline. Graphics with an agent tells that story from the top. This page is the reference for each tool.
- Needs
- A client connected over MCP, or the Assistant tab.
- Agent tools
graphic_referencewrite_graphicget_graphicrender_graphiclist_graphicsinsert_graphicadd_graphic_clipset_graphic
A graphic’s code is a module, the file graphics/<name>.js inside the project, and name in these tools is that file’s name without .js. Fonts, pictures, renames, deletes and packages are on Tools: graphic fonts, pictures and packages.
Every tool here also takes project, the path of an open project. Without it the call goes to the frontmost project. See How tool calls behave. Times are in ticks, 600,000 a second, and are rounded to the project’s frame grid. See Units and ids.
Write, place, change and check
Section titled “Write, place, change and check”A graphic made by an agent usually goes through these steps.
-
Read the API once with
graphic_reference. -
Write the module with
write_graphic. It returns the result of compiling that exact text. If it failed, fix the source and write it again. -
Look at it with
render_graphic, which draws frames with no clip on the timeline. -
Place it with
add_graphic_clip, giving the track, the time and any values it should draw with.insert_graphicplaces a graphic at the playhead instead, as the Insert Graphic sheet does. -
Change it with
set_graphic. To animate a property, add an action withadd_actionand say what the property ends at withset_action_end. See Animate graphic properties. -
Check a frame of the finished timeline with
render_frame.
graphic_reference
Section titled “graphic_reference”Returns the whole graphics API as Markdown, for a model to read once before it writes a graphic. It covers a module’s shape, ctx, the schema’s types, the standard library, fonts, the sandbox, the limits and worked examples.
It’s the same file as Help ▸ Graphics Reference. See The module API.
It takes no argument of its own, and it’s the one tool on this page that needs no project open. A project, when given, must still name an open one.
write_graphic
Section titled “write_graphic”Writes a module’s JavaScript into the project, compiles it and returns the result for that text. The folder graphics/ is made if it isn’t there yet. A person does the same by saving the file in an editor. See Edit a module.
| Argument | Type | Required | What it does |
|---|---|---|---|
name |
string | Yes | The module’s name: lowercase letters, digits and -, starting with a letter or a digit, at most 63 characters. |
source |
string | Yes | The whole module’s JavaScript. It exports render, and optionally meta and schema. |
It returns:
| Key | What it holds |
|---|---|
name, path, revision |
The module, its file, and the SHA-256 of its text. |
ok |
Whether the text compiled. |
meta, schema |
What the module declares. Both are empty when ok is false. |
diagnostics |
A list of {level, message, line, column, frame}. With ok false, they say where it went wrong. With ok true, they’re the module’s top-level warnings, such as asset() outside render naming a file the folder doesn’t hold. |
clips |
The ids of the clips drawn by this module. They redraw with the new text at once. |
kept |
The revisions of the module’s kept versions, newest first. |
note |
A reminder that the write can’t be undone and that the text it replaced is kept. |
A module that doesn’t compile isn’t an error. The call succeeds with ok false, and the file stays in the folder as written, so fix the source and write it again. The call itself fails for a name that isn’t a module name, or a file that can’t be written.
A write can’t be undone and doesn’t mark the project edited, but the text it replaced is kept, up to the last 10 for each module. restore_graphic brings one back.
get_graphic
Section titled “get_graphic”Reads one module, or the whole graphics folder. The module’s half is what the Source section of the Graphic sub-tab shows a person.
| Argument | Type | Required | What it does |
|---|---|---|---|
name |
string | No | The module to read. Leave it out to read the folder. |
With name, it returns name, source, path, revision, ok, meta, schema, diagnostics, clips and kept, with the same meanings as write_graphic. A name the folder doesn’t hold gives an error that lists what it does hold.
Without name, it returns:
| Key | What it holds |
|---|---|
folder |
The folder’s full path. It’s given even before the folder exists. |
folder_exists |
False until the first write makes the folder. |
modules |
Every module, as {name, revision, ok, clips}. |
families |
The font families the project’s graphics can draw with. |
assets |
The pictures in graphics/assets/. |
warnings |
What Frame Job skipped or couldn’t watch when it read the folder, in plain sentences. |
history |
{name, kept} for every name with kept versions, deleted modules included. |
A module saved a moment ago from outside can read ok false with one diagnostic saying the app hasn’t compiled it yet. Call again.
render_graphic
Section titled “render_graphic”Draws a module without a clip, to look at it before placing it. There’s no control for this in the app, because a person looks at the preview instead.
Render graphic options
Section titled “Render graphic options”| Argument | Type | Required | What it does |
|---|---|---|---|
name |
string | Yes | The module to draw. |
frames |
array of integers | No | The frames to draw, 1 to 16 of them, in the order given. Not with frame. |
frame |
integer | No | One frame to draw, 0 or more. Not with frames. With neither, frame 0 is drawn. |
props |
object | No | The values to draw with, keyed by the schema’s names. A key left out draws with the schema’s default. |
width |
integer | No | The width to draw at, 1 to 8192 pixels. Default: meta.width, else the canvas. |
height |
integer | No | The height to draw at, 1 to 8192 pixels. Default: meta.height, else the canvas. |
format |
string | No | png (the default) for a contact sheet, or svg for one frame’s text. |
max_width |
integer | No | The widest the sheet may be, 64 to 8192 pixels. The default is 2048. 8192 keeps a 1920-wide graphic’s two cells at full size. |
background |
string | No | What the sheet is painted on: transparent (the default), checker, or a hex colour as #rgb, #rrggbb or #rrggbbaa, in either case. |
path |
string | No | Where to write the sheet. It’s always a .png, and its folder must exist. Leave it out for a temporary file. |
max_width, background and path belong to the sheet, and svg won’t take them.
Each frame is drawn as a clip would draw it. The frame rate is the project’s, durationInFrames is the module’s meta value or else 5 seconds, and a frame at or past that length is still drawn, with progress at 1, as a longer clip draws it.
The contact sheet
Section titled “The contact sheet”The png format returns an image the model can see, a text block, and a file on disk. The frames sit on a near-square grid, top left first, and each frame’s number is printed in a dark strip under its cell. Sixteen frames make a 4 by 4 grid.
- Only the cells scale down to fit
max_width, never the 8-pixel gaps or the 24-pixel labels. Cells are never scaled up, and the sheet is never more than 8192 pixels tall. checkerpaints 16-pixel grey squares, which shows up a graphic’s transparent areas.- A frame that fails draws its error card in its cell. The sheet still comes back, and the text adds a sentence with the error and where it is. A frame that only warned adds a sentence too.
- The text says the frames, each cell’s size and scale, the grid, the sheet’s size and the background, and ends “Written to
<path>.”
A sheet draws at most 134,217,728 pixels of frames, counted as frames × width × height. That’s two frames at 8192 × 8192, or sixteen at 3840 × 2160. Past that the call fails before any frame is drawn, so ask for fewer frames or a smaller size.
One frame as SVG
Section titled “One frame as SVG”With format: "svg", it returns name, frame, ok, svg (the frame’s SVG text), diagnostics, and ctx, the values the frame was drawn with: fps, time, durationInFrames, progress, width, height and canvas.
It draws one frame and writes no file. A frame that fails isn’t an error here either: ok is false, svg is null and diagnostics say why.
When it won’t run
Section titled “When it won’t run”render_graphic won’t run when:
- The module isn’t in the folder, or doesn’t compile. The error lists what the folder holds, or gives the first compile error.
- Both
frameandframesare given, orframesdoesn’t hold 1 to 16 whole numbers of 0 or more. formatissvgwith more than one frame, or withpath,backgroundormax_width.max_width,width,heightorbackgroundis out of range, or the folder ofpathdoesn’t exist.- A
metavalue it would use isn’t a whole number in range. The error names the key.
list_graphics
Section titled “list_graphics”Lists the graphics Insert ▸ Graphic… offers, in the sheet’s order. See Insert a graphic.
It takes no argument of its own. It returns categories, a list of {name, graphics}, and each graphic is:
| Key | What it holds |
|---|---|
name |
What insert_graphic takes. |
title |
The module’s meta.name, else its name made into a title. Two This Project graphics with one title show as “title — name”. |
description |
The module’s meta.description, or null. |
category |
The module’s own category. |
from |
template or project, which is what insert_graphic takes as from. |
ok |
False for a module that doesn’t compile. It’s still listed. |
This Project comes first when the project’s graphics/ holds a module, and lists every module there, whatever its own category. The bundled templates follow by category, A to Z, each module’s meta.category or else Other, which is always last. Within a category, graphics sort by title.
insert_graphic
Section titled “insert_graphic”Places a graphic at the playhead, as the Insert button in Insert ▸ Graphic… does. See Insert a graphic.
| Argument | Type | Required | What it does |
|---|---|---|---|
name |
string | Yes | The graphic’s name as list_graphics gives it. |
from |
string | Yes | template for one of the bundled templates, project for a module already in the project’s graphics/. |
The clip goes on the front track when it fits there, otherwise on a new track above everything, at the module’s meta length and size, else 5 seconds and the canvas’s size. It’s one undo step, Insert Graphic. With a nest open, it lands inside the nest.
A template is first copied into graphics/ under a free name such as lower-third or lower-third-2. That copy can’t be undone, so undoing the insert takes the clip away and leaves the module. A project module is placed as it is, with no copy.
It returns what any edit returns, and name says which module the clip is drawn by.
It won’t place anything when:
nameisn’t a template or a module of the project. The error lists what there is.- The module doesn’t compile. The error gives the first problem, and a template’s copy stays in
graphics/. - A
metavalue it would use isn’t a whole number in range. - The canvas is wider or taller than 8192 pixels and the module gives no size.
add_graphic_clip
Section titled “add_graphic_clip”Places a clip drawn by a module already in graphics/, on a track and at a time you choose. Use it when you need more say than insert_graphic gives. Insert ▸ Graphic… is a template’s write followed by this. See Place a clip.
| Argument | Type | Required | What it does |
|---|---|---|---|
track |
integer | Yes | The track’s id. get_project lists them. |
at |
integer | Yes | The start, in ticks. |
name |
string | Yes | The module. |
duration |
integer | No | The length, in ticks, at least one frame. Default: the module’s meta.durationInFrames at the project’s frame rate, else 5 seconds. |
width |
integer | No | The width the module draws at, 1 to 8192 pixels. Default: meta.width, else the canvas. |
height |
integer | No | The height the module draws at, 1 to 8192 pixels. Default: meta.height, else the canvas. |
props |
object | No | The values to draw with, keyed by the schema’s names, at most 64. A key left out draws with the schema’s default. |
scope |
integer | No | A nest’s id, to add the clip inside that nest. See Editing inside a nest. |
Like a shape, the clip has no source of its own. Use set_graphic to change what it’s drawn from, and set_video to place it in the picture.
Each key of props is checked against the module’s schema as the file reads now. A key the schema lacks, a wrong type or a value out of range gives an error naming its dotted path. A colour is stored as lowercase hex, and a null is dropped.
It returns what any edit returns, with the new clip in new_clips, and it’s one undo step, Add Graphic.
It won’t place the clip when:
- The module isn’t in the folder, or doesn’t compile. The error lists what the folder holds, or gives the first compile error.
- A
metavalue it would use isn’t a whole number in range. - The canvas is wider or taller than 8192 pixels and no size was given.
- The clip would overlap another one on the track, as for any clip.
set_graphic
Section titled “set_graphic”Changes what graphic clips are drawn from: the module, the size, the graphic’s own length and its properties. It’s the same as editing Properties, Size and Timeline in the Graphic sub-tab. See Graphic properties and Graphic size and timing.
| Argument | Type | Required | What it does |
|---|---|---|---|
clips |
array of integers | Yes | The clip ids, at least one. |
patch |
object | Yes | The keys to change, below. |
scope |
integer | No | A nest’s id, to edit inside that nest. |
| Patch key | What it does |
|---|---|
name |
Draws the clips from another module, which must be in the folder and compile. |
width, height |
The size the module draws at, 1 to 8192 pixels. |
length |
The graphic’s own timeline, in ticks. It snaps to a frame and is at least one frame. Null ends it with the clip, which is Follow Clip. |
props |
The base values, merged key by key, at most 64 on a clip. A null removes its key. |
A null for a property that an action on the clip animates doesn’t remove it. It sets the schema’s default, so the animation keeps its start. To animate a property, use add_action and then set_action_end.
A patch with props or name is checked against a schema: the one of the module the patch names, otherwise the one module every clip is drawn by.
It returns what any edit returns, and it’s one undo step, Graphic Properties. A patch that changes nothing makes no undo step, and that includes a colour re-sent in another spelling.
It won’t run when:
- One of the clips isn’t a graphic. Nothing changes on the others either.
propsis sent with nonameto clips drawn by two different modules. Set them one module at a time.- The patch has
in, which moves with trims, rolls and splits, or any other key it doesn’t know. - A value fails its check. The error names it, and a property by its dotted path.
Editing the folder with your own file tools
Section titled “Editing the folder with your own file tools”An agent can also edit the graphics folder directly, and Frame Job sees a change within a moment. Ask get_graphic with no name for the folder’s path.
| What | Where |
|---|---|
| Modules | <name>.js |
| Fonts | fonts/, as .ttf or .otf |
| Pictures | assets/ |
history/, API.md and API.d.ts are Frame Job’s own, so leave them alone. history/ holds the kept versions that restore_graphic reads, and API.md and API.d.ts are the reference and its types.
A module’s text is kept when Frame Job sees it replaced while the project is open, and that includes a save from an outside editor. See Edit a module for how changes are picked up.