Skip to main content
Glama

Check rows before creating a batch

validate_batch
Read-onlyIdempotent

Checks batch rows on what the batch renders (pages, every page of templates, or a flow's video) and reports every problem by row index and field, without saving anything or spending credits. It runs the same checks as create_batch, so rows that pass here are accepted there, while create_batch saves nothing if any row fails. Each row comes back as the server read it on each page (layer keys, text, and each image resolved to its asset id and file name), so a misread value shows before any credits are spent, with the jobs the batch would make and their creditCost. A layer name two layers share is refused with their ids: fill each by id and tell the user, who can rename one. It does not measure text, so copy longer than the template's sample can still overflow its box. Needs templates:read.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "rows": "<rows>"
    },
    "name": "validate_batch"
  }
}

Input Schema

NameRequiredDescriptionDefault
flowNoInstead of pages: one flow (get_template_inputs flows), a video joining some of its template's pages, that every row renders as, with a video output format. A name fills that layer on every page of the video; `<pageId>@<layer>` one page, `<pageId>#2@<layer>` a page's second visit.
rowsYes1 to 1,000 rows, each its own modifications and output, rendered on every page named (or as the flow's video)
pagesNoPage ids (get_template_inputs pages, from any templates) every row renders on, in order: one id for one file per row, several for one file per row per page, such as a carousel's slides. A row's plain keys fill every page that has the layer; `<pageId>@<layer>` fills one page.
templatesNoInstead of pages: template ids whose every page each row renders on, in page order

Output Schema

NameRequiredDescriptionDefault
rowsYesEach row as the server read it on each page
validYesTrue when every row passes
issuesYesEvery problem found; empty when valid
jobCountYesJobs the batch makes: one per row per page
rowCountYes
warningsNoNot errors: pass these on to the user, such as a flow longer than a video renders
validRowsYes
creditCostYesCredits those jobs spend when they render
invalidRowsYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed29 schema fields changed
    • removedInput schema / properties / columns
      Removed value: -{
      -  "description": "For array rows: the layer key of each cell, in order, like a spreadsheet header",
      -  "items": {
      -    "minLength": 1,
      -    "type": "string"
      -  },
      -  "maxItems": 100,
      -  "minItems": 1,
      -  "type": "array"
      -}
    • removedInput schema / properties / defaults
      Removed value: -{
      -  "additionalProperties": {
      -    "anyOf": [
      -      {
      -        "description": "A text layer's text, with <s1>...</s1> tags for runs when it has several styles; or an image layer's asset id or file name",
      -        "type": "string"
      -      },
      -      {
      -        "additionalProperties": {},
      -        "description": "A text layer's text and visibility",
      -        "properties": {
      -          "text": {
      -            "description": "The layer's new text, tagged like a string value",
      -            "type": "string"
      -          },
      -          "visible": {
      -            "description": "false hides the layer; layout closes the gap",
      -            "type": "boolean"
      -          }
      -        },
      -        "type": "object"
      -      },
      -      {
      -        "additionalProperties": {},
      -        "description": "An image layer's image and framing",
      -        "properties": {
      -          "asset": {
      -            "description": "An asset id (search_assets, upload_images), the image's file name, or a designer image key. Omit to keep the template's image and only re-frame it.",
      -            "type": "string"
      -          },
      -          "fit": {
      -            "description": "cover fills the slot and crops (default), contain shows the whole image, stretch distorts to the slot. The designer's names work too: fill is cover, fit is contain",
      -            "enum": [
      -              "cover",
      -              "contain",
      -              "stretch",
      -              "fill",
      -              "fit"
      -            ],
      -            "type": "string"
      -          },
      -          "panX": {
      -            "description": "Moves the image by this fraction of the slot width; positive = right",
      -            "maximum": 1,
      -            "minimum": -1,
      -            "type": "number"
      -          },
      -          "panY": {
      -            "description": "Moves the image by this fraction of the slot height; positive = down",
      -            "maximum": 1,
      -            "minimum": -1,
      -            "type": "number"
      -          },
      -          "visible": {
      -            "description": "false hides the layer",
      -            "type": "boolean"
      -          },
      -          "zoom": {
      -            "description": "Zoom about the slot centre; 1 = none",
      -            "maximum": 4,
      -            "minimum": 0.2,
      -            "type": "number"
      -          }
      -        },
      -        "type": "object"
      -      }
      -    ]
      -  },
      -  "description": "Values every row gets unless it gives its own, such as a logo or call to action shared by all rows",
      -  "propertyNames": {
      -    "type": "string"
      -  },
      -  "type": "object"
      -}
    • addedInput schema / properties / flow
      Added value: +{
      +  "description": "Instead of pages: one flow (get_template_inputs flows), a video joining some of its template's pages, that every row renders as, with a video output format. A name fills that layer on every page of the video; `<pageId>@<layer>` one page, `<pageId>#2@<layer>` a page's second visit.",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • removedInput schema / properties / flowIds
      Removed value: -{
      -  "description": "Instead of pageIds: this template's flows (get_template_inputs flows), each a video joining some of its pages, that every row renders as, one video per row per flow, with a video outputFormat. A name fills every layer with it across a video's pages.",
      -  "items": {
      -    "format": "uuid",
      -    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
      -    "type": "string"
      -  },
      -  "maxItems": 20,
      -  "minItems": 1,
      -  "type": "array"
      -}
    • removedInput schema / properties / pageIds
      Removed value: -{
      -  "description": "This template's pages (get_template_inputs pages) every row renders on, in order: one id for one file per row, several for one file per row per page, such as a carousel's slides. The first page when omitted. A row may carry keys of any of these pages; each page takes the keys it has.",
      -  "items": {
      -    "format": "uuid",
      -    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
      -    "type": "string"
      -  },
      -  "maxItems": 20,
      -  "minItems": 1,
      -  "type": "array"
      -}
    • addedInput schema / properties / pages
      Added value: +{
      +  "description": "Page ids (get_template_inputs pages, from any templates) every row renders on, in order: one id for one file per row, several for one file per row per page, such as a carousel's slides. A row's plain keys fill every page that has the layer; `<pageId>@<layer>` fills one page.",
      +  "items": {
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "maxItems": 20,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • changedInput schema / properties / rows / description
      Previous value: -"1 to 500 rows. Each keys a layer by its name (case aside) or id, the key get_template_inputs gives, to a plain value: text as a string, an image as an asset id or file name, or { asset, fit, zoom, panX, panY } and { text, visible } when framing or visibility changes. rowExample in get_template_inputs is a ready row. With columns, a row is instead an array of cells in column order, which keeps large batches small. null leaves a layer at the template's own value. Layers left out keep the template's value, or the one in defaults."New value: +"1 to 1,000 rows, each its own modifications and output, rendered on every page named (or as the flow's video)"
    • addedInput schema / properties / rows / items / additionalProperties
      Added value: +false
    • removedInput schema / properties / rows / items / anyOf
      Removed value: -[
      -  {
      -    "additionalProperties": {
      -      "anyOf": [
      -        {
      -          "anyOf": [
      -            {
      -              "description": "A text layer's text, with <s1>...</s1> tags for runs when it has several styles; or an image layer's asset id or file name",
      -              "type": "string"
      -            },
      -            {
      -              "additionalProperties": {},
      -              "description": "A text layer's text and visibility",
      -              "properties": {
      -                "text": {
      -                  "description": "The layer's new text, tagged like a string value",
      -                  "type": "string"
      -                },
      -                "visible": {
      -                  "description": "false hides the layer; layout closes the gap",
      -                  "type": "boolean"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            {
      -              "additionalProperties": {},
      -              "description": "An image layer's image and framing",
      -              "properties": {
      -                "asset": {
      -                  "description": "An asset id (search_assets, upload_images), the image's file name, or a designer image key. Omit to keep the template's image and only re-frame it.",
      -                  "type": "string"
      -                },
      -                "fit": {
      -                  "description": "cover fills the slot and crops (default), contain shows the whole image, stretch distorts to the slot. The designer's names work too: fill is cover, fit is contain",
      -                  "enum": [
      -                    "cover",
      -                    "contain",
      -                    "stretch",
      -                    "fill",
      -                    "fit"
      -                  ],
      -                  "type": "string"
      -                },
      -                "panX": {
      -                  "description": "Moves the image by this fraction of the slot width; positive = right",
      -                  "maximum": 1,
      -                  "minimum": -1,
      -                  "type": "number"
      -                },
      -                "panY": {
      -                  "description": "Moves the image by this fraction of the slot height; positive = down",
      -                  "maximum": 1,
      -                  "minimum": -1,
      -                  "type": "number"
      -                },
      -                "visible": {
      -                  "description": "false hides the layer",
      -                  "type": "boolean"
      -                },
      -                "zoom": {
      -                  "description": "Zoom about the slot centre; 1 = none",
      -                  "maximum": 4,
      -                  "minimum": 0.2,
      -                  "type": "number"
      -                }
      -              },
      -              "type": "object"
      -            }
      -          ]
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ]
      -    },
      -    "propertyNames": {
      -      "type": "string"
      -    },
      -    "type": "object"
      -  },
      -  {
      -    "items": {
      -      "anyOf": [
      -        {
      -          "anyOf": [
      -            {
      -              "description": "A text layer's text, with <s1>...</s1> tags for runs when it has several styles; or an image layer's asset id or file name",
      -              "type": "string"
      -            },
      -            {
      -              "additionalProperties": {},
      -              "description": "A text layer's text and visibility",
      -              "properties": {
      -                "text": {
      -                  "description": "The layer's new text, tagged like a string value",
      -                  "type": "string"
      -                },
      -                "visible": {
      -                  "description": "false hides the layer; layout closes the gap",
      -                  "type": "boolean"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            {
      -              "additionalProperties": {},
      -              "description": "An image layer's image and framing",
      -              "properties": {
      -                "asset": {
      -                  "description": "An asset id (search_assets, upload_images), the image's file name, or a designer image key. Omit to keep the template's image and only re-frame it.",
      -                  "type": "string"
      -                },
      -                "fit": {
      -                  "description": "cover fills the slot and crops (default), contain shows the whole image, stretch distorts to the slot. The designer's names work too: fill is cover, fit is contain",
      -                  "enum": [
      -                    "cover",
      -                    "contain",
      -                    "stretch",
      -                    "fill",
      -                    "fit"
      -                  ],
      -                  "type": "string"
      -                },
      -                "panX": {
      -                  "description": "Moves the image by this fraction of the slot width; positive = right",
      -                  "maximum": 1,
      -                  "minimum": -1,
      -                  "type": "number"
      -                },
      -                "panY": {
      -                  "description": "Moves the image by this fraction of the slot height; positive = down",
      -                  "maximum": 1,
      -                  "minimum": -1,
      -                  "type": "number"
      -                },
      -                "visible": {
      -                  "description": "false hides the layer",
      -                  "type": "boolean"
      -                },
      -                "zoom": {
      -                  "description": "Zoom about the slot centre; 1 = none",
      -                  "maximum": 4,
      -                  "minimum": 0.2,
      -                  "type": "number"
      -                }
      -              },
      -              "type": "object"
      -            }
      -          ]
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ]
      -    },
      -    "type": "array"
      -  }
      -]
    • addedInput schema / properties / rows / items / properties
      Added value: +{
      +  "modifications": {
      +    "additionalProperties": {
      +      "anyOf": [
      +        {
      +          "anyOf": [
      +            {
      +              "description": "A text layer's text, with <s1>...</s1> tags for runs when it has several styles; or an image layer's asset id or file name",
      +              "type": "string"
      +            },
      +            {
      +              "additionalProperties": {},
      +              "description": "A text layer's text and visibility",
      +              "properties": {
      +                "text": {
      +                  "description": "The layer's new text, tagged like a string value",
      +                  "type": "string"
      +                },
      +                "visible": {
      +                  "description": "false hides the layer; layout closes the gap",
      +                  "type": "boolean"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            {
      +              "additionalProperties": {},
      +              "description": "An image layer's image and framing",
      +              "properties": {
      +                "asset": {
      +                  "description": "An asset id (search_assets, upload_images), the image's file name, or a designer image key. Omit to keep the template's image and only re-frame it.",
      +                  "type": "string"
      +                },
      +                "fit": {
      +                  "description": "cover fills the slot and crops (default), contain shows the whole image, stretch distorts to the slot. The designer's names work too: fill is cover, fit is contain",
      +                  "enum": [
      +                    "cover",
      +                    "contain",
      +                    "stretch",
      +                    "fill",
      +                    "fit"
      +                  ],
      +                  "type": "string"
      +                },
      +                "panX": {
      +                  "description": "Moves the image by this fraction of the slot width; positive = right",
      +                  "maximum": 1,
      +                  "minimum": -1,
      +                  "type": "number"
      +                },
      +                "panY": {
      +                  "description": "Moves the image by this fraction of the slot height; positive = down",
      +                  "maximum": 1,
      +                  "minimum": -1,
      +                  "type": "number"
      +                },
      +                "visible": {
      +                  "description": "false hides the layer",
      +                  "type": "boolean"
      +                },
      +                "zoom": {
      +                  "description": "Zoom about the slot centre; 1 = none",
      +                  "maximum": 4,
      +                  "minimum": 0.2,
      +                  "type": "number"
      +                }
      +              },
      +              "type": "object"
      +            }
      +          ]
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "default": {},
      +    "description": "Layer key to value: a layer's name (case aside) or id, the key get_template_inputs gives, to a plain value: text as a string, an image as an asset id or file name, or { asset, fit, zoom, panX, panY } and { text, visible } when framing or visibility changes. rowExample in get_template_inputs is ready to use. null leaves a layer at the page's own value; layers left out keep it too.",
      +    "propertyNames": {
      +      "type": "string"
      +    },
      +    "type": "object"
      +  },
      +  "output": {
      +    "additionalProperties": false,
      +    "description": "What to make; png when omitted",
      +    "properties": {
      +      "fileName": {
      +        "description": "The file's name, without extension",
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "format": {
      +        "default": "png",
      +        "description": "png, jpeg and webp render an image and pdf one vector page; mp4 and gif render the whole motion as a video, and webm (VP9) and mov (ProRes 4444) as a transparent video for overlaying on other footage. Video needs an animated template (get_template_inputs isAnimated) and costs more credits",
      +        "enum": [
      +          "png",
      +          "jpeg",
      +          "webp",
      +          "pdf",
      +          "mp4",
      +          "gif",
      +          "webm",
      +          "mov"
      +        ],
      +        "type": "string"
      +      },
      +      "stillTime": {
      +        "description": "Animated pages, images only: the second of the motion the image shows. Omit it to use the page's own still time (get_template_inputs stillTime), else the last frame. If the page has no still time, ask the user, because an outro or a loop can make the last frame a bad image.",
      +        "maximum": 600,
      +        "minimum": 0,
      +        "type": "number"
      +      }
      +    },
      +    "type": "object"
      +  }
      +}
    • addedInput schema / properties / rows / items / type
      Added value: +"object"
    • changedInput schema / properties / rows / maxItems
      Previous value: -500New value: +1000
    • removedInput schema / properties / templateId
      Removed value: -{
      -  "description": "The whole template, from search_templates. Not a page or flow id.",
      -  "format": "uuid",
      -  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
      -  "type": "string"
      -}
    • addedInput schema / properties / templates
      Added value: +{
      +  "description": "Instead of pages: template ids whose every page each row renders on, in page order",
      +  "items": {
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "maxItems": 20,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "templateId",
      -  "rows"
      -]New value: +[
      +  "rows"
      +]
    • addedOutput schema / properties / creditCost
      Added value: +{
      +  "description": "Credits those jobs spend when they render",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • removedOutput schema / properties / issues / items / properties / code / enum
      Removed value: -[
      -  "unknown_layer",
      -  "ambiguous_layer",
      -  "bad_value",
      -  "type_mismatch",
      -  "asset_not_found",
      -  "asset_ambiguous"
      -]
    • changedOutput schema / properties / issues / items / properties / field / description
      Previous value: -"The row key the problem is in"New value: +"The modifications key the problem is in"
    • addedOutput schema / properties / issues / items / properties / row
      Added value: +{
      +  "description": "Zero-based position of the row in rows",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • removedOutput schema / properties / issues / items / properties / rowIndex
      Removed value: -{
      -  "description": "Zero-based position of the row in rows",
      -  "maximum": 9007199254740991,
      -  "minimum": 0,
      -  "type": "integer"
      -}
    • changedOutput schema / properties / issues / items / required
      Previous value: -[
      -  "rowIndex",
      -  "field",
      -  "message"
      -]New value: +[
      +  "row",
      +  "field",
      +  "message"
      +]
    • addedOutput schema / properties / jobCount
      Added value: +{
      +  "description": "Jobs the batch makes: one per row per page",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / rows / description
      Previous value: -"Each row as the server understood it, keyed by layer key, images as { asset, name }"New value: +"Each row as the server read it on each page"
    • changedOutput schema / properties / rows / items / additionalProperties
      Previous value: -{}New value: +false
    • addedOutput schema / properties / rows / items / properties
      Added value: +{
      +  "pages": {
      +    "items": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "modifications": {
      +          "additionalProperties": {},
      +          "description": "The row as this page read it, by layer; images as { asset, name }",
      +          "propertyNames": {
      +            "type": "string"
      +          },
      +          "type": "object"
      +        },
      +        "page": {
      +          "description": "The page, or the flow for a video",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "page",
      +        "modifications"
      +      ],
      +      "type": "object"
      +    },
      +    "type": "array"
      +  },
      +  "row": {
      +    "maximum": 9007199254740991,
      +    "minimum": 0,
      +    "type": "integer"
      +  }
      +}
    • removedOutput schema / properties / rows / items / propertyNames
      Removed value: -{
      -  "type": "string"
      -}
    • addedOutput schema / properties / rows / items / required
      Added value: +[
      +  "row",
      +  "pages"
      +]
    • removedOutput schema / properties / sharedNames
      Removed value: -{
      -  "description": "Layer names more than one layer has; rows key those layers by id. Mention them to the user.",
      -  "items": {
      -    "additionalProperties": false,
      -    "properties": {
      -      "ids": {
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "name": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "name",
      -      "ids"
      -    ],
      -    "type": "object"
      -  },
      -  "type": "array"
      -}
    • changedOutput schema / required
      Previous value: -[
      -  "valid",
      -  "rowCount",
      -  "validRows",
      -  "invalidRows",
      -  "issues"
      -]New value: +[
      +  "valid",
      +  "rowCount",
      +  "validRows",
      +  "invalidRows",
      +  "jobCount",
      +  "creditCost",
      +  "issues",
      +  "rows"
      +]
  2. Changed6 schema fields changed
    • addedInput schema / additionalProperties
      Added value: +false
    • addedInput schema / properties / flowIds
      Added value: +{
      +  "description": "Instead of pageIds: this template's flows (get_template_inputs flows), each a video joining some of its pages, that every row renders as, one video per row per flow, with a video outputFormat. A name fills every layer with it across a video's pages.",
      +  "items": {
      +    "format": "uuid",
      +    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
      +    "type": "string"
      +  },
      +  "maxItems": 20,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • removedInput schema / properties / pageId
      Removed value: -{
      -  "description": "One page of the template (the designer connection's page_id). A template's pages are separate designs, each with its own inputs; the first page when omitted.",
      -  "format": "uuid",
      -  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
      -  "type": "string"
      -}
    • changedInput schema / properties / pageIds / description
      Previous value: -"Instead of pageId: pages every row renders on, one image per row per page, such as a carousel's slides in order. A row may carry keys of any of these pages; each page takes the keys it has."New value: +"This template's pages (get_template_inputs pages) every row renders on, in order: one id for one file per row, several for one file per row per page, such as a carousel's slides. The first page when omitted. A row may carry keys of any of these pages; each page takes the keys it has."
    • changedInput schema / properties / templateId / description
      Previous value: -"Template ID returned by search_templates"New value: +"The whole template, from search_templates. Not a page or flow id."
    • addedOutput schema / properties / warnings
      Added value: +{
      +  "description": "Not errors: pass these on to the user, such as a flow longer than a video renders",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  3. Changed13 schema fields changed
    • removedInput schema / additionalProperties
      Removed value: -false
    • removedInput schema / properties / defaults / additionalProperties / $ref
      Removed value: -"#/properties/rows/items/anyOf/0/additionalProperties/anyOf/0"
    • addedInput schema / properties / defaults / additionalProperties / anyOf
      Added value: +[
      +  {
      +    "description": "A text layer's text, with <s1>...</s1> tags for runs when it has several styles; or an image layer's asset id or file name",
      +    "type": "string"
      +  },
      +  {
      +    "additionalProperties": {},
      +    "description": "A text layer's text and visibility",
      +    "properties": {
      +      "text": {
      +        "description": "The layer's new text, tagged like a string value",
      +        "type": "string"
      +      },
      +      "visible": {
      +        "description": "false hides the layer; layout closes the gap",
      +        "type": "boolean"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": {},
      +    "description": "An image layer's image and framing",
      +    "properties": {
      +      "asset": {
      +        "description": "An asset id (search_assets, upload_images), the image's file name, or a designer image key. Omit to keep the template's image and only re-frame it.",
      +        "type": "string"
      +      },
      +      "fit": {
      +        "description": "cover fills the slot and crops (default), contain shows the whole image, stretch distorts to the slot. The designer's names work too: fill is cover, fit is contain",
      +        "enum": [
      +          "cover",
      +          "contain",
      +          "stretch",
      +          "fill",
      +          "fit"
      +        ],
      +        "type": "string"
      +      },
      +      "panX": {
      +        "description": "Moves the image by this fraction of the slot width; positive = right",
      +        "maximum": 1,
      +        "minimum": -1,
      +        "type": "number"
      +      },
      +      "panY": {
      +        "description": "Moves the image by this fraction of the slot height; positive = down",
      +        "maximum": 1,
      +        "minimum": -1,
      +        "type": "number"
      +      },
      +      "visible": {
      +        "description": "false hides the layer",
      +        "type": "boolean"
      +      },
      +      "zoom": {
      +        "description": "Zoom about the slot centre; 1 = none",
      +        "maximum": 4,
      +        "minimum": 0.2,
      +        "type": "number"
      +      }
      +    },
      +    "type": "object"
      +  }
      +]
    • addedInput schema / properties / defaults / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • addedInput schema / properties / pageId / pattern
      Added value: +"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
    • addedInput schema / properties / pageIds
      Added value: +{
      +  "description": "Instead of pageId: pages every row renders on, one image per row per page, such as a carousel's slides in order. A row may carry keys of any of these pages; each page takes the keys it has.",
      +  "items": {
      +    "format": "uuid",
      +    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
      +    "type": "string"
      +  },
      +  "maxItems": 20,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • changedInput schema / properties / rows / items / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": {
      -      "anyOf": [
      -        {
      -          "anyOf": [
      -            {
      -              "description": "A text layer's text, with <s1>...</s1> tags for runs when it has several styles; or an image layer's asset id or file name",
      -              "type": "string"
      -            },
      -            {
      -              "additionalProperties": true,
      -              "description": "A text layer's text and visibility",
      -              "properties": {
      -                "text": {
      -                  "description": "The layer's new text, tagged like a string value",
      -                  "type": "string"
      -                },
      -                "visible": {
      -                  "description": "false hides the layer; layout closes the gap",
      -                  "type": "boolean"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            {
      -              "additionalProperties": true,
      -              "description": "An image layer's image and framing",
      -              "properties": {
      -                "asset": {
      -                  "description": "An asset id (search_assets, upload_images), the image's file name, or a designer image key. Omit to keep the template's image and only re-frame it.",
      -                  "type": "string"
      -                },
      -                "fit": {
      -                  "description": "cover fills the slot and crops (default), contain shows the whole image, stretch distorts to the slot. The designer's names work too: fill is cover, fit is contain",
      -                  "enum": [
      -                    "cover",
      -                    "contain",
      -                    "stretch",
      -                    "fill",
      -                    "fit"
      -                  ],
      -                  "type": "string"
      -                },
      -                "panX": {
      -                  "description": "Moves the image by this fraction of the slot width; positive = right",
      -                  "maximum": 1,
      -                  "minimum": -1,
      -                  "type": "number"
      -                },
      -                "panY": {
      -                  "description": "Moves the image by this fraction of the slot height; positive = down",
      -                  "maximum": 1,
      -                  "minimum": -1,
      -                  "type": "number"
      -                },
      -                "visible": {
      -                  "description": "false hides the layer",
      -                  "type": "boolean"
      -                },
      -                "zoom": {
      -                  "description": "Zoom about the slot centre; 1 = none",
      -                  "maximum": 4,
      -                  "minimum": 0.2,
      -                  "type": "number"
      -                }
      -              },
      -              "type": "object"
      -            }
      -          ]
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ]
      -    },
      -    "type": "object"
      -  },
      -  {
      -    "items": {
      -      "anyOf": [
      -        {
      -          "$ref": "#/properties/rows/items/anyOf/0/additionalProperties/anyOf/0"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ]
      -    },
      -    "type": "array"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": {
      +      "anyOf": [
      +        {
      +          "anyOf": [
      +            {
      +              "description": "A text layer's text, with <s1>...</s1> tags for runs when it has several styles; or an image layer's asset id or file name",
      +              "type": "string"
      +            },
      +            {
      +              "additionalProperties": {},
      +              "description": "A text layer's text and visibility",
      +              "properties": {
      +                "text": {
      +                  "description": "The layer's new text, tagged like a string value",
      +                  "type": "string"
      +                },
      +                "visible": {
      +                  "description": "false hides the layer; layout closes the gap",
      +                  "type": "boolean"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            {
      +              "additionalProperties": {},
      +              "description": "An image layer's image and framing",
      +              "properties": {
      +                "asset": {
      +                  "description": "An asset id (search_assets, upload_images), the image's file name, or a designer image key. Omit to keep the template's image and only re-frame it.",
      +                  "type": "string"
      +                },
      +                "fit": {
      +                  "description": "cover fills the slot and crops (default), contain shows the whole image, stretch distorts to the slot. The designer's names work too: fill is cover, fit is contain",
      +                  "enum": [
      +                    "cover",
      +                    "contain",
      +                    "stretch",
      +                    "fill",
      +                    "fit"
      +                  ],
      +                  "type": "string"
      +                },
      +                "panX": {
      +                  "description": "Moves the image by this fraction of the slot width; positive = right",
      +                  "maximum": 1,
      +                  "minimum": -1,
      +                  "type": "number"
      +                },
      +                "panY": {
      +                  "description": "Moves the image by this fraction of the slot height; positive = down",
      +                  "maximum": 1,
      +                  "minimum": -1,
      +                  "type": "number"
      +                },
      +                "visible": {
      +                  "description": "false hides the layer",
      +                  "type": "boolean"
      +                },
      +                "zoom": {
      +                  "description": "Zoom about the slot centre; 1 = none",
      +                  "maximum": 4,
      +                  "minimum": 0.2,
      +                  "type": "number"
      +                }
      +              },
      +              "type": "object"
      +            }
      +          ]
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "propertyNames": {
      +      "type": "string"
      +    },
      +    "type": "object"
      +  },
      +  {
      +    "items": {
      +      "anyOf": [
      +        {
      +          "anyOf": [
      +            {
      +              "description": "A text layer's text, with <s1>...</s1> tags for runs when it has several styles; or an image layer's asset id or file name",
      +              "type": "string"
      +            },
      +            {
      +              "additionalProperties": {},
      +              "description": "A text layer's text and visibility",
      +              "properties": {
      +                "text": {
      +                  "description": "The layer's new text, tagged like a string value",
      +                  "type": "string"
      +                },
      +                "visible": {
      +                  "description": "false hides the layer; layout closes the gap",
      +                  "type": "boolean"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            {
      +              "additionalProperties": {},
      +              "description": "An image layer's image and framing",
      +              "properties": {
      +                "asset": {
      +                  "description": "An asset id (search_assets, upload_images), the image's file name, or a designer image key. Omit to keep the template's image and only re-frame it.",
      +                  "type": "string"
      +                },
      +                "fit": {
      +                  "description": "cover fills the slot and crops (default), contain shows the whole image, stretch distorts to the slot. The designer's names work too: fill is cover, fit is contain",
      +                  "enum": [
      +                    "cover",
      +                    "contain",
      +                    "stretch",
      +                    "fill",
      +                    "fit"
      +                  ],
      +                  "type": "string"
      +                },
      +                "panX": {
      +                  "description": "Moves the image by this fraction of the slot width; positive = right",
      +                  "maximum": 1,
      +                  "minimum": -1,
      +                  "type": "number"
      +                },
      +                "panY": {
      +                  "description": "Moves the image by this fraction of the slot height; positive = down",
      +                  "maximum": 1,
      +                  "minimum": -1,
      +                  "type": "number"
      +                },
      +                "visible": {
      +                  "description": "false hides the layer",
      +                  "type": "boolean"
      +                },
      +                "zoom": {
      +                  "description": "Zoom about the slot centre; 1 = none",
      +                  "maximum": 4,
      +                  "minimum": 0.2,
      +                  "type": "number"
      +                }
      +              },
      +              "type": "object"
      +            }
      +          ]
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "type": "array"
      +  }
      +]
    • addedInput schema / properties / templateId / pattern
      Added value: +"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
    • addedOutput schema / properties / invalidRows / maximum
      Added value: +9007199254740991
    • addedOutput schema / properties / issues / items / properties / rowIndex / maximum
      Added value: +9007199254740991
    • addedOutput schema / properties / rowCount / maximum
      Added value: +9007199254740991
    • addedOutput schema / properties / rows / items / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / validRows / maximum
      Added value: +9007199254740991
  4. First observed

TDQS

A4.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, and the description reinforces this with 'without saving anything or spending credits' plus the creditCost the batch would incur. It adds genuinely useful behavior beyond annotations: errors are reported by row index and field, duplicate layer names are refused with ids, and text is not measured. These are meaningful additions, though much of the safety profile is duplicated from annotations.

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?

Purpose and the no-cost/no-save guarantee are front-loaded, and each later sentence carries distinct information (return shape, duplicate names, the text-measurement gap). It is dense and somewhat long, with mild redundancy between 'without saving anything' and 'create_batch saves nothing', but no filler sentences.

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

Completeness5/5

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

Covers purpose, cost model, failure reporting shape, a specific edge-case remedy, a known limitation, and required scope — more than enough for a validation tool that also has an output schema. Nothing an agent needs to invoke or interpret it correctly is missing.

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 100%, so the baseline is 3, but the description adds real meaning by framing the three mutually exclusive render-selection modes (pages vs templates vs flow) in one sentence and by explaining the duplicate-layer-name refusal and id-based fill workaround. It does not add format syntax beyond the schema, so it stops short of a 5.

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 ('Checks batch rows') plus the scope it validates ('pages, every page of templates, or a flow's video') and explicitly contrasts with the sibling create_batch. An agent can distinguish this from create_batch/run_batch without opening a schema.

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

Usage Guidelines5/5

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

Gives an explicit when-to-use rule: run this first because 'rows that pass here are accepted there', and notes create_batch saves nothing on failure. It also names the one class of problem it cannot catch (text overflow) and the auth scope needed, so the agent knows the limits of the gate.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources