Skip to main content
Glama

Save layer template

save_layer_template

Create a reusable template from one clip's layers or custom layer timings, with optional intro/outro bumpers, to apply consistent styling across clips.

Instructions

Create a template from exactly one of clipId (that clip's layers: spanning = fill, touching the start = head, touching the end = tail, else anchored to the nearer edge; plus the intro and outro the clip renders with) or layers (each with a timing, see list_layer_templates; [] with bumpers = an intro / outro only template). Returns the template { id, name, layerCount, layers, bumpers }. Use apply_layer_template to put it on clips

Input Schema

NameRequiredDescriptionDefault
nameYesTemplate name (1-120 chars)
clipIdNoBuild the template from this clip's layers (get_project or search_clips). Pass clipId or layers, not both
layersNoOr the layers themselves, each with a timing: { kind: asset|text|audio, id, timing: { mode: head|tail|fill|relative, start, end, minSec, maxSec }, ...the layer's own fields (assetId, x, y, w, fade / text, size, color, fade / volume, duck, fade, loop) }
bumpersNoWith layers: the intro / outro the template puts on clips ({ intro, introSec, outro, outroSec }; a slot left out = clips keep their own, null = none, an id = that video or image). With clipId the clip's intro and outro are saved too

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv0.33.0
    • changedInput schema / properties / layers / description
      Previous value: -"Or the layers themselves, each with a timing: { kind: asset|text|audio, id, timing: { mode: head|tail|fill|relative, start, end, minSec, maxSec }, ...the layer's own fields (assetId, x, y, w / text, size, color / volume, duck, fade, loop) }"New value: +"Or the layers themselves, each with a timing: { kind: asset|text|audio, id, timing: { mode: head|tail|fill|relative, start, end, minSec, maxSec }, ...the layer's own fields (assetId, x, y, w, fade / text, size, color, fade / volume, duck, fade, loop) }"
    • changedInput schema / properties / layers / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "assetId": {
      -        "description": "Library asset id (search_assets with source library): an image, an animation or a video",
      -        "maxLength": 100,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "id": {
      -        "description": "Stable id for this overlay (any short string; keep it when editing)",
      -        "maxLength": 40,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "kind": {
      -        "const": "asset",
      -        "type": "string"
      -      },
      -      "loop": {
      -        "description": "Repeat a video / animation while its window is open (default: on for GIF and animated WebP, off for videos)",
      -        "type": "boolean"
      -      },
      -      "opacity": {
      -        "description": "0.1-1, default 1",
      -        "maximum": 1,
      -        "minimum": 0.1,
      -        "type": "number"
      -      },
      -      "timing": {
      -        "description": "Where the layer sits on a clip of any length",
      -        "oneOf": [
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Seconds after the clip starts (above start)",
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "head",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Seconds after the clip starts",
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Seconds before the clip ends (0 = the very end)",
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "tail",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Seconds before the clip ends (above end)",
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "mode": {
      -                "const": "fill",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "mode"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Fraction of the clip length (0-1, above start)",
      -                "maximum": 1,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "maxSec": {
      -                "description": "Never longer than this many seconds",
      -                "maximum": 600,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "minSec": {
      -                "description": "Never shorter than this many seconds",
      -                "maximum": 600,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "relative",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Fraction of the clip length (0-1)",
      -                "maximum": 1,
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          }
      -        ]
      -      },
      -      "w": {
      -        "description": "asset: width, fraction of the output width (0.05-1); the height follows the file. Default 0.3",
      -        "maximum": 1,
      -        "minimum": 0.05,
      -        "type": "number"
      -      },
      -      "x": {
      -        "description": "Centre, fraction of the output width (0-1)",
      -        "maximum": 1,
      -        "minimum": 0,
      -        "type": "number"
      -      },
      -      "y": {
      -        "description": "Centre, fraction of the output height (0-1)",
      -        "maximum": 1,
      -        "minimum": 0,
      -        "type": "number"
      -      }
      -    },
      -    "required": [
      -      "id",
      -      "assetId",
      -      "x",
      -      "y",
      -      "kind",
      -      "timing"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "box": {
      -        "description": "text: dark plate behind the text (default: outlined text, no plate)",
      -        "type": "boolean"
      -      },
      -      "color": {
      -        "description": "text: colour as #RRGGBB, default white",
      -        "pattern": "^#[0-9a-fA-F]{6}$",
      -        "type": "string"
      -      },
      -      "font": {
      -        "description": "text: font family from TEXT_FONTS (default DejaVu Sans, the caption font)",
      -        "maxLength": 60,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "id": {
      -        "description": "Stable id for this overlay (any short string; keep it when editing)",
      -        "maxLength": 40,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "kind": {
      -        "const": "text",
      -        "type": "string"
      -      },
      -      "opacity": {
      -        "description": "0.1-1, default 1",
      -        "maximum": 1,
      -        "minimum": 0.1,
      -        "type": "number"
      -      },
      -      "size": {
      -        "description": "text: font size as a fraction of the output height (0.02-0.12), default 0.045",
      -        "maximum": 0.12,
      -        "minimum": 0.02,
      -        "type": "number"
      -      },
      -      "text": {
      -        "description": "The line to show (1-120 chars)",
      -        "maxLength": 120,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "timing": {
      -        "description": "Where the layer sits on a clip of any length",
      -        "oneOf": [
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Seconds after the clip starts (above start)",
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "head",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Seconds after the clip starts",
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Seconds before the clip ends (0 = the very end)",
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "tail",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Seconds before the clip ends (above end)",
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "mode": {
      -                "const": "fill",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "mode"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Fraction of the clip length (0-1, above start)",
      -                "maximum": 1,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "maxSec": {
      -                "description": "Never longer than this many seconds",
      -                "maximum": 600,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "minSec": {
      -                "description": "Never shorter than this many seconds",
      -                "maximum": 600,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "relative",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Fraction of the clip length (0-1)",
      -                "maximum": 1,
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          }
      -        ]
      -      },
      -      "x": {
      -        "description": "Centre, fraction of the output width (0-1)",
      -        "maximum": 1,
      -        "minimum": 0,
      -        "type": "number"
      -      },
      -      "y": {
      -        "description": "Centre, fraction of the output height (0-1)",
      -        "maximum": 1,
      -        "minimum": 0,
      -        "type": "number"
      -      }
      -    },
      -    "required": [
      -      "id",
      -      "text",
      -      "x",
      -      "y",
      -      "kind",
      -      "timing"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "assetId": {
      -        "description": "Library audio asset id (search_assets with source library, kind audio); the same asset can be used more than once",
      -        "maxLength": 100,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "duck": {
      -        "description": "Lower the music while someone speaks (default true)",
      -        "type": "boolean"
      -      },
      -      "fade": {
      -        "description": "Fade in and out, seconds (default 0.5)",
      -        "maximum": 5,
      -        "minimum": 0,
      -        "type": "number"
      -      },
      -      "id": {
      -        "description": "Stable id for this track (any short string; keep it when editing)",
      -        "maxLength": 40,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "kind": {
      -        "const": "audio",
      -        "type": "string"
      -      },
      -      "loop": {
      -        "description": "Repeat the track when it is shorter than the window (default true)",
      -        "type": "boolean"
      -      },
      -      "offset": {
      -        "description": "Seconds into the track to start from (default 0)",
      -        "minimum": 0,
      -        "type": "number"
      -      },
      -      "timing": {
      -        "description": "Where the layer sits on a clip of any length",
      -        "oneOf": [
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Seconds after the clip starts (above start)",
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "head",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Seconds after the clip starts",
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Seconds before the clip ends (0 = the very end)",
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "tail",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Seconds before the clip ends (above end)",
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "mode": {
      -                "const": "fill",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "mode"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "properties": {
      -              "end": {
      -                "description": "Fraction of the clip length (0-1, above start)",
      -                "maximum": 1,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "maxSec": {
      -                "description": "Never longer than this many seconds",
      -                "maximum": 600,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "minSec": {
      -                "description": "Never shorter than this many seconds",
      -                "maximum": 600,
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "mode": {
      -                "const": "relative",
      -                "type": "string"
      -              },
      -              "start": {
      -                "description": "Fraction of the clip length (0-1)",
      -                "maximum": 1,
      -                "minimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "required": [
      -              "mode",
      -              "start",
      -              "end"
      -            ],
      -            "type": "object"
      -          }
      -        ]
      -      },
      -      "volume": {
      -        "description": "Music level 0-1 (default 0.6) on a track normalised to -20 LUFS, before ducking",
      -        "maximum": 1,
      -        "minimum": 0,
      -        "type": "number"
      -      }
      -    },
      -    "required": [
      -      "id",
      -      "assetId",
      -      "kind",
      -      "timing"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "assetId": {
      +        "description": "Library asset id (search_assets with source library): an image, an animation or a video",
      +        "maxLength": 100,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "fade": {
      +        "description": "Fade in when it appears and out when it goes, seconds (0-2, default 0 = appears and goes at once)",
      +        "maximum": 2,
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "id": {
      +        "description": "Stable id for this overlay (any short string; keep it when editing)",
      +        "maxLength": 40,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "kind": {
      +        "const": "asset",
      +        "type": "string"
      +      },
      +      "loop": {
      +        "description": "Repeat a video / animation while its window is open (default: on for GIF and animated WebP, off for videos)",
      +        "type": "boolean"
      +      },
      +      "opacity": {
      +        "description": "0.1-1, default 1",
      +        "maximum": 1,
      +        "minimum": 0.1,
      +        "type": "number"
      +      },
      +      "timing": {
      +        "description": "Where the layer sits on a clip of any length",
      +        "oneOf": [
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Seconds after the clip starts (above start)",
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "head",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Seconds after the clip starts",
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Seconds before the clip ends (0 = the very end)",
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "tail",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Seconds before the clip ends (above end)",
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "mode": {
      +                "const": "fill",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "mode"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Fraction of the clip length (0-1, above start)",
      +                "maximum": 1,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "maxSec": {
      +                "description": "Never longer than this many seconds",
      +                "maximum": 600,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "minSec": {
      +                "description": "Never shorter than this many seconds",
      +                "maximum": 600,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "relative",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Fraction of the clip length (0-1)",
      +                "maximum": 1,
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          }
      +        ]
      +      },
      +      "w": {
      +        "description": "asset: width, fraction of the output width (0.05-1); the height follows the file. Default 0.3",
      +        "maximum": 1,
      +        "minimum": 0.05,
      +        "type": "number"
      +      },
      +      "x": {
      +        "description": "Centre, fraction of the output width (0-1)",
      +        "maximum": 1,
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "y": {
      +        "description": "Centre, fraction of the output height (0-1)",
      +        "maximum": 1,
      +        "minimum": 0,
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "id",
      +      "assetId",
      +      "x",
      +      "y",
      +      "kind",
      +      "timing"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "box": {
      +        "description": "text: dark plate behind the text (default: outlined text, no plate)",
      +        "type": "boolean"
      +      },
      +      "color": {
      +        "description": "text: colour as #RRGGBB, default white",
      +        "pattern": "^#[0-9a-fA-F]{6}$",
      +        "type": "string"
      +      },
      +      "fade": {
      +        "description": "Fade in when it appears and out when it goes, seconds (0-2, default 0 = appears and goes at once)",
      +        "maximum": 2,
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "font": {
      +        "description": "text: font family from TEXT_FONTS (default DejaVu Sans, the caption font)",
      +        "maxLength": 60,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "Stable id for this overlay (any short string; keep it when editing)",
      +        "maxLength": 40,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "kind": {
      +        "const": "text",
      +        "type": "string"
      +      },
      +      "opacity": {
      +        "description": "0.1-1, default 1",
      +        "maximum": 1,
      +        "minimum": 0.1,
      +        "type": "number"
      +      },
      +      "size": {
      +        "description": "text: font size as a fraction of the output height (0.02-0.12), default 0.045",
      +        "maximum": 0.12,
      +        "minimum": 0.02,
      +        "type": "number"
      +      },
      +      "text": {
      +        "description": "The line to show (1-120 chars)",
      +        "maxLength": 120,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "timing": {
      +        "description": "Where the layer sits on a clip of any length",
      +        "oneOf": [
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Seconds after the clip starts (above start)",
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "head",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Seconds after the clip starts",
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Seconds before the clip ends (0 = the very end)",
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "tail",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Seconds before the clip ends (above end)",
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "mode": {
      +                "const": "fill",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "mode"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Fraction of the clip length (0-1, above start)",
      +                "maximum": 1,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "maxSec": {
      +                "description": "Never longer than this many seconds",
      +                "maximum": 600,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "minSec": {
      +                "description": "Never shorter than this many seconds",
      +                "maximum": 600,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "relative",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Fraction of the clip length (0-1)",
      +                "maximum": 1,
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          }
      +        ]
      +      },
      +      "x": {
      +        "description": "Centre, fraction of the output width (0-1)",
      +        "maximum": 1,
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "y": {
      +        "description": "Centre, fraction of the output height (0-1)",
      +        "maximum": 1,
      +        "minimum": 0,
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "id",
      +      "text",
      +      "x",
      +      "y",
      +      "kind",
      +      "timing"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "assetId": {
      +        "description": "Library audio asset id (search_assets with source library, kind audio); the same asset can be used more than once",
      +        "maxLength": 100,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "duck": {
      +        "description": "Lower the music while someone speaks (default true)",
      +        "type": "boolean"
      +      },
      +      "fade": {
      +        "description": "Fade in and out, seconds (default 0.5)",
      +        "maximum": 5,
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "id": {
      +        "description": "Stable id for this track (any short string; keep it when editing)",
      +        "maxLength": 40,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "kind": {
      +        "const": "audio",
      +        "type": "string"
      +      },
      +      "loop": {
      +        "description": "Repeat the track when it is shorter than the window (default true)",
      +        "type": "boolean"
      +      },
      +      "offset": {
      +        "description": "Seconds into the track to start from (default 0)",
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "timing": {
      +        "description": "Where the layer sits on a clip of any length",
      +        "oneOf": [
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Seconds after the clip starts (above start)",
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "head",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Seconds after the clip starts",
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Seconds before the clip ends (0 = the very end)",
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "tail",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Seconds before the clip ends (above end)",
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "mode": {
      +                "const": "fill",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "mode"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "properties": {
      +              "end": {
      +                "description": "Fraction of the clip length (0-1, above start)",
      +                "maximum": 1,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "maxSec": {
      +                "description": "Never longer than this many seconds",
      +                "maximum": 600,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "minSec": {
      +                "description": "Never shorter than this many seconds",
      +                "maximum": 600,
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "mode": {
      +                "const": "relative",
      +                "type": "string"
      +              },
      +              "start": {
      +                "description": "Fraction of the clip length (0-1)",
      +                "maximum": 1,
      +                "minimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "mode",
      +              "start",
      +              "end"
      +            ],
      +            "type": "object"
      +          }
      +        ]
      +      },
      +      "volume": {
      +        "description": "Music level 0-1 (default 0.6) on a track normalised to -20 LUFS, before ducking",
      +        "maximum": 1,
      +        "minimum": 0,
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "id",
      +      "assetId",
      +      "kind",
      +      "timing"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. Changed1 schema field changedv0.28.1
    • addedInput schema / properties / bumpers
      Added value: +{
      +  "description": "With layers: the intro / outro the template puts on clips ({ intro, introSec, outro, outroSec }; a slot left out = clips keep their own, null = none, an id = that video or image). With clipId the clip's intro and outro are saved too",
      +  "properties": {
      +    "intro": {
      +      "anyOf": [
      +        {
      +          "maxLength": 100,
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "Library video or image id (list_bumpers) for the intro; null = no intro; left out = clips keep their own"
      +    },
      +    "introSec": {
      +      "description": "Seconds an image intro/outro shows (1-10); videos keep their own length",
      +      "maximum": 10,
      +      "minimum": 1,
      +      "type": "number"
      +    },
      +    "outro": {
      +      "anyOf": [
      +        {
      +          "maxLength": 100,
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "Library video or image id (list_bumpers) for the outro; null = no outro; left out = clips keep their own"
      +    },
      +    "outroSec": {
      +      "description": "Seconds an image intro/outro shows (1-10); videos keep their own length",
      +      "maximum": 10,
      +      "minimum": 1,
      +      "type": "number"
      +    }
      +  },
      +  "type": "object"
      +}
  3. Addedv0.23.0

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the load and does reasonably well: it discloses the return shape { id, name, layerCount, layers, bumpers }, the mutual-exclusion rule, and the special empty-layers case. It omits permission requirements, the 30-layer cap, and whether saving a template has any side effects on existing clips.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core contract (create from one of two inputs) and then adds derivation detail compactly. The parenthetical timing explanation is dense but each clause carries information; nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter tool with a deeply nested layers union, the description covers both input modes, the exclusivity rule, the empty-layers edge case, the bumper slot semantics, and the return value even though no output schema exists. Only operational details like layer-count limits and permission/error behavior are absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3. The description earns above that by explaining derived behavior the schema can't express: a clip's spanning layers become fill, layers touching the start/end become head/tail, others anchor to the nearer edge, and the clip's intro/outro are carried over.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Create a template") and pins the source to "exactly one of clipId ... or layers", which an agent can act on without opening the schema. It also names apply_layer_template as the consumer, so it is distinguishable from the apply/update/delete siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear input-selection guidance: pass clipId or layers but not both, and an empty layers array with bumpers yields an intro/outro-only template. It also routes the agent to apply_layer_template afterwards. It stops short of saying when to prefer clipId over hand-built layers beyond the derivation hint.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.