nodes[] are {id, type: "agent", position: {x, y}, data: {label, type, config}} with string or number config values; place each block 220 right of its input and branches 180 apart. edges[] are {id, source, target}; templateId is "". Dataset {dataset: slug or "official:coco8", split: train|val|test, maxInputs: up to 20 on free shared trials, 0 = all with a deployment} reads images; given an input, {dataset: slug} collects them. Image {dataset, image: image ID, name} is one dataset image; uploads happen on the canvas. YOLO {model: "ul://ultralytics/yolo26/yolo26n" (-seg, -pose, -obb, -cls suffixes) or ul://owner/project/model, task, conf?}; official models detect the 80 COCO classes. LLM {model: e.g. gemini-nano-banana-2.1, prompt} reads the image and upstream text. Gate {kind: "condition", path: "<YOLO or Deployment block id>.counts.<class>" or ".confidence.<class or *>", op: eq|ne|gt|gte|lt|lte|between, value, upper?} or {kind: "every", unit: frames|seconds, value}. Deployment {deployment: slug, conf?}. Export {model, format} stands alone. Output {}. Slack {message}. Webhook {url: HTTPS, body: JSON object as a string}. Messages and bodies insert the upstream result at "{output}". Each block has at most one input. Dataset and Image blocks start chains; Export, Output, Slack, and Webhook end them.