🎨 De fotos crudas a anuncios editables: motor multi-agente en n8n
Cómo construí Agent1 para Dataverse Solutions: agentes de visión, geometría determinista y un compilador DrawingML sin dependencias que genera PPTX editables.
El diseño generativo para publicidad suele obligar a elegir mal. Los modelos de difusión entregan una imagen bonita que nadie puede editar, así que un error en el titular obliga a generar todo otra vez. Las herramientas de plantillas entregan texto editable, pero pegan cajas rígidas sobre la foto sin saber qué hay en ella.
En septiembre de 2026 construí Agent1 para Dataverse Solutions y Hoteles Lavid. Recibe fotos crudas de hoteles de lujo y conciertos masivos y devuelve carteles publicitarios como archivos PowerPoint (ECMA-376) que un equipo de marketing puede abrir en Canva, Google Slides o Keynote y editar capa por capa. Cada cartel incluye además una previsualización HD fiel al píxel.
🤖 Caso de Estudio y Especificación de Arquitectura:
Explora el desglose completo del sistema, flujo de datos y benchmarks en la página del proyecto Agent1.
💥 1. Dónde se rompía la primera versión
Las primeras iteraciones seguían el patrón habitual de pedirle a un LLM que eligiera un cuadrante o una plantilla. Cuatro fallos aparecían una y otra vez:
- Sujetos tapados. Las tarjetas de texto caían encima de la cama, los muebles o el artista en escena.
- Texto ilegible. Tipografía clara sobre cielos brillantes, incumpliendo el contraste WCAG 2.1.
- Saltos de línea rotos. Titulares escritos sin noción del tamaño físico de la caja donde debían caber.
- Archivos rechazados. Paquetes
.pptxque Canva o Google Slides marcaban como corruptos por un orden XML fuera del estándar o timestamps ZIP inválidos.
Los cuatro tienen la misma causa raíz. Le estábamos pidiendo al modelo que hiciera matemáticas.
📐 2. Una regla: si se puede calcular, el LLM no lo toca
Organicé el sistema alrededor de un único invariante. La geometría espacial, la luminancia, las colisiones entre cajas y el empaquetado binario se calculan con código determinista. Los modelos se encargan de lo que hacen bien, que es ver la foto y escribir el texto.
Cada traspaso entre etapas es un contrato JSON Schema validado con Ajv:
| Contrato | Lo produce | Qué contiene |
|---|---|---|
VisionGroundingOutput |
Agente de visión | Cajas de exclusión normalizadas de 0 a 1000, sujetos principales y secundarios, perfil de luz |
ArtDirectorBlueprint |
Dirección de arte | Coordenadas en EMUs, sistema de color, paradas de opacidad del scrim, presupuestos de caracteres |
CreativeCopyPack |
Agente de copy | Titulares y textos anclados al brief, dentro de límites de longitud por formato |
QualityAuditResult |
Crítico determinista | Puntaje de auditoría y directivas correctivas estructuradas |
La etapa de visión corre sobre GPT-4o o Qwen 2.5 VL 72B, y la de copy sobre GPT-4o o Claude 3.7 Sonnet. Si una salida no cumple su esquema, el pipeline se detiene en esa etapa en lugar de pasar datos defectuosos hacia adelante.
📦 3. Encontrar espacio libre con un solver de Rectángulo Máximo Vacío
Elegir entre plantillas prefabricadas era el origen de los sujetos tapados, así que lo reemplacé por un nodo en Node.js puro que ejecuta el algoritmo Maximal Empty Rectangle (MER). No hace llamadas a modelos y no agrega latencia medible.
- Toma las cajas
primary_focusdel contrato de visión y proyecta cortes ortogonales sobre un lienzo normalizado de 1000×1000. - Evalúa cada celda libre de colisiones y extrae los rectángulos vacíos más grandes para las zonas de encabezado y pie.
- La etapa de composición apila la tipografía en un flujo vertical acumulativo (cuerpo, luego CTA, luego pie). Cuando la pila cruzaría el margen de seguridad, todo el bloque sube, y con eso desaparecieron las colisiones entre el botón CTA y el pie de página.
⚙️ 4. Escribir un compilador PPTX desde cero
n8n ejecuta el código en un sandbox, y ahí no había lugar para librerías pesadas de documentos. Así que escribí un compilador OpenXML/DrawingML sobre el Buffer nativo de Node.js.
- Empaquetado ZIP en memoria. Construyo a mano las cabeceras de archivo local, el directorio central y el registro de fin de directorio, con una tabla CRC32 en memoria. Escribir timestamps DOS válidos resolvió las excepciones de fecha que lanzaban Google Slides y Canva al importar.
- Orden estricto ECMA-376. El parser de Canva exige un orden de nodos dentro de las propiedades de texto, metadatos Dublin Core, una parte de tema y matrices de transformación explícitas en los grupos de formas. Cumplir eso es lo que desbloquea todas las capas al importar.
- Seis capas vectoriales. El compilador lee las dimensiones reales de la imagen desde los bytes de cabecera JPEG/PNG, calcula recortes proporcionales y agrega un sangrado de 70,000 EMUs sobre un fondo maestro oscuro para que no aparezcan bordes blancos subpíxel. Los scrims con degradados de varias paradas y una sombra suave de 360° mantienen el texto legible sobre fotos brillantes.
🛡️ 5. Dos compuertas de calidad antes de entregar
- Crítico determinista. Calcula la luminancia relativa CIE sRGB para exigir un contraste WCAG 2.1 de al menos 4.5:1, ejecuta pruebas de intersección 2D AABB para que ninguna caja de texto toque un sujeto principal, impone un piso tipográfico de 24 puntos y bloquea precios o fechas que no estaban en el brief.
- Doble salida con bucle de QA visual. El flujo se bifurca en paralelo. Una rama compila el
.pptxeditable. La otra renderiza una previsualización HTML5/CSS3 en HD con Chromium headless vía Puppeteer, con fallback local en PHP GD. Un crítico visual inspecciona el render y puede pedir un ajuste geométrico acotado. Un techo duro de iteraciones con triple redundancia hace imposibles los bucles infinitos.
Los assets se guardan en Cloudflare R2 con firma SigV4, el estado vive en PostgreSQL y un editor human-in-the-loop permite al equipo aprobar o retocar cada cartel.
💻 6. Tratar los workflows como código
Las herramientas de flujos visuales son fáciles de empezar y difíciles de mantener. Agregué una CLI local (bundle, extract, validate, test, deploy) que descompila cada flujo de n8n en módulos JavaScript atómicos versionados en Git, valida esquemas y contratos sin conexión y despliega mediante la API REST de n8n.
💡 Lo que me llevo
La parte más confiable de un pipeline de IA es la que no usa IA. Contratos en cada frontera y código determinista para todo lo medible convirtieron una demo que funcionaba con fotos buenas en un sistema que aguanta las malas.