Módulo 2: El cerebro del agente: modelo y system prompt

7. Probar y repetir ejecuciones con el motor de depuración

Descripción

Al terminar esta lección vas a poder cargar una ejecución real y pasada de tu agente dentro del editor, congelar su dato de entrada, y comparar dos variantes — de modelo o de prompt — contra exactamente el mismo mensaje, sin volver a escribirle al bot ni a disparar el canal real una segunda vez.

Esto importa porque ya lo viste de lejos en la introducción de este módulo: comparar variantes escribiéndole al agente de verdad por WhatsApp o por el chat en vivo tiene un costo doble. Pagas de nuevo cada llamada al modelo, y encima pierdes la certeza de que el mensaje de prueba es idéntico al anterior — porque lo estás re-escribiendo a mano, con matices distintos cada vez. Un freelance o una agencia que itera un agente para un cliente necesita poder responder "sí, ya confirmé que el cambio funciona con datos reales" sin que eso signifique gastar otra tanda de tokens ni molestar de nuevo al cliente pidiéndole que repita su mensaje de prueba.

Conexión con el módulo: en la lección 2 ya viste el motor de depuración de pasada — como la herramienta para confirmar, sobre una muestra real, cuál candidato de modelo rinde mejor antes de fijarlo. En la lección 4 volviste a verlo mencionado, al comparar Llama 3.2 contra Mistral. Hoy es su turno: vas a aprender el mecanismo mismo. No vas a escribir un System Message nuevo (eso fue la lección 5) ni vas a ajustar temperatura o salida estructurada (lección 6) — vas a asumir que esas piezas ya existen, y vas a aprender a probarlas sin fricción antes del mini-proyecto de la lección 8.

Comparar sin repetir el experimento

Imagina a un ingeniero de audio probando dos pedales de guitarra distintos para ver cuál suena mejor en una canción. Si toca la canción en vivo una vez con el pedal A y, minutos después, la vuelve a tocar en vivo con el pedal B, cualquier diferencia que escuche puede venir del pedal — o puede venir de que la segunda toma salió un poco más rápida, o de que se equivocó en un acorde la primera vez. No hay forma de aislar la causa. Por eso ningún ingeniero serio prueba pedales así: graba una sola toma de la canción, la deja fija, y la hace pasar por el pedal A y después por el pedal B. La interpretación es idéntica las dos veces; lo único que cambia es el pedal. Recién ahí la diferencia que escucha significa algo.

n8n guarda algo parecido a esa toma grabada. Cada vez que tu agente corre, la pestaña Executions del workflow queda con un registro completo de esa ejecución: qué entró a cada nodo, qué salió. Dos botones te dejan traer ese registro de vuelta al canvas — Debug in editor si la ejecución falló, Copy to editor si terminó bien —, y ambos hacen lo mismo: copian los datos de esa ejecución exacta y los fijan (pin) en el primer nodo de tu flujo, normalmente el Chat Trigger. A partir de ahí, ese nodo deja de esperar un mensaje nuevo del canal real — entrega, cada vez que ejecutas, el mismo dato guardado. Es tu toma grabada.

Con el input congelado, ya puedes cambiar una sola cosa —el sub-nodo de modelo, una línea del System Message— y volver a ejecutar solo esa parte del flujo. Nada se dispara hacia el canal real: ni un mensaje nuevo llega por WhatsApp, ni gastas una llamada de más al trigger. Lo único que corre de nuevo es lo que tú decidiste tocar, contra el mismo mensaje de siempre.

Un detalle práctico antes de seguir: si estás corriendo n8n self-hosted — como el Self-Hosted AI Starter Kit v2 que levantaste en la lección 4 —, Debug in editor y Copy to editor solo aparecen en una instancia Community registrada. El registro es gratis: das tu correo, recibes una license key, y una vez activada no vence. Si no ves esos botones en tu instancia local, ese es el primer lugar a revisar, no un bug de n8n.

Ejemplo trabajado

Tu agente de TuTienda ya tiene el System Message de la lección 5 y la salida estructurada en JSON de la lección 6: cada respuesta debe venir en un objeto con un campo de texto para el cliente y un campo booleano que marca si el caso necesita escalarse a un humano. Ayer, un cliente real escribió esto por el chat en vivo:

Input real (ejecución #1842, registrada ayer a las 14:32):

Buenas! tengo dos pedidos, el 4521 y el 4530 (son del mismo mes)
¿me puedes decir el estado de LOS DOS? y aparte una pregunta aparte:
¿tienen envío gratis a partir de qué monto?

La ejecución falló. El nodo que procesa la respuesta del agente esperando el JSON de la lección 6 tiró un error de formato: el modelo, ante un mensaje con dos pedidos y una pregunta aparte, antepuso una frase de cortesía ("¡Claro, con gusto te ayudo con eso!") antes del JSON, y el parser no supo qué hacer con texto antes de la llave de apertura.

Paso 1 — localizar y cargar la ejecución fallida. En la pestaña Executions, filtras por "Failed" y encuentras la #1842. La abres: el nodo marcado en rojo es el que intenta interpretar la respuesta del agente como JSON. Seleccionas Debug in editor.

Qué esperar: n8n copia el mensaje real del cliente al canvas y lo fija en el Chat Trigger — ves el banner "This data is pinned" en el panel de salida de ese nodo. El resto del flujo sigue armado exactamente como estaba ayer.

Paso 2 — aislar una variable a la vez. Tienes dos hipótesis sobre por qué falló: (a) tal vez un modelo con más capacidad de razonamiento maneja mejor un mensaje con dos preguntas encimadas, sin tocar el prompt; (b) tal vez el System Message necesita una línea explícita del tipo "responde únicamente con el objeto JSON, sin ningún texto antes o después". Las pruebas una por una, nunca las dos juntas — si cambias el modelo y el prompt al mismo tiempo y el error desaparece, no vas a saber cuál de las dos cosas lo arregló.

Variante A — mismo System Message, cambias el modelo. Reemplazas el sub-nodo Chat Model actual (Claude Sonnet 5) por uno conectado a GPT-5.6 Terra, sin tocar el System Message. Ejecutas solo el nodo AI Agent contra el dato fijado.

Qué esperar — Variante A: el nuevo modelo también antepone una frase de cortesía antes del JSON. El error persiste. Conclusión: no era un problema de capacidad de razonamiento del modelo — ambos modelos, dado el mismo prompt ambiguo sobre el formato, cometen el mismo desliz.

Variante B — vuelves a Claude Sonnet 5, agregas una línea al System Message. Sumas: "Tu respuesta completa debe ser únicamente el objeto JSON —sin saludo, sin texto antes ni después—." Ejecutas de nuevo el nodo AI Agent contra el mismo dato fijado.

Qué esperar — Variante B: la respuesta llega como un JSON limpio, sin preámbulo, y el nodo que lo interpreta ya no falla. El caso confirma lo que viste en la introducción del módulo: modelo y prompt son ejes independientes, y este síntoma —un formato de salida que se rompe— vivía en el prompt, no en el modelo. Cambiar de modelo no iba a arreglarlo nunca.

Paso 3 — confirmar el fix sin volver a abrir el canvas. Ya guardaste la línea nueva del System Message en el workflow real. Para confirmar, con un clic, que ese cambio de verdad resuelve el caso real de ayer, vuelves a la lista de Executions, abres la #1842, y en el ícono de refrescar eliges Retry with currently saved workflow — esto vuelve a correr el dato original de esa ejecución, pero contra la versión del workflow que tienes guardada ahora mismo, línea nueva incluida.

Qué esperar: la ejecución se marca como exitosa. Tienes, en un clic y sin re-escribirle nada al cliente, la confirmación de que el fix funciona sobre el caso real que lo rompió — no sobre un mensaje de prueba inventado por ti.

Dos formas de repetir una ejecución, y para qué sirve cada una

El botón de refrescar de una ejecución en la lista de Executions te da dos opciones, y confundirlas te lleva a una conclusión equivocada:

  • Retry with currently saved workflow — corre el dato de entrada de esa ejecución pasada, pero contra la configuración que tienes guardada ahora en el workflow. Es la que usaste en el paso 3: sirve para confirmar que un cambio que ya aplicaste resuelve un caso real específico.
  • Retry with original workflow — corre exactamente lo que corrió esa vez: mismo dato, mismo modelo, mismo prompt, sin aplicar ningún cambio que hayas guardado después. Sirve para una pregunta distinta: ¿el fallo de ayer se repite siempre que le des ese mismo input, o fue una rareza de una sola vez?

Esa segunda pregunta importa más de lo que parece. Como viste en la lección 6, el parámetro de temperatura introduce variación en la respuesta del modelo — y la documentación de Anthropic es explícita en que, incluso con la temperatura en su valor más bajo, el resultado no es completamente determinístico. Eso significa que un mismo modelo, con el mismo prompt y el mismo input exacto, puede responder distinto en dos corridas separadas. Si corres Retry with original workflow sobre la ejecución #1842 varias veces y el error de formato aparece siempre, tienes un problema real de prompt (el que arreglaste en la Variante B). Si aparece solo a veces, estabas viendo una rareza de muestreo, no un patrón — y ahí el criterio cambia: quizás no hacía falta tocar el System Message, sino bajar la temperatura para que ese tipo de desvío ocurra con menos frecuencia.

Errores comunes

Pensar que cargar una ejecución pasada "congela" todo el flujo, no solo el dato de entrada (conceptual). Qué pasa: después de usar Debug in editor, cambias el modelo o el System Message, ejecutas de nuevo, y esperas ver la misma respuesta de ayer porque "ya quedó grabada esa ejecución". Cuando el resultado es distinto, algunos asumen que el motor de depuración no sirve para probar cambios reales. Por qué pasa: el nombre "pin data" y la idea de "cargar el pasado" sugieren que todo quedó fijo, cuando en realidad solo el nodo donde pusiste el pin —típicamente el trigger— deja de pedir un dato nuevo. Todo lo que viene después de ese nodo se ejecuta de verdad, con tu configuración actual, cada vez que lo corres. Cómo detectarlo: si cambiaste algo y el resultado no se mueve ni un poco, sospecha primero de que el cambio no se guardó o de que estás mirando el panel de salida de una ejecución vieja, no de que "el motor de depuración no deja probar nada nuevo". Cómo corregirlo: piensa el pin como "congelar solo la entrada", nunca como "congelar el experimento completo" — el resto del flujo sigue vivo y responde a lo que edites.

Cambiar dos variables a la vez al comparar (conceptual). Qué pasa: tocas el modelo y el System Message en la misma corrida —como pasaría si en el ejemplo trabajado hubieras probado GPT-5.6 Terra con la línea de formato nueva desde el inicio—, el error desaparece, y das el caso por cerrado sin saber cuál de los dos cambios lo resolvió. Semanas después, alguien quiere revertir el modelo por costo y el bug de formato vuelve, porque en realidad nunca fue el modelo el que lo arreglaba. Por qué pasa: cuando ya tienes dos hipótesis en la cabeza, es tentador probarlas juntas para "ahorrar una vuelta" — parece más eficiente, aunque destruye la posibilidad de aislar la causa. Cómo detectarlo: si no puedes responder con una frase concreta cuál de los cambios provocó la mejora, probablemente cambiaste más de una cosa a la vez. Cómo corregirlo: usa el dato fijado para probar una variable por corrida, exactamente como en las Variantes A y B del ejemplo — es más lento por comparación individual, pero es la única forma de saber, con certeza, qué fue lo que realmente funcionó.

Confundir "Retry with original workflow" con "Retry with currently saved workflow" (práctico). Qué pasa: aplicas un fix al System Message, lo guardas, y para confirmarlo eliges por error Retry with original workflow sobre la ejecución que falló. La ejecución vuelve a fallar exactamente igual —porque ese botón ignora tu cambio guardado y repite la configuración original, no la nueva—, y concluyes erróneamente que el fix no funcionó. Por qué pasa: los dos nombres son casi idénticos y aparecen uno junto al otro en el mismo menú; la diferencia entre "currently saved" y "original" es sutil si no la lees con cuidado. Cómo detectarlo: si "confirmaste" un fix con un retry y el error persistió idéntico, revisa cuál de los dos botones usaste antes de asumir que el fix falló. Cómo corregirlo: usa "Retry with currently saved workflow" para poner a prueba un cambio que ya guardaste, y reserva "Retry with original workflow" únicamente para confirmar si un fallo pasado es reproducible o fue una rareza puntual.

Ejercicios

Ejercicio 1. Volviendo al ejemplo de la lección 2 —comparar Claude Sonnet 5, GPT-5.6 Terra y Gemini 2.5 Flash para el agente que clasifica tickets de soporte—: tienes una ejecución real donde Sonnet 5 clasificó mal la urgencia de un ticket. Describe, en orden, los pasos que usarías con el motor de depuración para probar si Gemini 2.5 Flash clasifica ese mismo ticket mejor, sin volver a pedirle ese ticket a un cliente real.

Ver solución
  1. En la pestaña Executions del workflow del agente de tickets, localizas la ejecución donde Sonnet 5 clasificó mal la urgencia y la abres.
  2. Seleccionas Debug in editor (fue una ejecución con un resultado incorrecto, pero técnicamente no "falló" —si terminó sin error, el botón sería Copy to editor; si el parser de salida sí tiró un error, sería Debug in editor). Cualquiera de los dos copia el ticket real y lo fija en el primer nodo.
  3. Reemplazas el sub-nodo de modelo actual por uno conectado a Gemini 2.5 Flash, sin tocar el System Message ni ningún otro nodo.
  4. Ejecutas solo el nodo del agente contra el dato fijado y comparas la nueva clasificación de urgencia contra la que dio Sonnet 5 sobre el mismo ticket exacto.

Por qué funciona: el ticket real queda congelado como único input de la comparación, así que cualquier diferencia en la clasificación viene únicamente del modelo —la única variable que cambiaste—, no de que el segundo ticket sea distinto o esté redactado de otra forma.

Ejercicio 2. Un compañero de equipo cambia, en la misma corrida, el modelo del agente y una línea del System Message. El error que tenían desaparece. Te pregunta: "¿fue el modelo o el prompt lo que lo arregló?". ¿Qué le respondes, y qué debería haber hecho distinto?

Ver solución

No hay forma de saberlo con la evidencia que generó, porque cambió dos variables a la vez —exactamente el error común de esta lección—. Debería haber probado cada cambio por separado contra el mismo dato fijado: primero solo el modelo nuevo (con el System Message viejo), después solo la línea nueva del System Message (con el modelo viejo), y comparar cada resultado contra el original. Recién con esas dos corridas aisladas sabría cuál de los dos cambios —o si hicieron falta los dos— resolvió el caso.

Por qué funciona: aislar una variable por corrida es lo único que permite atribuir una mejora a una causa concreta; cambiar varias cosas a la vez puede arreglar el síntoma, pero deja a cualquiera adivinando por qué, lo cual importa el día que alguien quiera revertir solo uno de los dos cambios.

Ejercicio 3. Ya aplicaste y guardaste un fix al System Message de tu agente. Quieres confirmar, sin abrir el canvas ni tocar ningún nodo, que ese fix resuelve el caso real que falló ayer (ejecución #1842). Por separado, también quieres saber si el fallo original era reproducible siempre o fue una rareza de una sola vez. ¿Qué botón usas para cada pregunta?

Ver solución

Para confirmar que el fix ya guardado resuelve el caso real: abres la ejecución #1842 en la lista de Executions y eliges Retry with currently saved workflow —corre el dato original de esa ejecución contra la configuración que tienes guardada ahora, fix incluido—. Para saber si el fallo original era reproducible: eliges Retry with original workflow una o varias veces sobre esa misma ejecución —esto repite exactamente la configuración y el dato de ayer, sin tu fix, y si el error aparece cada vez, confirma que era un problema real de prompt y no una rareza de muestreo del modelo.

Por qué funciona: cada botón responde a una pregunta distinta —uno prueba tu cambio contra el pasado, el otro prueba si el pasado se repite tal cual— y elegir el equivocado te da una respuesta que no corresponde a la pregunta que estás haciendo.

Ejercicio 4 (reto). Diseña, paso a paso, cómo usarías el motor de depuración para comparar tres candidatos de modelo (Claude Sonnet 5, GPT-5.6 Terra, Gemini 2.5 Flash) sobre el mismo lote de 5 tickets reales de soporte —no uno solo—, controlando que la única variable que cambie entre corridas sea el modelo.

Ver solución

Por cada uno de los 5 tickets reales: localizas su ejecución en la lista de Executions y la cargas con Debug in editor o Copy to editor según haya fallado o no, fijando ese ticket en el primer nodo. Con el ticket fijado, ejecutas el nodo del agente tres veces seguidas —una por cada modelo—, reemplazando solo el sub-nodo Chat Model entre corrida y corrida, sin tocar el System Message ni ningún otro nodo. Anotas la clasificación y el borrador de respuesta que dio cada modelo para ese ticket. Repites la misma mecánica para los otros cuatro tickets, y al final comparas, ticket por ticket, cuál de los tres modelos acertó más veces en la clasificación y produjo el mejor borrador.

Por qué funciona: fijar cada ticket por separado asegura que los tres modelos compiten sobre exactamente el mismo input en cada ronda —nunca comparas la respuesta de un modelo sobre el ticket 1 contra la de otro modelo sobre el ticket 2—, y cambiar solo el sub-nodo de modelo entre corridas mantiene aislada la única variable que te interesa medir.

Resumen y siguiente paso

Ya sabes cargar una ejecución real —fallida con Debug in editor, exitosa con Copy to editor— y dejar su dato de entrada fijado en el primer nodo de tu flujo. Sabes cambiar una sola variable a la vez —modelo o prompt— y ejecutar solo esa parte contra el dato congelado, sin disparar el canal real ni gastar una llamada de más. Y sabes cuándo usar Retry with currently saved workflow para confirmar un fix, contra cuándo usar Retry with original workflow para comprobar si un fallo pasado es reproducible.

Esto es la base para lo que sigue: en el mini-proyecto de la lección 8 vas a ensamblar el agente completo —modelo elegido con criterio, System Message con límites propios— y el paso final antes de darlo por terminado es exactamente este: correrlo contra casos reales guardados y confirmar que se comporta como esperas, en vez de asumirlo por cómo se ve en un par de mensajes sueltos.

Antes de avanzar deberías poder explicar, sin mirar esta lección: qué diferencia hay entre Debug in editor y Copy to editor; qué significa exactamente que un dato quede "fijado" (pin) en un nodo, y qué parte del flujo sigue corriendo de verdad después de eso; y por qué cambiar dos variables en la misma corrida te impide saber cuál de las dos causó una mejora.

Recursos