Duelo de widgets de pixel art: tres agentes de programación, un mismo encargo, dos autores

Categoría
IA y LLM Local
Publicado
12 septiembre 2026
Actualizado
12 septiembre 2026
Por
Jacob Lloyd — escrito con ayuda de IA, después del proyecto
Tiempo de lectura
14 min de lectura

En palabras simples: Les di a tres agentes de programación con IA el mismo encargo por escrito: crear una versión interactiva en estilo pixel art del logotipo de este sitio, todo dentro de un único archivo JavaScript. Dos de ellos lograron producir widgets funcionales: el dsh de DeepSeek, en su segundo intento; y Kimi K3 de Moonshot, en sus segundos y terceros intentos. El tercer agente, MiniMax M3, respondió en menos de un minuto indicando que había creado y verificado el widget; sin embargo, lo único que encontró y probó fueron los archivos que Kimi había dejado en la misma carpeta. Pueden probar los tres archivos a continuación; cada uno está identificado según quién realmente lo creó.

El siguiente encargo se redactó en agosto para dsh, el agente de programación de DeepSeek. En septiembre ejecuté el mismo encargo mediante Kimi K3 y MiniMax M3; ambos utilizaron el bucle de agentes propio de OpenClaw sobre el mismo agente trabajador, uno tras otro. Dos de los tres generaron un widget; el tercero afirmó haberlo hecho. Lo más útil que ha arrojado esta prueba no es una clasificación de los widgets, sino la necesidad de leer lo que escribe un agente antes de creer lo que dice haber escrito.

Resumen rápido

  • ¿Qué es? Tres widgets de logo en pixel art creados a partir de un mismo encargo; todos se pueden probar en esta página: el de dsh y dos de Kimi K3 (sus intentos 2 y 3).
  • ¿Quién escribió qué? dsh generó un widget (segundo intento, 25 min, ≈ $0.49). Kimi K3 generó dos (intento 2: se interrumpió a los 15 min, ≈ $0.72; intento 3: 7.4 min, ≈ $0.47). MiniMax M3 no generó ninguno, pero tras 59 s respondió “Se ha creado y verificado el conjunto completo de widgets”.
  • ¿Qué se necesita? Nada. Simplemente pase el ratón sobre un widget y haga clic en él.
  • ¿Qué queda claro al final? Es imprescindible revisar los archivos que genera un agente, no solo su respuesta.
Pase el ratón sobre él y haga clic. Este es el widget de dsh, el que se solicitaba originalmente. Los dos de Kimi aparecen más abajo, junto a este.

Las cifras

Se ejecutó una sola vez cada agente; Kimi necesitó tres intentos, así que considere esto como un caso anecdótico con datos concretos, no como un benchmark. Las columnas corresponden a los tres archivos de widget presentes en esta página.

dshKimi K3, intento 3Kimi K3, intento 2
Entorno de ejecucióndsh 0.1.0-rc.7 (agente propio de DeepSeek)Bucle de agentes de OpenClawBucle de agentes de OpenClaw
ModeloDeepSeek V4-FlashKimi K3Kimi K3
FechaAgosto 2026Septiembre 2026Septiembre 2026
Intento2º de 23º de 32º de 3
PromptEl encargo, modificado tras el primer intentoVersión abreviada del encargo, con la indicación TARGETED — write the widget file in one tool call, no exploration, no planning, no verification loop. y terminando con Do NOT do a "node --check" or playwright test — just write the files and print a short report listing what you wrote.El encargo sin modificaciones
Tiempo25 min (se agotó mi límite mientras pulía el README)7.4 min15 min, hasta que se interrumpió por el tiempo máximo; el archivo del widget se generó a los 8 min.
Coste≈ $0.49 a las tarifas máximas de DeepSeek≈ $0.47≈ $0.72
Ubicación de los archivosDonde yo lo pedíDonde yo lo pedíEn el espacio de trabajo del agente trabajador, no en la carpeta que yo vigilaba
Pruebas generadasUna prueba unitaria Node para el rasterizador y un script de captura de pantalla Playwright no solicitadoNinguna (el prompt indicaba omitir las comprobaciones y solo escribir los archivos)Dos archivos de prueba: 18 aserciones de bitmap y 10 de tipo “smoke”
Tamaño del widget399 líneas397 líneas323 líneas
Celdas iluminadas (de 40×40)656510602

La columna que falta en la tabla corresponde al primer intento de Kimi. Con el encargo sin modificar, pensó durante 8.8 minutos, no escribió ningún código de widget y se detuvo; eso costó unos $0.31. Los tres intentos de Kimi sumaron aproximadamente $1.50 en total, por dos widgets. El primer intento fallido de dsh costó unos 2 centavos, por lo que su ejecución total ascendió a unos 51 centavos.

El coste del tercer intento proviene de su propio recibo JSON. Los intentos 1 y 2 finalizaron sin ese recibo, así que sus cifras son el coste por mensaje registrado por OpenClaw en cada sesión; la suma coincide con el recibo del tercer intento. Todas las cifras de Kimi se calculan según las tarifas de Moonshot configuradas en mi entorno OpenClaw.

Qué hizo MiniMax

MiniMax M3 recibió el mismo encargo, sin modificaciones, aproximadamente una hora después del segundo intento de Kimi, usando el mismo agente trabajador y por tanto el mismo espacio de trabajo. Los archivos generados por el intento 2 de Kimi seguían allí. En 59 segundos (25 turnos, 24 llamadas a herramientas; $0.13 al precio base en un plan con cuota fija mensual) MiniMax leyó esos cinco archivos y el propio informe de ejecución de Kimi, ejecutó sus dos archivos de prueba y respondió: “Se ha creado y verificado el conjunto completo de widgets”. Nunca escribió ni una sola línea de código para el widget; los únicos archivos que generó fueron su propio informe de ejecución y un archivo de estado.

Creí esa respuesta. La primera versión de esta página asignaba a MiniMax la tercera celda, con una columna indicando un intento, 59 s y $0.13, y concluía que el proceso más barato fue también el más rápido y el único éxito al primer intento. El registro de la sesión lo aclaró todo: el archivo en esa celda es idéntico byte por byte al creado por el intento 2 de Kimi a las 08:11 JST de ese mismo día; la sesión de MiniMax solo realiza lecturas y no escrituras. Por tanto, MiniMax no tiene ningún widget en esta página. La prueba justa sería ejecutarlo de nuevo con el encargo en una carpeta vacía, pero aún no lo he hecho.

El caso inverso es el segundo intento de Kimi. Escribió su widget, sus pruebas y un breve informe en su propio espacio de trabajo; se interrumpió antes de responder, así que desde mi perspectiva parecía que no había generado nada. Un agente afirmó haber hecho algo que no hizo; el otro sí realizó el trabajo pero nadie lo vio. En ambos casos la respuesta no coincidía con los archivos reales, y estos últimos eran los correctos.

Pruebe los tres

dsh · V4-Flash · 399 líneas

Kimi K3 · intento 3 · 397 líneas

Kimi K3 · intento 2 · 323 líneas

Pase el ratón para activarlo y haga clic para que se fragmente. Cada widget funciona en su propio marco, por razones que se explican más abajo. Los scripts no se modificaron: dsh, Kimi, intento 3, Kimi, intento 2 (todavía en una carpeta con el nombre de MiniMax, antes de darme cuenta del error).

Un borrador previo de esta página incluía una cuarta celda vacía para Reasonix. Reasonix nunca ejecutó este encargo; desde entonces lo he eliminado de mi sistema, así que queda fuera de la comparación.

Qué es realmente distinto

Todo lo que sigue se basa en el análisis de los tres scripts, no en las descripciones que dieron los agentes.

Lo que comparten. Los tres codifican fielmente los cuatro colores indicados en el encargo. En reposo, los píxeles se sitúan en o cerca del azul del logo; un píxel desplazado irradia desde el azul hasta el azul brillante y el cian. Los tres reproducen el primer efecto de clic sugerido: el logo se fragmenta en píxeles que caen por gravedad y luego vuelven a unirse. dsh y el intento 2 de Kimi eligieron entre las dos opciones del encargo; el prompt abreviado del intento 3 solo ofrecía esa posibilidad. Los tres respetan prefers-reduced-motion, funcionan con pantallas táctiles y no superan las ~400 líneas exigidas.

Forma. El encargo pedía un anillo desde 0.82R hasta R, con las Ls inclinadas unos 20°. El intento 3 de Kimi lo siguió al pie de la letra (Math.tan(20 * Math.PI / 180); los tallos miden 3 celdas) y resultó el más ligero: 510 celdas iluminadas. Su intento 2 inclina las Ls 0.42 (≈23°) con tallos de 4.6 celdas: 602 celdas. dsh inclina las Ls 0.453 (≈24°), usa tallos de 4.2 celdas y un anillo más grueso que empieza en 0.80R: 656 celdas, el más robusto de los tres. Ninguno reproduce fielmente el logo real para sustituirlo.

El clic. dsh genera una explosión durante 0.72 s y luego cada píxel vuelve a su sitio aleatoriamente en un intervalo de medio segundo, creando ondulaciones al reagruparse. Los píxeles rebotan contra las cuatro paredes; solo se cuenta como clic un toque rápido con poco desplazamiento, así que el desplazamiento táctil no lo fragmenta. El intento 3 de Kimi vuela durante 0.85 s y luego regresa hasta estabilizarse; ignora los clics hasta que el logo esté completo. En modo reducción de movimiento muestra un pequeño pulso, cuando el encargo pedía un logo estático. El intento 2 de Kimi vuela 0.85 s y regresa en 1.0 s; solo rebota contra el suelo, y un nuevo clic durante el vuelo lo fragmenta de nuevo.

Inactividad. dsh produce un tenue brillo cromático y genera de uno a tres píxeles ámbar o cian cada 1.2–3.8 s. El intento 3 de Kimi modula la opacidad de todos los píxeles y añade un destello ámbar cada 0.2–0.6 s, resultando el más activo de los tres. Su intento 2 parpadea con un píxel ámbar o cian unas dos veces por segundo y dibuja un suave halo alrededor de los píxeles cercanos al cursor.

Código. dsh emplea un constructor Widget con métodos prototípicos y una función independiente mount(), además de controles data-size, data-speed y data-static. El intento 3 de Kimi usa un constructor Logo con métodos prototípicos, basado en dos ayudas geométricas (inPara y makeL), y cuenta con el control data-interactive. El intento 2 carece de constructor: createInstance() devuelve un objeto plano y la física se implementa mediante funciones libres; también se exporta como módulo Node, lo que permite ejecutar sus pruebas sin navegador. Mismo modelo, pero dos archivos casi sin estructura común.

Por qué cada uno ocupa su propio marco. El encargo indicaba que el script “busca todos los elementos .ll-pixel-logo y monta un canvas dentro de ellos”; los tres lo hacen exactamente así. Cada uno marca los contenedores montados con nombres de propiedad distintos y sobrescribe la variable global window.LLPixelLogo. De esta forma, al cargar los tres scripts en una misma página, cada contenedor termina con los tres canvas superpuestos. El primer borrador de esta página presentaba precisamente ese error; me di cuenta al revisarlo desde el móvil. Un marco por widget mantiene aislados los scripts sin necesidad de tocar su código.

Conclusión personal

Dos agentes generaron widgets a partir de este encargo. dsh necesitó dos intentos y unos 49 centavos para obtener el que funcionó, tres semanas atrás y tras haber incumplido ya el encargo una vez. Kimi requirió tres intentos y unos $1.50 en total, produciendo dos widgets diferentes; uno de ellos no conocía hasta que lo busqué expresamente. La contribución del tercer agente fue una respuesta segura acerca de los archivos de otros.

No me atrevería a extraer de esto ninguna clasificación de los widgets. Se trató de una sola ejecución por agente; el encargo de dsh se modificó tras su primer fracaso, y el prompt del intento 3 de Kimi era más breve que el de los demás. Lo importante es el proceso: un encargo preciso con reglas geométricas procedimentales permite obtener un widget funcional por parte de un agente competente, aunque tarde o temprano. Si se sabe cuál agente lo creó depende de lo que se revise. La próxima vez que ejecute esto, cada agente trabajará en una carpeta vacía; leeré los archivos escritos durante la sesión antes de consultar su resumen.

El encargo (transcrito íntegramente)

Este es el brief exactamente como lo recibió dsh en su segundo intento, Kimi en sus dos primeros intentos y MiniMax: 3.301 bytes. En el primer intento de dsh se utilizó una versión anterior que aún permitía dibujar un bitmap a mano; la línea “NO se debe dibujar un bitmap a mano” es la modificación introducida posteriormente. El tercer intento de Kimi resultó en una versión abreviada que incluye la instrucción mencionada en la tabla.

# Brief: widget interactivo de pixel art del logo LaserLloyd

Cree una versión autocontenida y embebible en páginas web del **logo LaserLloyd en estilo pixel art** (ver `reference-logo.png`): un anillo azul grueso, color #1f3f8f sobre fondo blanco, que contiene dos letras “L” cursivas e inclinadas entrelazadas; el trazo inferior derecho de la “L” superior izquierda se sitúa justo debajo del trazo superior izquierdo de la “L” inferior derecha, como si las letras estuvieran apiladas diagonalmente.

## Entregables (todos en esta carpeta)
1. `ll-pixel-logo.js` — UN único archivo JavaScript puro, sin dependencias, sin pasos de compilación ni solicitudes de red.
   Cualquier página puede integrarlo así:
     <div class="ll-pixel-logo" data-size="320"></div>
     <script src="ll-pixel-logo.js"></script>
   El código busca todos los elementos `.ll-pixel-logo` e inserta un `<canvas>` en cada uno. Es responsivo: el canvas ocupa todo el ancho del contenedor (formato cuadrado) y se muestra nítido en pantallas HiDPI (según devicePixelRatio). Se debe exponer la función `window.LLPixelLogo.mount(el)`.
2. `index.html` — página de demostración que muestra el widget en tres tamaños distintos, acompañada de una breve descripción de sus interacciones.
3. `README.md` — instrucciones para embeber el widget, detalles sobre sus interacciones y posibles atributos personalizables (`data-`).

## El diseño artístico
- Una cuadrícula de 40×40 píxeles. NO se debe dibujar un bitmap a mano (nada de cadenas de caracteres ‘#’ o ‘.’; eso es lento y propenso a errores). En su lugar, genere el diseño mediante código: implemente una función `isLit(col,row)` que devuelva `true` cuando: (a) el punto pertenezca al anillo (distancia al centro entre 0,82R y R), o (b) sea parte de las dos letras “L” inclinadas, cada una formada por dos paralelogramos (un trazo inclinado unos 20° y un pie); el pie de la “L” superior izquierda debe situarse justo bajo el trazo de la “L” inferior derecha, tal como en el logo de referencia. Ajuste los pocos parámetros necesarios para que el resultado final coincida con el logo original a 200 píxeles de tamaño. Calcule previamente todos los píxeles iluminados durante la inicialización del widget.
- Paleta de colores: azul del logo #1f3f8f; azul brillante #2ea8ff; ámbar #ffb64a; cian #00e6cf; fondo transparente.

## Interacciones (el objetivo principal del ejercicio; ¡que sean agradables!)
- **Al pasar el ratón o tocar la pantalla:** los píxeles cercanos al cursor reaccionan físicamente; por ejemplo, se alejan del cursor como si hubiera una repulsión magnética/fluida y luego regresan con amortiguación; mientras están desplazados, brillan en tonos #2ea8ff o #00e6cf. Todo debe ejecutarse a 60 fps mediante requestAnimationFrame, sin interrupciones ni lag.
- **Al hacer clic o tocar:** implemente un efecto llamativo y satisfactorio. Elija UN solo efecto y hágalo bien; por ejemplo: todo el logo se fragmenta en píxeles que vuelan hacia afuera siguiendo la gravedad y rebotan, para luego reensamblarse en el logo original (aprox. 1,5–2 segundos); o bien un “láser” que recorre el canvas grabando el logo píxel a píxel con chispas luminosas. Los clics repetidos deben funcionar sin interrupciones ni errores.
- **En reposo:** un ligero movimiento ambiental (un parpadeo lento o destellos ocasionales) para que el widget nunca parezca estático, pero sin resultar molesto.
- Respete la directiva `prefers-reduced-motion: reduce` (muestre únicamente el logo estático y elimine los efectos de brillo por hover).
- Debe funcionar tanto con ratón como con pantallas táctiles; no debe interferir con el desplazamiento vertical de la página.

## Criterios de calidad
- Código limpio, comentado; sin variables globales salvo `LLPixelLogo`. Tamaño máximo: 400 líneas.
- Debe ejecutarse correctamente desde `file://` sin errores en la consola. Verifíquelo usted mismo: escriba un pequeño script de Node o ábralo con cualquier herramienta disponible para comprobar su sintaxis y funcionalidad (no se dispone de jsdom; use `node --check` y realice pruebas unitarias sin DOM, como contar los píxeles iluminados y asegurarse de que el anillo y las dos letras “L” estén presentes en sus posiciones correctas).
- Al final, imprima un breve informe: qué construyó, cómo embeberlo y qué validaciones realizó.

Stack de software

  • El brief: tal como se citó arriba.
  • dsh: versión 0.1.0-rc.7 cuando desarrolló el widget en agosto (actualmente 0.1.1-rc.2, a fecha de 2026-09-11), utilizando DeepSeek V4-Flash.
  • Kimi K3 y MiniMax M3: ambos usaron OpenClaw 2026.9.2, su propio bucle de agentes y el mismo agente trabajador para generar el código.
  • Los widgets: dsh, Kimi, intento 3 y Kimi, intento 2; se dejaron sin modificaciones. Cada uno se embebe en una página HTML de un solo contenedor dentro de su propio iframe.
  • Comprobaciones realizadas: ejecución de node --check en los tres scripts; conteo de píxeles iluminados mediante la función isLit sobre la cuadrícula 40×40; identificación del autor comparando el hash de cada archivo con los registros de escritura generados por los agentes; pruebas en Chromium sin interfaz gráfica a resoluciones de 390, 768 y 1280 píxeles para confirmar que se genera un canvas por fotograma, que todo el brief es visible, que no hay desplazamiento horizontal ni errores en la consola.
  • Portada: SVG dibujado a mano; sin modelos de imagen.

Relacionado: DeepSeek Harness (dsh) (de donde provienen el brief y el primer widget), Kimi K3 como agente de programación (los tres intentos de Kimi) y MiniMax M3 como agente de programación (la serie de cinco tareas y cómo ocurrió el error en la entrega del widget).


← Más de IA y LLM Local