<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Guillermo Leyendeker</title>
    <description>The latest articles on DEV Community by Guillermo Leyendeker (@gleyendeker).</description>
    <link>https://dev.to/gleyendeker</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4076418%2F91162074-74e5-4be3-b493-4c97fd80ca29.jpg</url>
      <title>DEV Community: Guillermo Leyendeker</title>
      <link>https://dev.to/gleyendeker</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gleyendeker"/>
    <language>en</language>
    <item>
      <title>Le pedí al sistema que se mejorara solo: junté 1.771 incidentes y 13 propuestas</title>
      <dc:creator>Guillermo Leyendeker</dc:creator>
      <pubDate>Mon, 31 Aug 2026 12:30:30 +0000</pubDate>
      <link>https://dev.to/gleyendeker/le-pedi-al-sistema-que-se-mejorara-solo-junte-1771-incidentes-y-13-propuestas-3nnm</link>
      <guid>https://dev.to/gleyendeker/le-pedi-al-sistema-que-se-mejorara-solo-junte-1771-incidentes-y-13-propuestas-3nnm</guid>
      <description>&lt;p&gt;La segunda semana de mayo tenía sobre la mesa una pila de reportes de incidentes. Cada vez que el sistema se rendía con una tarea, dejaba escrito qué había intentado y por qué había fallado. Eran datos estructurados, acumulándose solos.&lt;/p&gt;

&lt;p&gt;Y ahí apareció una idea que, si trabajás con agentes, seguro se te cruzó alguna vez: &lt;strong&gt;si el sistema registra sus propias fallas, debería poder leer los patrones y proponer arreglos a sus propias instrucciones&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;La construí. Funciona. Y prácticamente no sirvió para nada. Esta entrega es sobre por qué.&lt;/p&gt;

&lt;h2&gt;El caso que originó la idea&lt;/h2&gt;

&lt;p&gt;No fue una idea abstracta: salió de un problema concreto y repetido.&lt;/p&gt;

&lt;p&gt;Una de las habilidades del sistema tenía la costumbre de terminar sus corridas con una pregunta. Algo del estilo "¿querés que continúe con la siguiente parte?". Para el orquestador, una corrida que termina esperando input es una corrida trabada: abortaba la secuencia entera.&lt;/p&gt;

&lt;p&gt;Lo arreglé a mano, editando las instrucciones de esa habilidad. Y mientras lo hacía pensé lo obvio: este patrón está registrado. El sistema sabe que esta habilidad falló por este motivo, varias veces. ¿Por qué tengo que ser yo el que lo detecte?&lt;/p&gt;

&lt;p&gt;El objetivo quedó escrito así: reemplazar el ciclo &lt;em&gt;humano detecta, humano edita, humano commitea&lt;/em&gt; por &lt;em&gt;el sistema detecta, propone un parche, el humano aprueba con un click&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;La restricción que puse desde el día uno&lt;/h2&gt;

&lt;p&gt;Antes de escribir una línea, decidí algo que hoy sigo considerando la mejor decisión de todo el subsistema: &lt;strong&gt;la rutina nunca edita archivos ni commitea por su cuenta&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Su salida no es un cambio, es una &lt;em&gt;propuesta&lt;/em&gt;: el diff más el razonamiento de por qué. Se guarda en la base de datos y espera. Un humano la aprueba y ahí sí se aplica, o la rechaza y queda archivada.&lt;/p&gt;

&lt;p&gt;La tentación de saltearse eso es fuerte, porque la aprobación manual es justamente el cuello de botella que querés eliminar. Pero un sistema que modifica sus propias instrucciones sin supervisión no tiene ningún freno: si el criterio con el que evalúa está mal, cada iteración lo empeora, y no hay nada afuera que lo detecte.&lt;/p&gt;

&lt;h2&gt;Cuatro fases, todas implementadas&lt;/h2&gt;

&lt;p&gt;El diseño quedó en cuatro partes, y las cuatro están funcionando:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Una &lt;strong&gt;tabla unificada de incidentes&lt;/strong&gt;, que consolida señales que antes vivían desperdigadas: rendiciones del orquestador, habilidades que se traban esperando input, chequeos previos que fallan.&lt;/li&gt;
  &lt;li&gt;Una &lt;strong&gt;detección de patrones recurrentes&lt;/strong&gt;: agrupa por habilidad y motivo, y marca los que aparecen tres veces o más en siete días.&lt;/li&gt;
  &lt;li&gt;La &lt;strong&gt;rutina que propone el parche&lt;/strong&gt;, que decide si el arreglo va en las instrucciones de la habilidad o en el código, calcula el diff y lo persiste.&lt;/li&gt;
  &lt;li&gt;La &lt;strong&gt;interfaz de aprobación&lt;/strong&gt;, con un límite de 24 horas para no reproponer lo mismo una y otra vez.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nada de esto está roto. Todo corre.&lt;/p&gt;

&lt;h2&gt;Los números, tres meses después&lt;/h2&gt;

&lt;p&gt;Cuando fui a medir el resultado, esto es lo que encontré:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;1.901 incidentes registrados&lt;/strong&gt; en total.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;1.771 de ellos todavía abiertos&lt;/strong&gt;, sin procesar.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;13 propuestas&lt;/strong&gt; generadas en toda la historia del sistema. Siete aprobadas, seis rechazadas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trece. En tres meses, con casi dos mil incidentes de materia prima.&lt;/p&gt;

&lt;p&gt;Y lo que más molesta es que los incidentes más frecuentes son exactamente los que uno querría convertir en reglas. En catorce días: &lt;strong&gt;351 lecturas repetidas del mismo archivo&lt;/strong&gt;, &lt;strong&gt;154 búsquedas que no encontraron nada&lt;/strong&gt; y &lt;strong&gt;151 comandos fallidos&lt;/strong&gt;. Todos patrones accionables. Todos ahí, sin procesar.&lt;/p&gt;

&lt;h2&gt;Dónde falló, que no es donde uno esperaría&lt;/h2&gt;

&lt;p&gt;Mi primera reacción fue pensar que el modelo no estaba a la altura de la tarea. Es la explicación cómoda, y estaba equivocada.&lt;/p&gt;

&lt;p&gt;El loop no falla en la parte inteligente. Falla en la cañería. Las hipótesis que tengo abiertas —y que todavía no terminé de descartar— son tres, y ninguna tiene que ver con la capacidad del modelo:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Que la rutina de propuestas casi no se esté disparando, por cómo quedó programada su ejecución.&lt;/li&gt;
  &lt;li&gt;Que la vista de patrones recurrentes no esté agrupando bien, y por eso no encuentre nada que reportar.&lt;/li&gt;
  &lt;li&gt;Que el umbral de tres ocurrencias en siete días sea inalcanzable, no porque los patrones no se repitan, sino porque hay tanto ruido de fondo que los casos reales quedan diluidos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esa última hipótesis es la que más me interesa, porque implica que el problema no es de detección sino de &lt;strong&gt;calidad de la señal&lt;/strong&gt;. Si el detector de ineficiencias genera falsos positivos a gran escala, no importa cuán bueno sea lo que venga después: le estás pidiendo que encuentre patrones en un montón de ruido.&lt;/p&gt;

&lt;p&gt;Por eso el próximo paso no es mejorar la rutina que propone parches. Es hacer un triage de los 1.771 incidentes abiertos y responder algo más básico: &lt;strong&gt;cuántos son señal real y cuántos son ruido del propio detector&lt;/strong&gt;. Si el grueso es ruido, hay que endurecer la detección antes de pedirle propuestas a nadie.&lt;/p&gt;

&lt;h2&gt;Lo que aprendí de esto&lt;/h2&gt;

&lt;p&gt;Un loop de auto-mejora no falla por falta de inteligencia. Falla en la cañería, que es la parte que nadie muestra en las demos.&lt;/p&gt;

&lt;p&gt;Registrar señales es fácil y barato, y por eso es lo primero que uno construye. Se siente productivo: los números suben, la tabla se llena, parece que el sistema está aprendiendo. Convertir esa señal en acción es el trabajo real, y es exactamente donde el proyecto se detuvo.&lt;/p&gt;

&lt;p&gt;Acumular 1.771 incidentes sin procesarlos no es telemetría. Es un log caro con aspecto de tablero.&lt;/p&gt;

&lt;p&gt;La lección la aplico ahora antes de instrumentar cualquier cosa nueva: si no tengo claro qué decisión va a tomar alguien —o algo— con ese dato, la instrumentación puede esperar.&lt;/p&gt;

&lt;h2&gt;La segunda vez que los datos me contradijeron&lt;/h2&gt;

&lt;p&gt;Este fue el primer resultado que me obligó a ir a mirar la base de datos en vez de confiar en lo que creía que estaba pasando.&lt;/p&gt;

&lt;p&gt;Un mes después hice lo mismo con el resto del sistema, en una revisión general con el objetivo de mejorar la velocidad del pipeline. Tenía un diagnóstico armado y un plan escrito en base a él.&lt;/p&gt;

&lt;p&gt;Los datos me hicieron tirar ese plan el mismo día. De eso trata la próxima entrega.&lt;/p&gt;

</description>
      <category>automejora</category>
      <category>agentes</category>
      <category>telemetria</category>
      <category>incidentes</category>
    </item>
    <item>
      <title>Cuando el agente falla: corregir, cambiar de enfoque o rendirse</title>
      <dc:creator>Guillermo Leyendeker</dc:creator>
      <pubDate>Sun, 23 Aug 2026 09:00:59 +0000</pubDate>
      <link>https://dev.to/gleyendeker/cuando-el-agente-falla-corregir-cambiar-de-enfoque-o-rendirse-1dcl</link>
      <guid>https://dev.to/gleyendeker/cuando-el-agente-falla-corregir-cambiar-de-enfoque-o-rendirse-1dcl</guid>
      <description>&lt;p&gt;Para principios de mayo el sistema ya sabía detectar que un trabajo estaba mal. Lo que hacía a continuación era, básicamente, nada: frenaba la cadena y me esperaba.&lt;/p&gt;

&lt;p&gt;Eso convierte al orquestador en una herramienta que solo funciona mientras estás mirando. Podía dejarlo corriendo diez minutos, no una tarde. Y el problema no era técnico: era que no había decidido qué debía pasar después de un veredicto negativo.&lt;/p&gt;

&lt;p&gt;El 5 de mayo me senté a resolver eso, y es el día en que el proyecto dejó de ser un lanzador con controles y pasó a tener una arquitectura propia.&lt;/p&gt;

&lt;h2&gt;Separar al que hace del que evalúa&lt;/h2&gt;

&lt;p&gt;El primer cambio fue estructural: separar explícitamente dos roles. Uno genera el trabajo, otro lo evalúa. No es una sutileza organizativa — cambia qué información viaja entre los pasos.&lt;/p&gt;

&lt;p&gt;Mientras el evaluador devuelve "aprobado" o "rechazado", lo único que podés hacer con un rechazo es volver a intentar a ciegas. Si en cambio devuelve &lt;strong&gt;retroalimentación estructurada&lt;/strong&gt;, el sistema puede decidir qué hacer con ella.&lt;/p&gt;

&lt;p&gt;La evaluación pasó a ser multidimensional. En vez de un veredicto único, cuatro ejes: corrección, seguridad, experiencia de usuario y completitud. Cada uno con su puntaje. Y algo que resultó más útil de lo que esperaba: &lt;strong&gt;detección de regresiones&lt;/strong&gt; respecto de intentos anteriores, para distinguir el caso "sigue mal" del caso "está peor que antes", que son problemas distintos.&lt;/p&gt;

&lt;h2&gt;Tres caminos, no uno&lt;/h2&gt;

&lt;p&gt;Con esa información encima, el sistema elige entre tres salidas. Esta es la parte que creo que falta en la mayoría de los orquestadores, donde el manejo de fallas se reduce a reintentar.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;Corregir&lt;/strong&gt;: el trabajo está encaminado pero incompleto o con defectos puntuales. Se vuelve al mismo implementador con la retroalimentación específica de qué arreglar.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;Cambiar de enfoque&lt;/strong&gt;: el trabajo está mal encarado. No alcanza con corregir sobre lo hecho, porque el punto de partida es el problema. Se devuelve la tarea un paso más arriba en la cadena.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;Rendirse&lt;/strong&gt;: después de tres intentos, el sistema deja de insistir.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rendirse no es fallar en silencio, que sería lo peor de los dos mundos. Escribe un &lt;strong&gt;reporte estructurado del incidente&lt;/strong&gt;: qué se intentó, con qué retroalimentación, en qué dimensiones falló cada vez. Ese reporte queda guardado y es material para revisar después.&lt;/p&gt;

&lt;p&gt;De hecho, mirando la pila de esos reportes acumulados fue como se me ocurrió la idea más ambiciosa del proyecto, que es el tema de la próxima entrega y que salió bastante peor de lo que esperaba.&lt;/p&gt;

&lt;h2&gt;El error que tardé un mes en ver&lt;/h2&gt;

&lt;p&gt;Hay un detalle de esta implementación que estuvo mal durante un mes entero y que ilustra bien lo fácil que es desperdiciar contexto sin darse cuenta.&lt;/p&gt;

&lt;p&gt;Cuando el sistema decidía &lt;em&gt;corregir&lt;/em&gt;, relanzaba al implementador. Pero al hacerlo &lt;strong&gt;descartaba la sesión anterior&lt;/strong&gt;. El agente volvía a empezar de cero: sin memoria de qué archivos había tocado, qué caminos había descartado ni por qué había tomado las decisiones que tomó. Lo único que recibía era un texto con la retroalimentación del evaluador.&lt;/p&gt;

&lt;p&gt;Dicho de otra forma: le pedía que corrigiera un trabajo del que no se acordaba.&lt;/p&gt;

&lt;p&gt;La corrección, cuando finalmente la vi, fue de una línea: &lt;strong&gt;conservar la sesión cuando la decisión es corregir&lt;/strong&gt;, y descartarla solamente cuando se cambia de enfoque, que es el único caso donde el olvido es deliberado —ahí querés que el modelo arranque sin el sesgo del intento fallido—.&lt;/p&gt;

&lt;p&gt;Lo que hace segura esa decisión es un límite que ya existía: como la rendición corta al tercer intento, una corrección con la sesión viva puede ocurrir dos veces como máximo. El contexto no crece indefinidamente, tiene un techo estructural.&lt;/p&gt;

&lt;h2&gt;Distinguir los fallos que no son del agente&lt;/h2&gt;

&lt;p&gt;Otra cosa que aprendí operando esto: no todos los fallos son culpa del que trabaja.&lt;/p&gt;

&lt;p&gt;Cuando la API del proveedor devolvía un error de red, el sistema lo contaba como un intento fallido. El agente no había hecho nada mal — ni siquiera había llegado a empezar— pero se le consumía uno de sus tres intentos. Con dos cortes de red seguidos, una tarea perfectamente sana llegaba a la rendición sin que nadie hubiera evaluado nada.&lt;/p&gt;

&lt;p&gt;Hoy esos errores no consumen intento y se reintenta con espera creciente. Penalizar al modelo por una caída de infraestructura es, sencillamente, medir mal.&lt;/p&gt;

&lt;h2&gt;El cuarto camino&lt;/h2&gt;

&lt;p&gt;En agosto agregué una salida más, para un caso que no había previsto: el cambio de enfoque imposible.&lt;/p&gt;

&lt;p&gt;A veces el evaluador determina que el trabajo está mal encarado, pero devolverlo un paso arriba no tiene sentido porque ese paso anterior no existe o ya se agotó. Antes eso caía directo en rendición. Ahora, en vez de abandonar, el sistema &lt;strong&gt;vuelve a explorar el terreno&lt;/strong&gt;: relanza el reconocimiento del código para reconstruir el contexto y reintenta desde ahí.&lt;/p&gt;

&lt;p&gt;Es un ejemplo de algo que se repite en todo el proyecto: las políticas de fracaso no se diseñan bien de entrada. Se descubren operando, cuando aparece el caso que no encaja en ninguna de las salidas que habías previsto.&lt;/p&gt;

&lt;h2&gt;Lo que se gana con esto&lt;/h2&gt;

&lt;p&gt;Un sistema con agentes necesita una política de fracaso tan explícita como su camino feliz. Y esa política tiene que distinguir tres cosas que a primera vista se parecen: el trabajo que está cerca y merece otra pasada, el que está mal encarado y necesita volver atrás, y el que hay que dejar en manos de una persona.&lt;/p&gt;

&lt;p&gt;Reintentar sin esa distinción es tirar dinero: repetís el mismo error con la misma información y esperás un resultado distinto. Y no distinguir la rendición del resto es peor todavía, porque perdés el único caso que realmente merecía tu atención.&lt;/p&gt;

&lt;p&gt;Con las tres salidas implementadas, el sistema empezó a resolver solo la mayoría de sus propios tropiezos. Y quedaron, como sedimento, los reportes de los que no pudo resolver.&lt;/p&gt;

&lt;p&gt;Esa pila de reportes fue el punto de partida de lo que viene: pedirle al sistema que se mejore a sí mismo.&lt;/p&gt;

</description>
      <category>arquitecturadeagentes</category>
      <category>reintentos</category>
      <category>generatorevaluator</category>
      <category>manejodeerrores</category>
    </item>
    <item>
      <title>Cómo saber si el agente hizo lo que dice que hizo</title>
      <dc:creator>Guillermo Leyendeker</dc:creator>
      <pubDate>Sun, 16 Aug 2026 09:00:36 +0000</pubDate>
      <link>https://dev.to/gleyendeker/como-saber-si-el-agente-hizo-lo-que-dice-que-hizo-50dc</link>
      <guid>https://dev.to/gleyendeker/como-saber-si-el-agente-hizo-lo-que-dice-que-hizo-50dc</guid>
      <description>&lt;p&gt;La segunda semana de abril el pipeline ya producía. Un agente elegía la tarea, otro la implementaba, y el sistema la marcaba como terminada. Todo funcionaba, en el sentido de que ningún paso devolvía error.&lt;/p&gt;

&lt;p&gt;Ese era exactamente el criterio: &lt;strong&gt;si el paso anterior corrió sin error, la tarea está hecha&lt;/strong&gt;. Escrito así suena razonable. En la práctica significaba que el sistema le estaba tomando declaración al sospechoso.&lt;/p&gt;

&lt;p&gt;Un agente puede terminar su corrida sin ningún error y no haber tocado una sola línea de código. Puede haber explorado el repositorio, razonado sobre el problema, redactado un resumen convincente de lo que haría, y cerrar. El proceso termina con código de salida cero. El sistema, mirando solamente eso, lo da por implementado.&lt;/p&gt;

&lt;h2&gt;El 12 de abril agregué la primera prueba de implementación&lt;/h2&gt;

&lt;p&gt;La idea era sencilla y cambió el sistema entero: &lt;strong&gt;para marcar algo como hecho hay que encontrar evidencia en el repositorio&lt;/strong&gt;. No leer una afirmación en la salida del agente. Buscar commits.&lt;/p&gt;

&lt;p&gt;Parece un detalle menor. No lo es, porque invierte la carga de la prueba. Antes el sistema asumía que el trabajo estaba hecho salvo que algo fallara. A partir de ese día, asumía que no lo estaba hasta que apareciera un cambio real en el código.&lt;/p&gt;

&lt;p&gt;Tres días después endurecí un poco más el criterio: el control de calidad, que hasta entonces era un paso que se podía saltear, pasó a ser obligatorio entre la implementación y el cierre. Ya no era una verificación opcional que corría cuando yo me acordaba. Sin control aprobado, la tarea no se cerraba.&lt;/p&gt;

&lt;h2&gt;Los agujeros que aparecieron después&lt;/h2&gt;

&lt;p&gt;Lo interesante de este problema es que no se resolvió con esos dos cambios. Se resolvió —parcialmente— a lo largo de cuatro meses, y cada agujero que tapé me enseñó algo sobre la diferencia entre verificar y aparentar que verificás.&lt;/p&gt;

&lt;p&gt;A principios de mayo agregué un control que compara &lt;strong&gt;los archivos que la especificación declaraba que había que tocar contra los que efectivamente cambiaron&lt;/strong&gt; en los commits. Porque encontrar "un commit" no alcanza: el agente puede haber commiteado algo, en algún lado, que no tiene nada que ver con lo que se le pidió.&lt;/p&gt;

&lt;p&gt;Ese mismo día apareció un caso que no había anticipado: un control de calidad viejo certificando trabajo nuevo. La tarea había pasado el control en un intento anterior, después se modificó, y el veredicto guardado seguía diciendo que todo estaba bien. La regla que agregué fue exigir &lt;strong&gt;un control reciente&lt;/strong&gt; antes de marcar nada como hecho.&lt;/p&gt;

&lt;p&gt;Y hubo un problema de alcance, más aburrido pero igual de importante: la búsqueda de commits solo miraba el repositorio principal. Como los cambios se reparten entre el backend y los distintos frontends, había implementaciones perfectamente reales que el sistema no encontraba, y tareas que quedaban trabadas sin motivo. Hubo que extender la búsqueda a todos los repositorios del espacio de trabajo.&lt;/p&gt;

&lt;h2&gt;Cuatro meses después, el problema sigue apareciendo&lt;/h2&gt;

&lt;p&gt;Esta es la parte que menos esperaba cuando empecé.&lt;/p&gt;

&lt;p&gt;El 3 de agosto —casi cuatro meses después del primer control— encontré un caso nuevo: &lt;strong&gt;el control estaba certificando tareas que en realidad nunca había mirado&lt;/strong&gt;. No es que fallara la verificación; es que en cierto camino del código la verificación no llegaba a ejecutarse y el resultado quedaba, por omisión, como aprobado.&lt;/p&gt;

&lt;p&gt;Ese es el tipo de error que más me preocupa, porque no se ve. Un control que falla hace ruido. Un control que no corre y devuelve verde es indistinguible de uno que corrió bien, salvo que vayas a buscarlo específicamente.&lt;/p&gt;

&lt;p&gt;Nueve días más tarde di el último paso hasta ahora: la etapa de implementación de cada tarea &lt;strong&gt;dejó de declararse por lo que el sistema cree&lt;/strong&gt; y pasó a derivarse de la evidencia de cambios ya verificada. Es decir, el estado ya no es algo que se escribe cuando un paso termina; es algo que se calcula a partir de lo que se puede comprobar.&lt;/p&gt;

&lt;p&gt;Si miro la historia completa del proyecto, esta es la única línea de trabajo que atraviesa los cuatro meses de punta a punta. Todo lo demás tuvo un principio y un final. Esto no.&lt;/p&gt;

&lt;h2&gt;Por qué es el problema más difícil del rubro&lt;/h2&gt;

&lt;p&gt;Creo que hay una razón de fondo, y es que confiar es el comportamiento por defecto de casi cualquier sistema que orqueste agentes.&lt;/p&gt;

&lt;p&gt;Cuando conectás un modelo a un pipeline, lo que tenés naturalmente disponible es el resultado del proceso: terminó, no terminó, tiró error. Construir la verificación real —ir al repositorio, buscar commits, cruzar archivos contra la especificación, confirmar que el control corrió sobre esta versión y no sobre otra— es trabajo extra que nadie te pide y que no se nota cuando funciona.&lt;/p&gt;

&lt;p&gt;Se nota cuando no está. Y se nota tarde, que es lo peor: una tarea mal cerrada no genera un error, genera una base falsa sobre la que se apoyan las siguientes. El costo aparece semanas después, cuando algo que dependía de eso no funciona y nadie entiende por qué.&lt;/p&gt;

&lt;p&gt;Por eso lo que aprendí de estos cuatro meses no es una técnica sino un criterio: &lt;strong&gt;la confianza en un agente no se configura, se construye con evidencia externa a él&lt;/strong&gt;. Y la evidencia útil no es que el proceso haya terminado sin error. Es que existan commits, con archivos concretos, que se correspondan con lo que se pidió, verificados después de la última modificación.&lt;/p&gt;

&lt;p&gt;Todo lo demás es tomarle declaración al sospechoso.&lt;/p&gt;

&lt;h2&gt;Lo que esto habilitó&lt;/h2&gt;

&lt;p&gt;Con el sistema capaz de detectar que un trabajo estaba mal, quedó expuesta la pregunta siguiente, que era bastante más incómoda: &lt;em&gt;¿y ahora qué hago con eso?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Por entonces, un veredicto negativo simplemente frenaba la cadena y me esperaba a mí. El agente había fallado, el control lo había detectado, y el sistema se quedaba quieto hasta que yo apareciera a mirar qué había pasado.&lt;/p&gt;

&lt;p&gt;Un pipeline que necesita que vos estés mirando no sirve de mucho. De eso trata la próxima entrega: qué hace el sistema cuando el agente falla, y cómo decidir entre insistir, cambiar de enfoque o abandonar.&lt;/p&gt;

</description>
      <category>verificacion</category>
      <category>agentesdecodigo</category>
      <category>qaautomatizado</category>
      <category>git</category>
    </item>
    <item>
      <title>El mayor ahorro del sistema fue sacarle trabajo al agente</title>
      <dc:creator>Guillermo Leyendeker</dc:creator>
      <pubDate>Thu, 13 Aug 2026 15:53:47 +0000</pubDate>
      <link>https://dev.to/gleyendeker/el-mayor-ahorro-del-sistema-fue-sacarle-trabajo-al-agente-2a5b</link>
      <guid>https://dev.to/gleyendeker/el-mayor-ahorro-del-sistema-fue-sacarle-trabajo-al-agente-2a5b</guid>
      <description>&lt;p&gt;El 7 de abril de 2026 escribí el primer commit de lo que iba a ser mi orquestador de agentes. Era, básicamente, una pantalla. Un servidor que gestionaba varios proyectos a la vez y desde el cual podía disparar tareas de un agente de código, con un tablero al medio que mostraba en qué etapa estaba cada cosa.&lt;/p&gt;

&lt;p&gt;Si me hubieran preguntado ese día cuál era el problema que estaba resolviendo, habría contestado sin dudar: &lt;strong&gt;ver y lanzar&lt;/strong&gt;. Necesitaba un lugar desde donde disparar el trabajo y mirar cómo avanzaba. Cuatro meses después, con más de dos mil tareas cerradas por ese sistema, puedo decir que esa respuesta estaba equivocada, y que el primer indicio de por qué llegó a los tres días.&lt;/p&gt;

&lt;h2&gt;Los dos primeros días fueron todos de interfaz&lt;/h2&gt;

&lt;p&gt;Si miro el historial de esa primera semana, es casi cómico. El ancho del panel lateral. Los tooltips con las fechas completas al pasar el mouse. Los badges de "en progreso" sobre cada etapa. Los colores por etapa del pipeline, para que se distinguieran de un vistazo.&lt;/p&gt;

&lt;p&gt;Hay un par de commits consecutivos que me gusta especialmente como retrato de ese momento. El primero pone un emoji como ícono del botón de repetición. El segundo lo reemplaza por un carácter Unicode, porque el emoji ignoraba el color que le definía por CSS y se veía siempre igual, sin importar el estado.&lt;/p&gt;

&lt;p&gt;No lo cuento para burlarme de mí mismo. Lo cuento porque es exactamente cómo se ve un proyecto cuando todavía no sabés cuál es el problema. Estaba puliendo la superficie del sistema con mucho cuidado porque la superficie era lo único que tenía enfrente. La pregunta de fondo —qué parte de este flujo tiene que decidir un modelo y qué parte no— ni siquiera me la había hecho.&lt;/p&gt;

&lt;h2&gt;El 10 de abril cambió el foco&lt;/h2&gt;

&lt;p&gt;Para entonces el pipeline ya tenía forma: una cadena de pasos donde un agente elegía la próxima tarea pendiente, la implementaba y después la marcaba como terminada. Los tres pasos los hacía el modelo, porque los tres estaban escritos como instrucciones dentro de las habilidades que le pasaba.&lt;/p&gt;

&lt;p&gt;Y ahí apareció la primera pregunta incómoda: &lt;em&gt;¿por qué está eligiendo el modelo?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Elegir la próxima tarea, cuando lo mirás de cerca, no tiene nada de ambiguo. Hay un índice de items. Cada uno tiene un estado y una lista de prerequisitos. La regla es: agarrá el primero que esté pendiente y tenga todos sus prerequisitos cumplidos, marcalo como en progreso y dejá constancia. Eso no es criterio, es un filtro. Es un &lt;code&gt;if&lt;/code&gt; con un par de condiciones.&lt;/p&gt;

&lt;p&gt;Ese día lo convertí en un script determinista. Parsea el índice, encuentra el primer item pendiente con los prerequisitos en orden, lo marca en progreso y commitea el cambio. También contempla el caso de retomar un item que ya estaba empezado, que era la única parte con algo de sutileza.&lt;/p&gt;

&lt;p&gt;El mismo día hice lo propio con el otro extremo de la cadena. El paso de cerrar una tarea —cambiar el estado, recalcular los contadores del resumen, borrar el archivo de especificación y commitear— también dejó de pasar por el modelo. Es una secuencia de operaciones sobre archivos y estado. No hay nada que interpretar.&lt;/p&gt;

&lt;h2&gt;Los números que anoté en ese momento&lt;/h2&gt;

&lt;p&gt;Lo que hace que esto no sea una anécdota es que medí el antes y el después, y lo dejé escrito en los mensajes de esos commits.&lt;/p&gt;

&lt;p&gt;La selección automática costaba alrededor de &lt;strong&gt;0,25 dólares y 40 segundos&lt;/strong&gt; cada vez que corría. El cierre, alrededor de &lt;strong&gt;0,30 dólares y 20 segundos&lt;/strong&gt;. Como script, la selección pasó a ser el paso cero del pipeline: instantáneo y de costo cero, ejecutándose antes de que se levantara ningún agente.&lt;/p&gt;

&lt;p&gt;Poco menos de sesenta centavos y un minuto por tarea. Visto de a una, es despreciable. Ese es justamente el problema con este tipo de desperdicio: nunca duele lo suficiente como para que lo mires.&lt;/p&gt;

&lt;p&gt;Cuatro meses más tarde, el sistema lleva &lt;strong&gt;2.095 funcionalidades y arreglos completados&lt;/strong&gt;. A ese ritmo, esos dos scripts acumulan más de mil dólares y más de treinta horas de espera que nunca se pagaron. Y no porque el modelo hiciera mal su trabajo: lo hacía bien. Simplemente estaba haciendo un trabajo que no requería un modelo.&lt;/p&gt;

&lt;h2&gt;El modelo se paga donde hay ambigüedad&lt;/h2&gt;

&lt;p&gt;La conclusión que saqué de esos dos días la sigo usando como criterio para cada paso nuevo que agrego al pipeline. Un modelo se justifica donde hay que interpretar algo: entender una especificación escrita en prosa, decidir cómo estructurar un cambio, evaluar si un resultado es aceptable. Donde la regla se puede escribir, la regla gana.&lt;/p&gt;

&lt;p&gt;Y no gana solo por precio. Gana por tres motivos que pesan más a medida que el sistema crece:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;Es más barato&lt;/strong&gt;, que es lo obvio y lo menos importante.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;Es más rápido&lt;/strong&gt;: un script tarda milisegundos donde un agente tarda decenas de segundos, y esa diferencia se multiplica por cada tarea del backlog.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;Es determinista&lt;/strong&gt;, que es lo que realmente importa. Un pipeline que tiene que correr sin nadie mirando no puede tener pasos que a veces hagan una cosa y a veces otra. Cada punto donde interviene un modelo es un punto donde el resultado puede variar, y esa varianza se acumula a lo largo de la cadena.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dicho de otro modo: cada paso determinista que le sacás al agente no es solo ahorro, es una fuente de incertidumbre que eliminás del sistema.&lt;/p&gt;

&lt;h2&gt;La telemetría fue lo que hizo posible verlo&lt;/h2&gt;

&lt;p&gt;Hay un detalle sin el cual nada de esto habría pasado: para poder afirmar que un paso costaba veinticinco centavos, primero tuve que medirlo.&lt;/p&gt;

&lt;p&gt;Esa instrumentación —registrar el costo y la duración de cada paso, uno por uno— es de lo primero que construí, y hoy el sistema lleva &lt;strong&gt;5.698 corridas de habilidades y 9.109 pasos registrados&lt;/strong&gt;, cada uno con lo que costó y lo que tardó. Es la base sobre la que se apoyan casi todas las decisiones que voy a contar en esta serie.&lt;/p&gt;

&lt;p&gt;Sin esos números, el razonamiento de aquel 10 de abril habría sido una intuición más, del mismo tipo que las que después resultaron equivocadas. Con los números, fue una decisión de diez minutos.&lt;/p&gt;

&lt;h2&gt;Lo que vino después&lt;/h2&gt;

&lt;p&gt;Con el flujo ordenado y los pasos deterministas fuera del modelo, el pipeline empezó a producir a buen ritmo. Y ahí, casi de inmediato, apareció el problema que me iba a ocupar los cuatro meses siguientes y que todavía hoy no está del todo cerrado.&lt;/p&gt;

&lt;p&gt;El agente terminaba su corrida, informaba que había implementado lo pedido, y el sistema lo daba por terminado con un único criterio: que el paso anterior hubiera corrido sin error. Eso resultó insuficiente muy rápido.&lt;/p&gt;

&lt;p&gt;De eso se trata la próxima entrega: cómo saber si el agente hizo lo que dice que hizo.&lt;/p&gt;

</description>
      <category>agentesdecodigo</category>
      <category>orquestacion</category>
      <category>determinismo</category>
      <category>costosdellm</category>
    </item>
  </channel>
</rss>
