> ## Documentation Index
> Fetch the complete documentation index at: https://comfyui-mcp.artokun.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflow Execution

> Enqueue workflows — one at a time, from a named template, or as a batch — and inspect the queue, jobs, history, and system stats.

<Info>6 tools. Generated from the live MCP tool schemas — do not edit by hand; run `npm run docs:gen`.</Info>

<Tip>**You don't type these calls.** Ask your agent for what you want in ordinary English — it chooses the tool and fills in the arguments. The JSON on this page is what it sends. New here? Start with [Using the tools](/docs/using-tools).</Tip>

## enqueue\_workflow

Submit work to the ComfyUI execution queue — the primary way an agent starts a render. Driven by the `action` parameter:

* action:"enqueue" — Submit an API-format workflow you are already holding (one you built with create\_workflow, loaded with get\_workflow, or edited with create\_workflow action:"modify"). Returns immediately with the prompt\_id and queue position; does NOT wait for completion. Seed values in the workflow are used EXACTLY as supplied — they are NOT re-randomized, so a run is reproducible by resubmitting the same workflow (for a fresh-seed re-run of a past job, use action:"rerun"). `workflow` is required. Use queue (action:"status") to check progress later, or get\_history (action:"list") to retrieve results and images after completion.
* action:"rerun" — Re-run the workflow behind a PREVIOUS generation. Retrieves the prompt graph from execution history (by `prompt_id`, or the most recent run when omitted — chosen by ComfyUI's queue number, same logic as get\_history) and re-enqueues it, optionally applying `inputs` overrides. Seeds are re-randomized (within each node's declared range) unless disable\_random\_seed is set or the seed is pinned via `inputs`. Returns the new prompt\_id and the source prompt\_id it came from. Clear error if no matching history exists. To re-run from a registered ASSET instead of history, use generate\_image (action:"regenerate").
* action:"run\_url" — Read (and optionally execute) a SHARED workflow from a URL. Fetches the workflow JSON, accepts API-format prompt graphs or UI-format exports (UI is auto-converted via the same converter as get\_workflow), validates it, and summarizes it. Supports raw .json links and GitHub blob/raw URLs (blob is normalized to raw); other share hosts that need a site API return a clear 'paste the raw JSON URL' error. The fetch is bounded (http/https only, timeout + size cap, loopback/private/metadata IPs rejected to prevent SSRF). READ-ONLY unless run=true; when run=true it enqueues the workflow (applying optional `inputs` overrides) and returns the prompt\_id. `url` is required.
* action:"template\_schema" — Get a template's OVERRIDABLE run-time parameters (its 'slots') BEFORE running it. Pass a bundled pack name (from list\_packs action:"list") or a custom-node-contributed workflow template name (from list\_packs action:"list\_templates") as `template`. Returns `slots` — the meaningful knobs: positive/negative prompt, seed, steps, cfg, sampler/scheduler, width/height, checkpoint/LoRA/model files, denoise, batch\_size, input image — plus `other_slots` (every remaining overridable widget), each with a stable key "\<nodeId>.\<widget\_name>", semantic role, type, current value, and min/max/options where the node schema is known. Read-only. Feed the keys DIRECTLY into action:"run\_template"'s `overrides` (same convention) for a schema→run round-trip.
* action:"run\_template" — ONE-SHOT: run a named workflow template (a bundled pack from list\_packs) with optional `overrides`. Resolves the template's expert graph, applies overrides, and enqueues it — replacing the manual list\_packs (action:"read\_workflow") → create\_workflow (action:"modify") → action:"enqueue" chain. Override keys are '\<nodeId>.\<widget\_name>' (e.g. \{'6.text': 'a cat', '3.seed': 42}) — the SAME keys action:"template\_schema" reports (when available), so schema→run round-trips; only widget values can be overridden, never graph connections. By default returns \{prompt\_id} immediately; pass wait:true to block until the job completes and return its outputs (images etc.). Unresolvable template names return a clear error with near-matches. `template` is required.

<Tip>**In plain terms:** Starts a render. `action` says where the graph comes from: one the agent is holding in the conversation, an earlier run, a URL someone shared, or a bundled template. If you want to run the graph you are LOOKING at in ComfyUI, that is the panel's run tool instead, and if you just want a picture, use generate\_image.</Tip>

### Parameters

<ParamField path="action" type="enum" required>
  Which enqueue entry point to use. action:"enqueue" requires `workflow`; action:"rerun" takes an optional `prompt_id` (+ `inputs`); action:"run\_url" requires `url` (+ `run`/`inputs`); action:"template\_schema" and action:"run\_template" require `template`; with action:"run\_template" you may also pass `overrides`/`wait`/`timeout_s`. Options: `action:"enqueue"`, `action:"rerun"`, `action:"run_url"`, `action:"template_schema"`, `action:"run_template"`.
</ParamField>

<ParamField path="workflow" type="object">
  action:"enqueue" — ComfyUI workflow in API format (node ID -> \{class\_type, inputs}). REQUIRED for that action.
</ParamField>

<ParamField path="disable_random_seed" type="boolean">
  If true, do not randomize seed values — applies to action:"rerun" and action:"run\_template" (for action:"rerun", combine with inputs.seed to reproduce exactly). It is a NO-OP for action:"enqueue", whose seeds are always used exactly as supplied (issue #865).
</ParamField>

<ParamField path="prompt_id" type="string">
  action:"rerun" — prompt ID of the generation to re-run. If omitted, uses the most recent execution.
</ParamField>

<ParamField path="inputs" type="object">
  Overrides applied to every node with a matching input name (e.g. cfg, steps, sampler\_name, seed, text). Used by action:"rerun", and by action:"run\_url" only when run=true.
</ParamField>

<ParamField path="url" type="string">
  action:"run\_url" — URL of the workflow JSON. Raw .json links and GitHub blob/raw URLs work directly. REQUIRED for that action.
</ParamField>

<ParamField path="run" type="boolean" default="false">
  action:"run\_url" — if true, enqueue the fetched workflow for execution and return the prompt\_id. Default false: only fetch, validate, and summarize (read-only).
</ParamField>

<ParamField path="template" type="string">
  Template name/id: a bundled pack directory name (list\_packs action:"list") or a custom-node-contributed workflow template name (list\_packs action:"list\_templates"). REQUIRED for action:"template\_schema" and action:"run\_template".
</ParamField>

<ParamField path="overrides" type="object">
  action:"run\_template" — widget overrides keyed '\<nodeId>.\<widget\_name>' (action:"template\_schema"'s keys), e.g. \{'6.text': 'a red fox', '3.steps': 20}.
</ParamField>

<ParamField path="wait" type="boolean">
  action:"run\_template" — block until the job completes and return its outputs. Default false: return \{prompt\_id} immediately.
</ParamField>

<ParamField path="timeout_s" type="number">
  action:"run\_template" — max seconds to wait when wait:true (default 300). On timeout the job keeps running; poll queue (action:"status").
</ParamField>

### Examples

**You say:** Run it.

```json theme={null}
{
  "tool": "enqueue_workflow",
  "arguments": {
    "action": "enqueue",
    "workflow": {
      "4": {
        "class_type": "CheckpointLoaderSimple",
        "inputs": {
          "ckpt_name": "sd_xl_base_1.0.safetensors"
        }
      },
      "9": {
        "class_type": "SaveImage",
        "inputs": {
          "filename_prefix": "portrait",
          "images": [
            "8",
            0
          ]
        }
      }
    }
  }
}
```

<Note>Shortened for readability — two nodes of a real API-format graph are shown. In practice the agent passes the whole thing: the graph it just loaded with get\_workflow, or the one it built for you.</Note>

**You get back:** A prompt\_id straight away, then the finished images once the render completes.

**You say:** What can I change about the anima text-to-image pack?

```json theme={null}
{
  "tool": "enqueue_workflow",
  "arguments": {
    "action": "template_schema",
    "template": "anima-txt2img"
  }
}
```

**You get back:** The knobs that template exposes — prompt, size, steps, which model file — with their current values, and the exact keys to pass as `overrides` when you run it. Read-only.

**You say:** Run the anima pack with my prompt and wait for it.

```json theme={null}
{
  "tool": "enqueue_workflow",
  "arguments": {
    "action": "run_template",
    "template": "anima-txt2img",
    "overrides": {
      "45.text": "a lighthouse in a storm, dramatic sky"
    },
    "wait": true
  }
}
```

<Note>Override keys are `"&lt;nodeId&gt;.&lt;widget_name&gt;"`, not bare parameter names — a plain `"prompt"` is rejected. 45 is the positive CLIPTextEncode in THIS pack; every template numbers its nodes differently, so read the keys off the schema call above rather than copying this one.</Note>

**You get back:** With `wait: true`, the finished result in one go. Leave it off and you get a prompt\_id immediately and check back later.

**You say:** Someone posted this workflow — what is in it?

```json theme={null}
{
  "tool": "enqueue_workflow",
  "arguments": {
    "action": "run_url",
    "url": "https://raw.githubusercontent.com/comfyanonymous/ComfyUI_examples/master/flux/flux_dev_example.json"
  }
}
```

**You get back:** A summary of the graph and a validation report, WITHOUT running it. Add `run: true` to enqueue it once you have read what it does.

<Warning>`run: true` executes a graph you did not write on your own GPU. Read the summary first — a shared workflow can pull in models and custom nodes you do not have, and will fail late if so.</Warning>

***

## get\_system\_stats

Inspect the connected ComfyUI server: what it is running on, what it has logged, and whether it is healthy enough to dispatch work to. All three actions are READ-ONLY — nothing here mutates anything. Driven by the `action` parameter:

* action:"stats" — Get system information from the connected ComfyUI server: GPU device(s), total/free VRAM, ComfyUI/Python/PyTorch versions, and OS details. Requires a running ComfyUI server (works against local or remote targets); read-only, takes no parameters. Returns the raw /system\_stats JSON. Use to confirm connectivity and check available VRAM before enqueuing large workflows. Errors if the server is unreachable.
* action:"logs" — Get ComfyUI server runtime logs. Useful for debugging execution errors, model loading issues, missing nodes, and Python tracebacks. `max_lines` tails the end (default 100), `keyword` filters case-insensitively.
* action:"health" — Pre-flight diagnostic for the connected ComfyUI: one call that aggregates the signals an agent should check before dispatching a batch. Reports ComfyUI version/Python/PyTorch, GPU name + VRAM free/total, system RAM free, queue depth (running + pending), per-category /models populations (catches empty dropdowns from a misconfigured extra\_model\_paths.yaml), and recent errors from /internal/logs. Read-only — no mutation. Use this when a job fails for an unexpected reason, before a long batch run, or to confirm a remote ComfyUI is healthy. Originally contributed by github.com/joaolvivas.

<Tip>**In plain terms:** Three read-only views of the connected ComfyUI: action:"stats" for what it is running on, action:"logs" for what it has said, and action:"health" for whether it is fit to dispatch work to. Nothing here changes anything — freeing VRAM is clear\_vram, and filing a bug is report\_issue.</Tip>

### Parameters

<ParamField path="action" type="enum" required>
  Which read to perform. "stats" takes no other parameters; "logs" takes `max_lines`/`keyword`; "health" takes `model_categories`/`recent_errors`. None of them is required. Options: `action:"stats"`, `action:"logs"`, `action:"health"`.
</ParamField>

<ParamField path="max_lines" type="integer">
  action:"logs" — maximum number of log lines to return from the end (default: 100).
</ParamField>

<ParamField path="keyword" type="string">
  action:"logs" — filter log lines containing this keyword (case-insensitive). Examples: 'error', 'warning', 'VRAM', a node name.
</ParamField>

<ParamField path="model_categories" type="string[]">
  action:"health" — override the model categories to poll (defaults to checkpoints, diffusion\_models, loras, vae, text\_encoders, controlnet).
</ParamField>

<ParamField path="recent_errors" type="integer">
  action:"health" — how many recent error/traceback lines to include from /internal/logs (default 20, max 200).
</ParamField>

### Examples

**You say:** How much VRAM have I got left?

```json theme={null}
{
  "tool": "get_system_stats",
  "arguments": {
    "action": "stats"
  }
}
```

**You get back:** The GPU, its total and free VRAM, system RAM, and the ComfyUI and Python versions.

**You say:** Is everything working?

```json theme={null}
{
  "tool": "get_system_stats",
  "arguments": {
    "action": "health"
  }
}
```

**You get back:** Whether the server is reachable, what it is running on, and whether the model folders have anything in them.

**You say:** Check the setup, and tell me if any recent runs blew up.

```json theme={null}
{
  "tool": "get_system_stats",
  "arguments": {
    "action": "health",
    "model_categories": [
      "checkpoints",
      "loras"
    ],
    "recent_errors": 5
  }
}
```

**You get back:** The same report, narrowed to the two model folders you asked about, with the last five errors from history attached.

**You say:** Show me the last errors from the server log.

```json theme={null}
{
  "tool": "get_system_stats",
  "arguments": {
    "action": "logs",
    "keyword": "error",
    "max_lines": 50
  }
}
```

**You get back:** The last fifty log lines that mention 'error', ANSI codes stripped.

***

## queue

Inspect and manage the ComfyUI execution queue. Driven by the `action` parameter:

* action:"list" — The job running now plus all pending jobs, each with its prompt\_id and position. Read-only; requires a reachable ComfyUI server (works against local or remote --comfyui-url). Omits queued workflow payloads by default to keep output small; set include\_workflows:true when you need to inspect or edit the exact pending payload. Use this before action:"cancel" (running), action:"cancel\_queued"/action:"clear" (pending), action:"move", or action:"edit".
* action:"status" — Check ONE job by its prompt\_id (the id returned by enqueue\_workflow). Queries the connected ComfyUI server; requires it to be running. Returns JSON with running, pending, and done booleans, plus optional status\_str, error details, and execution\_stats from ComfyUI history once the job is done. Also returns text\_outputs when the workflow contained text-preview nodes (Preview as Text, ShowText, …) — those produce no image file, so this is the ONLY way to read their result; report that text back to the user. Use action:"list" to see the whole queue at once, and get\_history for full output filenames.
* action:"get\_workflow" — The full workflow payload for one PENDING queue item by prompt\_id. Read-only. Does not work for the currently running job because ComfyUI cannot safely edit a job after execution starts.
* action:"move" — Move a PENDING queue item to the front or back by removing it and re-enqueuing its saved workflow payload; `position` ("front"|"back") is required. The job receives a NEW prompt\_id; the old prompt\_id is removed. Running jobs cannot be moved.
* action:"edit" — Edit a PENDING queue item by removing it and re-enqueuing an updated workflow. Provide either a complete replacement `workflow` or `node_inputs` patches keyed by node id; `position` selects where to requeue (default back). The job receives a NEW prompt\_id; the old prompt\_id is removed. Running jobs cannot be edited.
* action:"cancel" — Stop the CURRENTLY RUNNING job ROBUSTLY. Sends an interrupt, then WAITS and verifies the job actually stopped — ComfyUI only honors interrupts BETWEEN steps, so a long single step (e.g. a high-res video sampler) can ignore a plain cancel. If the interrupt isn't honored it escalates to freeing VRAM (POST /free) and re-checks; if it STILL won't die it reports the job as WEDGED and tells you to restart\_comfyui (an HTTP cancel cannot kill a stuck step). Set clear\_pending:true to also drop ALL pending jobs in the same call — the correct "reset the queue" action, since cancelling alone leaves pending jobs that would run next. The partial result is discarded. With `prompt_id` given, only interrupts the running job when its prompt\_id matches; omit to interrupt whatever is currently running. Use action:"cancel\_queued" to remove one specific PENDING job instead.
* action:"cancel\_queued" — Remove one specific PENDING job from the queue by prompt\_id. Does not affect running jobs.
* action:"clear" — Clear ALL pending jobs from the queue. Does not affect the currently running job.

### Parameters

<ParamField path="action" type="enum" required>
  Which queue operation to perform. "list" and "clear" take no other parameters; "status", "get\_workflow" and "cancel\_queued" require `prompt_id`; "move" requires `prompt_id` + `position`; "edit" requires `prompt_id` (optional `workflow`/`node_inputs`/`position`); "cancel" takes an optional `prompt_id` and `clear_pending`. Options: `action:"list"`, `action:"status"`, `action:"get_workflow"`, `action:"move"`, `action:"edit"`, `action:"cancel"`, `action:"cancel_queued"`, `action:"clear"`.
</ParamField>

<ParamField path="prompt_id" type="string">
  The prompt\_id of a job (the id returned by enqueue\_workflow). REQUIRED for actions "status", "get\_workflow", "move", "edit" and "cancel\_queued" (a PENDING queue item for all but "status"). OPTIONAL for action:"cancel" — if given, only interrupts the running job when its prompt\_id matches; omit to interrupt whatever is currently running.
</ParamField>

<ParamField path="include_workflows" type="boolean">
  action:"list" — include each running/pending job's workflow payload and extra\_data. Can be large.
</ParamField>

<ParamField path="position" type="enum">
  Where to requeue the job. REQUIRED for action:"move". OPTIONAL for action:"edit" — defaults to back. Options: `front`, `back`.
</ParamField>

<ParamField path="workflow" type="object">
  action:"edit" — optional complete replacement API-format workflow. If omitted, the existing queued workflow is patched with `node_inputs`.
</ParamField>

<ParamField path="node_inputs" type="object">
  action:"edit" — optional input patches keyed by node id, e.g. \{"3":\{"steps":30,"cfg":7}}.
</ParamField>

<ParamField path="clear_pending" type="boolean">
  action:"cancel" — also clear ALL pending jobs (recommended when resetting after a stuck/slow render, so a re-queue doesn't stack behind a backlog). Default false.
</ParamField>

### Example

<Note>No worked example yet — the call below is a skeleton generated from the required parameters. Real examples live in `scripts/tool-doc-examples.ts`; contributions welcome.</Note>

```json theme={null}
{
  "tool": "queue",
  "arguments": {
    "action": "list"
  }
}
```

***

## get\_history

Read what has already been generated on this machine — execution history, why a run failed, and the settings your past renders actually used. Driven by the `action` parameter:

* action:"list" — Execution history for a ComfyUI prompt: status, timing, cached nodes, and output details (media filenames for get\_image action:"get"). Also carries the raw error/traceback. To diagnose WHY a run FAILED or what is missing, prefer action:"diagnose" — it returns the same failure info PLUS missing models (with the file + widget) and missing node types, which this action does not. Use action:"list" when you need the run's OUTPUTS or timing for a specific prompt\_id.
* action:"diagnose" — WHY DID MY RENDER FAIL / WHAT IS MISSING? Explains a failed run in ONE call, without needing a canvas — the headless counterpart to the panel's panel\_get\_errors ("why is this red?"), so mobile/remote sessions get the same answer. Returns: the failed node (id, type) with its `exception_type` + message and a trimmed traceback; **missing\_models** (the exact model file that is not installed and the widget holding it — feed the filename to download\_model action:'search\_civitai', then action:'download\_civitai' — or action:'search' then action:'download' — to fix it); **missing\_node\_types** (node classes this install lacks — feed to search\_custom\_nodes, then install\_custom\_node); and any other per-input validation errors. Call this whenever a run fails, an enqueue is rejected, or the user asks what is missing — instead of guessing from raw logs. With no prompt\_id it diagnoses the most recent FAILED run (falling back to the most recent run). Read-only.
* action:"stats" — Statistics from this MCP server's LOCAL generation-history database (populated as you run workflows; NOT from ComfyUI, and not the same source as action:"list"): total generations, count of unique sampler/scheduler/steps/CFG combos, a per-model-family breakdown, and the most-reused settings. Read-only; works without a running ComfyUI. Returns empty stats until you have generated images. For concrete recommended settings rather than aggregate counts, use action:"suggest".
* action:"suggest" — Recommend concrete, proven sampler/scheduler/steps/CFG (and denoise/shift/LoRA) settings derived from that same LOCAL generation-history database. Read-only and works without a running ComfyUI. Narrow results by `model_family`, `lora_hash`, or a name `search`; with no filter it returns the top settings across all history. Returns a ranked list with each combo's reuse count, or a "no history" message until you have generated images. Use this for ready-to-apply values; use action:"stats" for aggregate counts and breakdowns rather than specific suggestions.

### Parameters

<ParamField path="action" type="enum" required>
  Which history view to return. "list" and "diagnose" read ComfyUI's execution history and take an optional `prompt_id`; "stats" and "suggest" read this server's own local generation-settings database and take `model_family` (plus `lora_hash`/`search`/`limit` for "suggest"). No action requires any other field. Options: `action:"list"`, `action:"diagnose"`, `action:"stats"`, `action:"suggest"`.
</ParamField>

<ParamField path="prompt_id" type="string">
  Actions "list" and "diagnose" — the prompt ID to look up (returned by enqueue\_workflow). For action:"list", if omitted, returns the most recent COMMITTED execution (chosen by ComfyUI's queue number, not dict order); immediately after a run finishes it can briefly lag by one until ComfyUI commits the new entry, so pass the prompt\_id from enqueue\_workflow to get that exact run, and prefer the run-finished event for naming a just-produced output. For action:"diagnose", omit to diagnose the most recent FAILED run — preferred over a newer successful one — falling back to the most recent run if nothing failed.
</ParamField>

<ParamField path="model_family" type="string">
  Actions "stats" and "suggest" — model-family key to scope to, e.g. 'sdxl', 'flux', 'qwen\_image', 'illustrious'.
</ParamField>

<ParamField path="lora_hash" type="string">
  action:"suggest" — AutoV2 hash (10 chars) of a specific LoRA to find settings for.
</ParamField>

<ParamField path="search" type="string">
  action:"suggest" — full-text search on model/LoRA filenames (e.g. 'copax', 'lightning').
</ParamField>

<ParamField path="limit" type="integer">
  action:"suggest" — max results (default 10).
</ParamField>

### Example

<Note>No worked example yet — the call below is a skeleton generated from the required parameters. Real examples live in `scripts/tool-doc-examples.ts`; contributions welcome.</Note>

```json theme={null}
{
  "tool": "get_history",
  "arguments": {
    "action": "list"
  }
}
```

***

## calculate

Evaluate a batch of math expressions exactly — no ComfyUI connection needed, so it works even in cloud mode or when ComfyUI is down. A safe, zero-dependency expression evaluator (no eval): numbers only, no strings/arrays/property access. Handy for the arithmetic agents get wrong token-by-token.

Each line is one expression. `name = expr` assigns a variable that persists into later lines. Lines are separated by newlines or semicolons ONLY — commas are argument separators (e.g. min(a, b)), never expression separators.

Operators: + - \* / // (floor div) % (modulo) \*\* (power, right-assoc), comparisons \< \<= > >= == != (return 1/0), unary minus. Constants: pi, e, tau. Functions: abs round min max pow sqrt floor ceil sin cos tan asin acos atan atan2 sinh cosh tanh exp log log10 log2 hypot radians degrees sign trunc clamp(x,lo,hi), plus seeded RNG rand() random() uniform(a,b) randint(a,b) (inclusive). Pass `seed` for reproducible RNG; it is echoed back when omitted.

Examples:
• SDXL-legal resolution from an aspect ratio, snapped to /64:
variables=\{ar: 1.5}; spec="w = floor(sqrt(1024*1024*ar)/64)*64\nh = floor(sqrt(1024*1024/ar)/64)*64"
• Reproducible seed batch (one 32-bit seed per line):
spec="randint(0, 2**32-1)\nrandint(0, 2**32-1)\nrandint(0, 2\*\*32-1)", seed=42
• CFG sweep:
spec="3 + 0*0.5\n3 + 1*0.5\n3 + 2*0.5\n3 + 3\*0.5"

### Parameters

<ParamField path="spec" type="string | string[]" required>
  Expressions to evaluate, separated by newlines/semicolons (string) or one per array item. `name = expr` assigns; assignments persist across subsequent lines. NOTE: comma is an argument separator (min(a,b)), NOT an expression separator.
</ParamField>

<ParamField path="variables" type="object">
  Initial variable environment, e.g. \{"w": 1024, "ar": 1.5}.
</ParamField>

<ParamField path="seed" type="integer">
  Seed for rand()/uniform(a,b)/randint(a,b). Same seed => identical sequence (mulberry32). Omit for a random seed (echoed in the result).
</ParamField>

### Example

<Note>No worked example yet — the call below is a skeleton generated from the required parameters. Real examples live in `scripts/tool-doc-examples.ts`; contributions welcome.</Note>

```json theme={null}
{
  "tool": "calculate",
  "arguments": {
    "spec": "<spec>"
  }
}
```

***

## batch

Run MANY ComfyUI workflows under one durable batch\_id. Driven by the `action` parameter:

* action:"submit" — Enqueue a batch. Provide EITHER `workflows` (array of API-format workflows) OR one `workflow` plus a `sweep` (array of flat input-override sets — each set produces one job, applied to every node that already has that input, like create\_workflow (action:"modify")). Reuses the enqueue\_workflow path (seeds re-randomized unless disable\_random\_seed). Returns \{ batch\_id, count, prompt\_ids }; the mapping is persisted to disk and stays valid across server restarts.
* action:"status" — Per-job status for `batch_id`: each prompt\_id's state (pending/running/done/error/unknown) plus rollup counts and all\_terminal. Same status source as queue (action:"status").
* action:"output" — Collected outputs for the batch's COMPLETED jobs: for each done prompt\_id, the raw ComfyUI history `outputs` (node id → images/videos/audio filenames, same data get\_history reports — feed filenames to get\_image action:"get"). Jobs still pending/running are listed with their state; errored jobs carry the error message. Safe to call before the batch finishes.
* action:"wait" — Block until every job is terminal (done or error) or `timeout_s` elapses, then return the same rollup as action:"status" plus timed\_out/waited\_s. Default timeout 300s, hard cap 600s — it can never hang; if timed\_out is true, call it again or poll action:"status".
  Batch ids are durable — they survive server restarts.

### Parameters

<ParamField path="action" type="enum" required>
  Which batch operation to perform. "submit" takes workflows | workflow+sweep; "status"/"output"/"wait" each require `batch_id` ("wait" also takes `timeout_s`). Options: `action:"submit"`, `action:"status"`, `action:"output"`, `action:"wait"`.
</ParamField>

<ParamField path="workflows" type="object[]">
  action:"submit" — array of ComfyUI workflows in API format (node ID -> \{class\_type, inputs}). Mutually exclusive with workflow+sweep.
</ParamField>

<ParamField path="workflow" type="object">
  action:"submit" — one base workflow in API format, used with `sweep`.
</ParamField>

<ParamField path="sweep" type="object[]">
  action:"submit" — param sweep: one job per override set, e.g. \[\{"cfg":6},\{"cfg":8,"steps":30}]. Each key is set on every node that already has that input.
</ParamField>

<ParamField path="disable_random_seed" type="boolean">
  action:"submit" — if true, do not randomize seed values (default randomizes per job).
</ParamField>

<ParamField path="batch_id" type="string">
  The batch\_id returned by action:"submit". Required for actions "status", "output" and "wait".
</ParamField>

<ParamField path="timeout_s" type="number">
  action:"wait" — max seconds to wait (default 300, hard cap 600).
</ParamField>

### Example

<Note>No worked example yet — the call below is a skeleton generated from the required parameters. Real examples live in `scripts/tool-doc-examples.ts`; contributions welcome.</Note>

```json theme={null}
{
  "tool": "batch",
  "arguments": {
    "action": "submit"
  }
}
```

***
