diff --git a/docs/api/prompt-schema.md b/docs/api/prompt-schema.md new file mode 100644 index 000000000..48d1bb289 --- /dev/null +++ b/docs/api/prompt-schema.md @@ -0,0 +1,137 @@ +# ComfyUI Prompt API Schema + +This document describes the JSON format used by the `/prompt` endpoint in ComfyUI. + +## Overview + +A ComfyUI prompt is a JSON object where: +- **Keys** are unique node IDs (arbitrary strings, typically numeric) +- **Values** are node objects containing `class_type`, `inputs`, and optional `_meta` + +## Format Specification + +### Node Object + +```json +{ + "class_type": "KSampler", + "inputs": { + "seed": 123456, + "steps": 20, + "model": ["4", 0] + }, + "_meta": { + "title": "My KSampler" + } +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `class_type` | string | ✅ | Must match a registered node class in `NODE_CLASS_MAPPINGS` | +| `inputs` | object | ✅ | Input parameters for the node | +| `_meta` | object | ❌ | UI metadata (display title, position, etc.) | + +### Input Values + +Each input can be one of two types: + +#### Direct Value +Any JSON-serializable value: +```json +{"seed": 123456, "steps": 20, "cfg": 7.0, "width": 512} +``` + +#### Node Link (Output Reference) +A 2-element array `[source_node_id, output_index]`: +```json +{"model": ["4", 0], "positive": ["6", 0]} +``` + +### Validation Rules + +Based on `execution.py:validate_prompt()`: + +1. Every node **must** have a `class_type` field +2. `class_type` **must** reference a registered node (existing in `NODE_CLASS_MAPPINGS`) +3. The prompt **must** contain at least one `OUTPUT_NODE` +4. All linked inputs must reference valid node IDs and output indices +5. Required inputs for each node class must be provided + +### Common Error Types + +| Type | Description | +|------|-------------| +| `missing_node_type` | Node has no `class_type` or class not found | +| `prompt_no_outputs` | No OUTPUT_NODE found in the prompt | + +## Validation + +Use the JSON Schema to validate prompts: + +```bash +# Using ajv-cli +npx ajv validate -s schemas/prompt.json -d my_prompt.json + +# Using Python +pip install jsonschema +python -c " +import json, jsonschema +with open('schemas/prompt.json') as f: + schema = json.load(f) +with open('my_prompt.json') as f: + prompt = json.load(f) +jsonschema.validate(prompt, schema) +print('Valid!') +" +``` + +## Minimal Example + +```json +{ + "1": { + "class_type": "CheckpointLoaderSimple", + "inputs": {"ckpt_name": "model.safetensors"} + }, + "2": { + "class_type": "CLIPTextEncode", + "inputs": {"text": "hello world", "clip": ["1", 1]} + }, + "3": { + "class_type": "EmptyLatentImage", + "inputs": {"width": 512, "height": 512, "batch_size": 1} + }, + "4": { + "class_type": "KSampler", + "inputs": { + "seed": 0, "steps": 20, "cfg": 7, + "sampler_name": "euler", "scheduler": "normal", + "denoise": 1, "model": ["1", 0], + "positive": ["2", 0], "negative": ["2", 0], + "latent_image": ["3", 0] + } + }, + "5": { + "class_type": "VAEDecode", + "inputs": {"samples": ["4", 0], "vae": ["1", 2]} + }, + "6": { + "class_type": "SaveImage", + "inputs": {"filename_prefix": "test", "images": ["5", 0]} + } +} +``` + +## Workflow vs Prompt Format + +The **prompt format** (this schema) is the compact API format used by `/prompt`. + +The **workflow format** is the UI serialization format that includes additional layout data, group information, and node positions. Workflows are converted to prompts before execution. + +## Future Enhancements + +This schema documents the current static format. Future versions may include: +- Per-node schemas with required/optional input definitions +- Dynamic schema generation based on installed custom nodes +- LLM-friendly structured output definitions diff --git a/schemas/prompt.json b/schemas/prompt.json new file mode 100644 index 000000000..3bbb8f13e --- /dev/null +++ b/schemas/prompt.json @@ -0,0 +1,89 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://github.com/Comfy-Org/ComfyUI/blob/main/schemas/prompt.json", + "title": "ComfyUI Prompt Format", + "description": "JSON Schema for the ComfyUI /prompt endpoint. Each key is a unique node ID, and each value describes a node with its class_type, inputs, and optional metadata.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/node" + }, + "definitions": { + "node": { + "type": "object", + "required": ["class_type", "inputs"], + "properties": { + "class_type": { + "type": "string", + "description": "The node class to instantiate. Must match a key in NODE_CLASS_MAPPINGS." + }, + "inputs": { + "$ref": "#/definitions/inputs" + }, + "_meta": { + "type": "object", + "description": "Optional UI metadata for a node.", + "properties": { + "title": { + "type": "string", + "description": "Display title for the node in the UI." + } + } + } + }, + "additionalProperties": true + }, + "inputs": { + "type": "object", + "description": "Node inputs. Keys are parameter names. Values are either direct values or node links [source_id, output_index].", + "additionalProperties": true + }, + "node_link": { + "type": "array", + "description": "A link to another node's output.", + "items": [ + {"type": "string", "description": "Source node ID"}, + {"type": "integer", "description": "Output index of the source node"} + ], + "minItems": 2, + "maxItems": 2 + } + }, + "examples": [ + { + "4": { + "class_type": "CheckpointLoaderSimple", + "inputs": {"ckpt_name": "v1-5-pruned-emaonly.safetensors"} + }, + "5": { + "class_type": "EmptyLatentImage", + "inputs": {"width": 512, "height": 512, "batch_size": 1} + }, + "6": { + "class_type": "CLIPTextEncode", + "inputs": {"text": "a beautiful landscape", "clip": ["4", 1]} + }, + "7": { + "class_type": "CLIPTextEncode", + "inputs": {"text": "ugly, blurry", "clip": ["4", 1]} + }, + "3": { + "class_type": "KSampler", + "inputs": { + "seed": 123456, "steps": 20, "cfg": 7.0, + "sampler_name": "euler", "scheduler": "normal", "denoise": 1.0, + "model": ["4", 0], "positive": ["6", 0], "negative": ["7", 0], + "latent_image": ["5", 0] + } + }, + "8": { + "class_type": "VAEDecode", + "inputs": {"samples": ["3", 0], "vae": ["4", 2]}, + "_meta": {"title": "VAE Decode"} + }, + "9": { + "class_type": "SaveImage", + "inputs": {"filename_prefix": "ComfyUI", "images": ["8", 0]} + } + } + ] +}