---
name: comfyui_extract_template
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: impure
signature: "def comfyui_extract_template(name: str, comfyui_python: str | None = None, to_api: bool = False, server: str = \"127.0.0.1:8188\") -> dict"
description: "Extrae el grafo de nodos de un workflow template oficial de ComfyUI por su template_id. Devuelve el grafo completo (formato UI: nodes/links), la lista de class_types que usa (aplanando subgrafos y descartando UUID de instancia), el formato, el bundle y los assets en disco. Opcionalmente (to_api=True) convierte el grafo UI a API format reutilizando comfyui_import_workflow_json (requiere un servidor ComfyUI vivo). Nombre inexistente -> error legible con sugerencias, sin traceback. Localiza el interprete de ComfyUI y usa su API oficial via subprocess. Impura: lee disco (+ red opcional si to_api)."
tags: [comfyui, ml, templates, workflow, extract]
uses_functions: ["comfyui_import_workflow_json_py_ml"]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
  - name: name
    desc: "template_id exacto del template (p.ej. 'sdxl_simple_example', 'image_sdxl'). Usa comfyui_list_templates para ver los nombres disponibles."
  - name: comfyui_python
    desc: "Ruta al interprete python de ComfyUI con el paquete comfyui-workflow-templates. None autodetecta (env COMFYUI_PYTHON, ~/ComfyUI/.venv/bin/python)."
  - name: to_api
    desc: "True intenta convertir el grafo UI a API format via comfyui_import_workflow_json (requiere servidor ComfyUI vivo en `server`). Si falla, el grafo UI se devuelve igualmente y el motivo va en api_error."
  - name: server
    desc: "host:port del servidor ComfyUI usado para la conversion to_api (default '127.0.0.1:8188')."
output: "dict {ok, name, format, class_types, has_subgraphs, n_nodes, graph, api_workflow, api_error, bundle, version, assets, error}. graph = dict del template (formato UI o API). class_types = lista ordenada de tipos de nodo reales. api_workflow = dict API si to_api tuvo exito, si no {}. Nunca lanza: nombre inexistente -> ok=False con error + sugerencias."
tested: true
tests:
  - "sin el paquete instalado -> ok=False con error que menciona comfyui-workflow-templates"
  - "el nombre pedido se preserva y el dict trae todas sus claves aun en fallo"
  - "golden (skip si no hay ComfyUI con el paquete): extrae un template real con graph + class_types no vacios"
  - "golden (skip si no hay ComfyUI con el paquete): nombre inexistente -> ok=False con error legible"
test_file_path: "python/functions/ml/tests/test_comfyui_extract_template.py"
file_path: "python/functions/ml/comfyui_extract_template.py"
---

## Ejemplo

```bash
# Lanzable directo (grafo slim + class_types de un template concreto):
python/.venv/bin/python3 python/functions/ml/comfyui_extract_template.py sdxl_simple_example

# Con conversion a API format (necesita ComfyUI corriendo en 127.0.0.1:8188):
python/.venv/bin/python3 python/functions/ml/comfyui_extract_template.py sdxl_simple_example --to-api
```

```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_extract_template import comfyui_extract_template

res = comfyui_extract_template("sdxl_simple_example")
print(res["format"], res["n_nodes"], "nodos")        # ui_graph 25 nodos
print(res["class_types"])                             # ['CheckpointLoaderSimple', 'KSamplerAdvanced', ...]
graph = res["graph"]                                  # dict cargable en la UI tal cual
```

## Cuando usarla

Cuando quieras reutilizar la estructura de nodos de un template oficial: cargar su
grafo en tu UI, usarlo de base para un workflow propio, o saber exactamente que
class_types encadena. Segundo paso del flujo listar (`comfyui_list_templates`) ->
extraer. Para encolar el resultado en `/prompt` usa `to_api=True` (o pasa el grafo por
`comfyui_import_workflow_json`).

## Gotchas

- El grafo viene en **formato UI** (nodes/links con posiciones), no en API format. La
  UI de ComfyUI lo entiende tal cual (cargalo o copia el dict); para `/prompt` hay que
  convertirlo a API format con `to_api=True`.
- `to_api=True` reutiliza `comfyui_import_workflow_json`, que necesita un **servidor
  ComfyUI vivo** para mapear los widgets a sus claves de input. Sin servidor, la
  extraccion del grafo UI sigue funcionando (ok=True) y el motivo del fallo de
  conversion va en `api_error` (no rompe). KISS: no se fuerza la conversion.
- Templates **subgraphed** (con `definitions.subgraphs`, `has_subgraphs=True`): la
  conversion a API NO expande el subgraph (limitacion de la normalizacion UI->API
  estandar), asi que `api_workflow` puede quedar con solo los nodos top-level. Para
  esos, cargar el grafo UI en la UI es lo fiable. `class_types` sí incluye los nodos
  reales de dentro del subgraph.
- Nombre inexistente -> `ok=False` con `error` legible y sugerencias por substring (o
  difflib). No lanza traceback.
- El paquete vive en el venv de ComfyUI; si no se encuentra el interprete o el paquete,
  `ok=False` indicando `pip install comfyui-workflow-templates`.
