---
name: comfyui_build_seamless_tile_workflow
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: pure
signature: "def comfyui_build_seamless_tile_workflow(positive: str, negative: str = \"\", *, ckpt_name: str = \"IMG_dreamshaper_8.safetensors\", tiling: str = \"enable\", copy_model: str = \"Make a copy\", circular_vae: bool = True, material_lora: str | None = None, lora_strength: float = 1.0, steps: int = 20, cfg: float = 7.0, width: int = 512, height: int = 512, seed: int = 0, sampler_name: str = \"euler\", scheduler: str = \"normal\", filename_prefix: str = \"seamless\") -> dict"
description: "Construye el dict (API format) de un workflow ComfyUI de textura SEAMLESS (tileable) usando el custom node spinagon/ComfyUI-seamless-tiling: inserta SeamlessTile (Conv2d circular) entre la fuente MODEL y el KSampler, y CircularVAEDecode en lugar de VAEDecode. Compone comfyui_build_txt2img_workflow (+ comfyui_inject_lora opcional). Pura, sin red ni I/O. class_types verificados contra /object_info."
tags: [comfyui, ml, gamedev-2d, seamless, tile, texture, workflow, stable-diffusion]
uses_functions: [comfyui_build_txt2img_workflow_py_ml, comfyui_inject_lora_py_ml]
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
params:
  - name: positive
    desc: "Prompt de la textura (ej. 'seamless grass texture, top down'). No puede estar vacio."
  - name: negative
    desc: "Prompt negativo (ej. 'seam, border, frame')."
  - name: ckpt_name
    desc: "Checkpoint. Default 'IMG_dreamshaper_8.safetensors' (SD1.5 holgado en 8GB; el seamless cuesta ~0 VRAM). keyword-only."
  - name: tiling
    desc: "Eje de tileado: 'enable' (ambos), 'x_only' (horizontal, muros), 'y_only' (vertical), 'disable'. Un solo widget. keyword-only."
  - name: copy_model
    desc: "'Make a copy' (recomendado, no contamina el modelo cacheado del server compartido) o 'Modify in place'. keyword-only."
  - name: circular_vae
    desc: "Si True reemplaza VAEDecode por CircularVAEDecode (decode tambien circular, sin color-bleeding). keyword-only."
  - name: material_lora
    desc: "LoRA de material/estilo opcional a inyectar antes del SeamlessTile (ej. piedra/madera). None = sin LoRA. keyword-only."
  - name: lora_strength
    desc: "Fuerza del material_lora sobre model y clip. keyword-only."
  - name: steps
    desc: "Pasos del KSampler. keyword-only."
  - name: cfg
    desc: "CFG del KSampler. keyword-only."
  - name: width
    desc: "Ancho en px (multiplo de 8). keyword-only."
  - name: height
    desc: "Alto en px (multiplo de 8). keyword-only."
  - name: seed
    desc: "Semilla del KSampler. keyword-only."
  - name: sampler_name
    desc: "Sampler del KSampler. keyword-only."
  - name: scheduler
    desc: "Scheduler del KSampler. keyword-only."
  - name: filename_prefix
    desc: "Prefijo del PNG en output/. keyword-only."
output: "dict en API format listo para comfyui_submit_workflow: txt2img base (+ LoRA opcional) con un SeamlessTile entre la fuente MODEL y el KSampler, y CircularVAEDecode (si circular_vae) en lugar de VAEDecode."
tested: true
tests: ["golden: SeamlessTile insertado, KSampler.model -> SeamlessTile, CircularVAEDecode reemplaza VAEDecode, SeamlessTile.model -> checkpoint", "edge tiling='x_only' propagado a SeamlessTile y CircularVAEDecode", "edge circular_vae=False conserva VAEDecode", "edge material_lora: SeamlessTile.model -> LoRA", "error positive vacio / tiling invalido / copy_model invalido -> ValueError", "determinismo"]
test_file_path: "python/functions/ml/comfyui_build_seamless_tile_workflow_test.py"
file_path: "python/functions/ml/comfyui_build_seamless_tile_workflow.py"
---

## Ejemplo

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

wf = comfyui_build_seamless_tile_workflow(
    "seamless mossy stone wall texture, top down, game tile",
    negative="seam, border, frame, watermark",
    tiling="enable",      # 'x_only' para muros/cielos
    seed=7,
)
# -> comfyui_submit_workflow + comfyui_wait_result + comfyui_fetch_output_image
# Verificar costura: generar y montar 3x3 (o nodo OffsetImage 50/50); si aparece
# costura en el centro, no es seamless.
```

O lanzable directo con: `./fn run comfyui_build_seamless_tile_workflow` (imprime el JSON del workflow de ejemplo).

## Cuando usarla

Cuando necesites una textura tileable para el motor (suelos, muros, fondos
repetibles, terrenos). El modo `x_only` para superficies que solo tilean en
horizontal (muros, cielos). Combínala con un `material_lora` para texturas de
material concreto (piedra, madera, metal). Para verificar que tilea de verdad,
usa el check objetivo (montaje 3×3 / `OffsetImage` 50/50), no "se ve bien".

## Gotchas

- **Requiere el custom node `spinagon/ComfyUI-seamless-tiling` instalado** (ya lo
  está: `SeamlessTile`, `CircularVAEDecode`, `MakeCircularVAE`, `OffsetImage` en
  /object_info). Sin él, HTTP 400 al enviar.
- **class_type `SeamlessTile` (sin espacio)**, NO el display name `"Seamless Tile"`.
- **`SeamlessTile` va SIEMPRE entre el checkpoint/LoRAs y el KSampler**. Si fuese
  después, no tilearía (parchea las Conv2d del UNet antes del sampling).
- **`copy_model="Make a copy"` por defecto** porque el server es compartido
  (vídeo/3D): `Modify in place` contaminaría el checkpoint cacheado en memoria.
- Coste VRAM del seamless ≈ 0 (model-level): cabe sobre cualquier base en 8GB.
- Función pura: no valida contra el server.
