20 DE ABRIL DE 2026
1000 ejecuciones después: qué aprendimos corriendo LLMs locales con tareas reales
Temperatura, system prompt, retry loops, thinking visible y tamaño de modelo: una radiografía práctica de lo que ya se puede automatizar en una RTX 3090 sin depender de la nube.
Durante los últimos días corrimos un benchmark interno de 1000 ejecuciones sobre 10 modelos locales, 5 temperaturas, 4 contextos de system prompt y 5 tareas de terminal que mezclan scaffolding, edición, git y recuperación ante fallos. No queríamos una prueba de “chat bonito”; queríamos ver qué tan cerca estamos de tener agentes locales útiles para trabajo real.
El resultado más importante no es que ya existan modelos muy buenos. Lo interesante es que hay palancas pequeñas que cambian mucho la confiabilidad: una temperatura ligeramente distinta, un prompt menos verboso, un aviso explícito de que el modelo está repitiendo el mismo comando, o una mejor instrucción para no detenerse en el primer fallo.
Lo que medimos realmente
Las tareas fueron deliberadamente terrenales: crear una app de Vite, mutar archivos, encadenar git, recuperar un archivo faltante y resolver un merge conflict. En otras palabras: trabajo de terminal con fricción real, no puzzles de benchmark diseñados para caber en una sola respuesta bonita.
Además separamos dos métricas que suelen mezclarse:
- DONE: el modelo terminó su loop de herramientas con salida final y último comando exitoso.
- Validated: el estado del filesystem o del repositorio realmente coincide con lo que la tarea pedía.
Esa diferencia importa porque varios modelos “dicen haber terminado” antes de dejar el sistema en el estado correcto. Ahí es donde un benchmark deja de ser ornamental y empieza a servir.
Resumen duro: la tarea de crear una app (`P1`) ya está prácticamente resuelta por casi todos. La de merge conflict (`R4`) sigue siendo el cuello de botella. Esa sola observación define qué tan cerca estamos de agentes locales robustos: crear cosas es fácil; recuperarse bien de estados intermedios sigue siendo difícil.
1. La temperatura no es cosmética
En conversación general es común pensar que la temperatura solo afecta “creatividad”. En tool use eso es una simplificación peligrosa. En nuestro run, la mejor temperatura global fue 0.7 con 147/200 ejecuciones validadas. Le siguieron 0.3 con 142/200 y 0.5 con 141/200. Los extremos perdieron terreno: 0.1 quedó en 135/200 y 0.9 en 137/200.
La lectura útil es esta: subir la temperatura un poco ayudó a destrabar tool use, pero subirla demasiado volvió al agente más errático. La zona media-alta generó más capacidad de corrección sin caer tanto en exploración inútil. Esto es especialmente visible en tareas de recuperación (`R1`) y edición (`P2`), donde un poco más de variación favorece probar una segunda hipótesis cuando la primera falla.
No todas las tareas reaccionan igual. `P1` está saturada en cualquier temperatura razonable; `R4` sigue siendo difícil en todas. Eso también es valioso: la temperatura mejora la ejecución donde existe ambigüedad operativa, pero no convierte una tarea estructuralmente compleja en una tarea fácil.
2. Más contexto no siempre es mejor contexto
Probamos cuatro variantes de system prompt: Generic Assistant, Minimal Tool Use, Structured CLI y Machine Context Rich. La intuición común diría que más detalles de máquina, rutas, restricciones y consejos deberían ayudar. En la práctica, no necesariamente.
| Contexto | Validated | DONE | Think avg |
|---|---|---|---|
| Minimal Tool Use | 185 / 250 | 205 / 250 | 114 |
| Generic Assistant | 182 / 250 | 202 / 250 | 117 |
| Structured CLI | 172 / 250 | 198 / 250 | 148 |
| Machine Context Rich | 163 / 250 | 195 / 250 | 176 |
Esto no significa que el contexto de máquina sea inútil. Significa algo más interesante: el contexto debe entrar cuando de verdad reduce incertidumbre operacional. Si lo conviertes en ruido de onboarding, algunos modelos lo consumen como si fuera parte del problema a razonar, no como una ayuda táctica para ejecutar mejor.
Hay un principio práctico aquí: menos narrativa, más affordance. Los prompts que mejor funcionaron fueron los que empujaron a usar la herramienta, observar la salida y continuar iterando. No los que se parecían a una especificación extensa.
3. Los modelos no “piensan” igual, y a veces ni siquiera lo muestran
También medimos reasoning_tokens, pero hay que leer esa métrica con cuidado: en algunos modelos vale cero porque no exponen thinking a través del adapter, no porque mágicamente resuelvan todo sin computación intermedia. Aun así, compararlos sigue siendo útil para detectar dos perfiles muy distintos:
- Modelos de alta calidad con thinking visible moderado, como qwen3.5-35b-a3b (94/100 validados, 107.7 think avg).
- Modelos con mucha calidad absoluta pero más thinking expuesto, como qwen3.5-27b (98/100, 190.1 think avg) y qwen3.6-35b-a3b (95/100, 169.4).
- Modelos eficientes con baja o nula exposición de thinking, como gemma-4-31b-it (80/100) y qwen3.5-9b (75/100).
Hay una lección importante aquí para quienes evalúan agents: “pensar más” no es automáticamente mejor. En varios casos, más reasoning visible vino acompañado de más latencia y más repeticiones, no de mejor estado final. La meta no es forzar cadenas de pensamiento cada vez más largas; la meta es cerrar mejor el loop entre error observado, hipótesis nueva y siguiente comando.
4. Qué capacidad real podemos aspirar a correr en local
La foto que deja este benchmark es mucho más optimista que la intuición típica de hace un año. En una sola 3090 ya estamos viendo tres niveles de capacidad bien diferenciados:
- 4B-9B: útiles para scaffolding y tareas lineales, pero todavía frágiles en recuperación y git con estados intermedios.
- 20B-31B: ya son agentes operativos en muchos flujos simples y medianos, especialmente si el prompt reduce ruido y el runtime da feedback explícito.
- 27B-35B: entran a una zona donde ya puedes pedir tareas multi-step con una expectativa realista de éxito, siempre que el loop de herramientas esté bien diseñado.
Eso cambia completamente la conversación sobre AI local. Ya no se trata solo de privacidad o costo por token. Se trata de que sí podemos aspirar a automatización práctica sin salir del equipo, siempre que dejemos de pensar en el modelo como un oráculo y empecemos a diseñar mejor el entorno que lo rodea.
La evidencia fuerte está en las tareas mismas. `P1` quedó prácticamente resuelta. `P3` y `R1` ya están en una zona útil. `R4` sigue siendo dura, pero justo por eso es una buena métrica de frontera: marca el punto donde el agente tiene que entender estado, no solo emitir comandos correctos sueltos.
5. Las ayudas pequeñas sí mueven la aguja
Una parte del aprendizaje no vino de los modelos, sino de las pequeñas correcciones que hicimos al harness:
- Separar DONE de validated para dejar de premiar respuestas bonitas con estado final incorrecto.
- Mostrar el número de iteración y el límite total del loop, para que el modelo sienta la presión operativa.
- Marcar retakes: si el agente repetía exactamente el mismo comando, el runtime agregaba
[RETAKE] Same command sent before. Try a different approach.. - Dar errores de shell enriquecidos con cwd final, exit code y segmentos ejecutados.
- Diseñar tareas de recovery donde el siguiente paso correcto no es insistir, sino inspeccionar qué existe antes de reintentar.
Ese último punto es central. Un agent reactivo no es el que nunca falla. Es el que lee el fallo, cambia de hipótesis y ajusta su siguiente acción. En local, donde todo corre en una sandbox controlada, esas ayudas son baratas y muy rentables.
Lo que mejora a un agente no siempre es un modelo más grande. A veces es simplemente un runtime que le deja claro cuándo está insistiendo a ciegas.
6. Lo más revelador: hay que diseñar para iteración, no para acierto a la primera
Muchos flujos de agent design todavía están obsesionados con el “one shot correct answer”. En terminal eso es una mala abstracción. El comportamiento verdaderamente útil es otro: avanzar, verificar, corregir, continuar. Por eso el mejor prompt agregado no fue el más completo, sino el que mejor empujó al modelo a usar la herramienta y seguir iterando.
Si quieres mejores agentes locales, el camino no es solo buscar más parámetros. También pasa por:
- hacer visibles los estados intermedios correctos,
- castigar repeticiones inútiles,
- encarecer el estancamiento y abaratar la inspección,
- enseñar al agente a verificar después de escribir, mover o mergear.
Cuando haces eso, incluso modelos medianos empiezan a comportarse mejor. Y cuando además eliges bien temperatura y contexto, la diferencia ya no es marginal: se convierte en una mejora material de confiabilidad.
Qué me llevaría a producción hoy
Si mañana tuviera que diseñar el siguiente OpenCode, Claude Code o cualquier agent local orientado a trabajo real, no empezaría preguntando “cuál modelo tiene más benchmark points”. Empezaría por una pregunta más útil: qué hábitos operativos quiero inducir en el agente. Lo que vimos aquí sirve para estos modelos, pero también se traslada bastante bien al trabajo diario con agents en general.
Estas serían mis reglas base de arquitectura:
- Optimizar para bucles, no para respuestas únicas. El runtime debe asumir que el agente avanzará en varias iteraciones y ayudarlo a corregirse rápido.
- Usar temperatura media como baseline. En este benchmark 0.7 fue mejor punto de partida que 0.1; suficiente flexibilidad para explorar, sin tanto ruido como 0.9.
- Preferir prompts cortos, accionables y con affordances claras. El mejor contexto fue el que empujó a usar herramientas, no el que intentó explicarlo todo.
- Separar éxito narrativo de éxito operativo. El agent puede sonar convincente y aun así dejar el repo roto; por eso la validación del estado final debe ser métrica principal.
- Instrumentar el runtime para enseñar buenos reflejos: cwd visible, número de iteración, último exit code y avisos cuando repite el mismo comando.
- Diseñar el set de pruebas alrededor de recovery. Crear archivos o scaffolds ya no es suficiente; hay que medir qué hace el agente cuando algo falla a mitad del camino.
- Escoger el modelo según el tipo de agente. Para agentes serios multi-step hoy la zona útil empieza alrededor de 20B-35B; los modelos más pequeños siguen siendo buenos copilotos de tareas lineales.
La implicación práctica es potente: una parte importante de la diferencia entre un agent torpe y uno útil no está en el peso del modelo, sino en cómo está diseñado el bucle de ejecución. Si el sistema premia inspeccionar, verificar y ajustar, el modelo sube de nivel. Si el sistema solo le pide “resuelve esto” y luego se sorprende cuando se atasca, el problema es tanto del harness como del modelo.
Y eso es justo lo interesante para cualquiera construyendo agentes hoy: hay mejoras transferibles. Los hints de retry, el feedback de retake, las verificaciones baratas después de acciones importantes y la validación fuerte del estado final son patrones que sirven más allá de este benchmark concreto.
La invitación correcta
La conclusión más útil de este benchmark no es “ya hay un modelo ganador” ni “ya podemos reemplazar todo con agentes”. La conclusión valiosa es otra: ya existe suficiente capacidad local para construir sistemas más ambiciosos, siempre que los diseñemos bien.
Eso implica experimentar en serio. No solo comparar prompts. También construir herramientas mejores, crear suites que castiguen el estancamiento, dar feedback útil cuando un comando falla, medir cómo se recupera un agente y empujarlo a ser más reactivo que ceremonial. En otras palabras: dejar de tratar al modelo como caja negra y empezar a tratar al agent runtime como producto.
Si alguien está armando hoy el siguiente agent de terminal, el siguiente IDE assistant o el siguiente entorno tipo OpenCode, yo rescataría esta idea central: el objetivo no es que el modelo acierte a la primera; el objetivo es que aprenda a iterar bien bajo restricciones reales. Ahí es donde empieza a aparecer algo útil para el día a día.
Cuando logras eso, el modelo deja de ser una demo aislada. Se convierte en una pieza operativa. Y en local, además, esa pieza puede ser rápida, privada, barata y sorprendentemente capaz.