Lección 1: «Parece terminado» no es «está terminado»
Objetivos de aprendizaje:
- Explicar por qué Claude se detiene cuando el trabajo parece terminado, y quién termina haciendo la verificación cuando eso pasa
- Usar el contraste entre sistemas deterministas y no deterministas para explicar por qué los supuestos de las pruebas tradicionales —«entrada X, camino Y, salida Z»— se derrumban con los agentes
- Ante un reporte de finalización, distinguir qué enunciados son afirmaciones y cuáles son evidencia, e identificar qué falta todavía para el visto bueno
Requisitos: Terminaste los primeros 9 cursos de esta serie; escribes a mano bucles de arnés guiados por stop_reason; entiendes los puntos de control y la recuperación | Siguiente: Lección 2 >>
Se lanzó el martes, se rompió el viernes
El martes por la tarde le pides a un agente que agregue una función de «importación masiva de usuarios» a un panel de administración interno: subir un CSV, parsearlo, validar los campos, escribir en la base de datos. Dejas los requisitos bien claros y te vas a una reunión.
Cuando vuelves, la sesión ya se detuvo. El último mensaje se ve así:
Le echas un vistazo al diff. Las funciones están bien separadas, los nombres coinciden con los de los módulos vecinos, los casos límite parecen contemplados: los archivos vacíos devuelven un error explícito, la expresión regular del email no está rota de manera evidente. Lo fusionas. Lo lanzas.
El viernes por la tarde, operaciones escribe en el canal: «¿Por qué acabamos de importar 400 usuarios vacíos?».
La causa es sencilla. Operaciones generó ese CSV con un «Guardar como» desde Excel, lo que agregó un BOM: tres bytes invisibles que a Excel le gusta anteponer a los archivos UTF-8. Así, el nombre de la primera columna se parseó como email en lugar de email, todo el mapeo de campos se cayó, y cada fila terminó siendo «todos los campos son undefined». ¿Y esa capa de validación? Revisaba «si el formato del email es válido», pero undefined tomó otra rama y se trató como «esta columna no se llenó», así que pasó.
Nadie hizo las cosas a medias. El agente escribió código que funciona. Se probó a sí mismo con un CSV que él mismo generó, y por supuesto su propio CSV no tiene BOM. Cuando revisaste el diff, estabas comprobando «si este código está bien escrito», no «qué pasa cuando este código se encuentra con una entrada del mundo real». Ambas partes hicieron su mejor esfuerzo. La brecha ocurrió igual.
El problema está en el momento en que se detuvo. Cuando el agente se detuvo, lo que tenía era «lo escribí, lo leí una vez, se ve bien». No se detuvo en «confirmé que está terminado». Se detuvo en «parece terminado». Y en el historial de la conversación no puedes distinguir la diferencia.
Se detiene donde las cosas parecen terminadas
La documentación de Claude Code lo dice sin rodeos: Claude se detiene cuando el trabajo parece terminado; sin una comprobación que pueda ejecutar, «parece terminado» es la única señal disponible, y tú te conviertes en el bucle de verificación: cada error espera a que tú lo notes1.
Vale la pena leer esta oración dos veces, palabra por palabra. No dice «Claude a veces hace las cosas a medias» ni «el modelo todavía no da la talla». Describe un hecho estructural: si nada en todo el pipeline puede producir un resultado objetivo, entonces «parece terminado» es la única señal que existe en ese sistema. El modelo solo puede decidir con esa señal. No tiene ninguna otra.
La misma documentación le pone nombre a este fenómeno: la brecha de confiar-y-después-verificar, donde Claude produce una implementación de apariencia plausible que no maneja los casos límite1. En palabras simples: primero confías (el código se ve bien), y la verificación o no ocurre o llega demasiado tarde (el viernes por la tarde, en el canal de operaciones). El ejemplo del BOM de arriba es la forma estándar de esta brecha: el código no está mal, pero nadie preguntó «¿qué pasa con un archivo exportado desde Excel?».
Hay una segunda capa que es fácil pasar por alto. La solución que sugiere la documentación termina así: si no lo puedes verificar, no lo lances1. El énfasis no está en «verificar», está en «no lo lances». Reconoce que hay cosas que simplemente no puedes verificar. Cuando no puedes, la jugada correcta no es «esta vez confía en tu instinto». Es reducir el alcance, cambiar el requisito o postergar el lanzamiento.
Afirmaciones frente a evidencia: ¿cuál es la diferencia?
Vuelve a ese mensaje de finalización. Divídelo en oraciones sueltas y hazte la misma pregunta con cada una: ¿puedo confirmar esta oración sin leer código, usando solo lo que me mostró?
- «Agregué
src/importer/parseCsv.js»: lo puedes confirmar. Que el archivo exista se comprueba de un vistazo. Esto es evidencia (aunque de la clase más débil).
- «La implementación sigue el estilo de código de los módulos existentes»: no lo puedes confirmar. Es un juicio estético del modelo. Afirmación.
- «Sin errores durante la ejecución»: suena a evidencia, pero en realidad es una afirmación. Dice que las herramientas que llamó no lanzaron excepciones, no que la salida sea correcta. Que todas las herramientas devuelvan éxito mientras el resultado está completamente mal: totalmente posible.
- «Revisar el formato del email y los campos obligatorios»: no lo puedes confirmar. Esto describe la intención, no el comportamiento. ¿Qué permite o rechaza en realidad esa expresión regular? Esta oración no dice nada al respecto.
¿Dónde está la línea? La evidencia es algo que una segunda persona puede volver a ejecutar exactamente igual: un comando con su salida en bruto, un código de salida, una lista de nombres de pruebas que fallaron, una captura de pantalla, una comparación numérica de antes y después. Las afirmaciones son cosas que solo puedes elegir creer o no: «la lógica es correcta», «debería estar bien», «ya está optimizado», «no va a volver a pasar».
La documentación oficial traza exactamente esta línea: haz que Claude muestre evidencia en lugar de afirmar el éxito: la salida de las pruebas, el comando que ejecutó y lo que devolvió, o una captura de pantalla del resultado. Revisar evidencia es más rápido que volver a ejecutar la verificación tú mismo, y funciona para las sesiones que no estuviste mirando1.
Esa última media oración es la clave. Si estuviste mirando todo el tiempo, la distinción entre «afirmación» y «evidencia» no te aporta mucho: lo viste tú mismo. Pero en el momento en que apartas la vista, lo único que queda en el historial de la conversación es texto, y en el texto las afirmaciones se ven tan seguras como la evidencia.
Por qué los agentes chocan especialmente con este problema
El «se ve bien pero está mal» también lo vemos en el software tradicional. ¿Por qué merece una lección propia en el caso de los agentes?
Porque las pruebas tradicionales descansan sobre un supuesto que los agentes no cumplen.
Empecemos por las definiciones. En computación, los sistemas deterministas producen la misma salida cada vez que reciben entradas idénticas, mientras que los sistemas no deterministas —como los agentes— pueden generar respuestas variadas incluso con las mismas condiciones iniciales2. Esto no es «tiene errores y por eso es inestable». Así es como funciona. Aunque no cambies nada en tu prompt, no hay garantía de que las decisiones de dos ejecuciones coincidan3.
Así que la premisa de la evaluación tradicional se derrumba. Las evaluaciones tradicionales suelen suponer que la IA sigue los mismos pasos cada vez: dada la entrada X, el sistema debería seguir el camino Y para producir la salida Z3. Los sistemas multiagente no funcionan así. Incluso con puntos de partida idénticos, los agentes podrían tomar caminos válidos completamente distintos para llegar a su objetivo: un agente podría buscar en tres fuentes mientras otro busca en diez, o podrían usar herramientas distintas para encontrar la misma respuesta3.
Así se ve en concreto:
No puedes llamar «incorrecta» a ninguna de las dos trayectorias. La segunda ejecución leyó un archivo de más, modificó un lugar de más y ejecutó las pruebas dos veces: quizá dio un rodeo, o quizá detectó un acoplamiento que la primera ejecución se perdió. Si escribes una aserción que dice «debe leer schema.sql primero», la segunda ejecución falla, y sin embargo puede que la segunda ejecución haya hecho un mejor trabajo.
Cotejar la trayectoria con un guion prescrito no funciona aquí: como no siempre sabemos cuáles son los pasos correctos, por lo general no podemos limitarnos a comprobar si los agentes siguieron los pasos «correctos» que prescribimos de antemano3.
Agrega una capa más: los errores en los sistemas de agentes se componen. Un fallo menor del software tradicional, cuando le toca a un agente, puede descarrilar la tarea entera: que un paso falle puede llevar a los agentes a explorar trayectorias completamente distintas, con resultados impredecibles3. Esto no es como un programa tradicional donde «una función devuelve un valor malo y se propaga hacia arriba». Un agente toma un mal resultado y toma decisiones nuevas a partir de ese mal resultado: si lee mal un archivo, podría concluir que «este módulo no existe» y crear uno nuevo; y después sigue trabajando alrededor de ese módulo nuevo. Para cuando ves la salida final, el error ya no está en su lugar original. Creció hasta convertirse en otra cosa.
La propia conclusión de Anthropic aterriza aquí: la naturaleza autónoma de los agentes implica costos más altos y el potencial de errores que se componen. Recomiendan pruebas exhaustivas en entornos de sandbox, junto con los guardrails adecuados4. Y una línea más, directa: el LLM operará potencialmente durante muchos turnos, y debes tener cierto nivel de confianza en su toma de decisiones4.
Fíjate en la formulación «cierto nivel de confianza». No dice «tienes que confiar en él». Dice que esa confianza tiene que venir de algún lado. Y la confianza tiene solo dos fuentes: lo miraste tú mismo (con lo cual el agente no te ahorró nada de tiempo), o algo lo miró por ti. Todo este curso trata de la segunda.
La salida: darle una comprobación que pueda ejecutar
Todo ese planteo aterriza en una sola oración: dale a Claude una comprobación que pueda ejecutar: pruebas, una compilación, una captura de pantalla para comparar. Es la diferencia entre una sesión que miras y una de la que te puedes alejar1.
¿De dónde sale la diferencia? Dale a Claude algo que produzca un aprobado o un fallido y el bucle se cierra solo. Claude hace el trabajo, ejecuta la comprobación, lee el resultado e itera hasta que la comprobación pasa1.
Puedes mapear esta oración de vuelta al bucle de arnés del curso 7 de esta serie. Primero mira dónde se detiene tu bucle actual:
¿Qué significa end_turn? Significa que el modelo cree que terminó de hablar en este turno. Eso es todo. No significa que el trabajo esté correcto, y ni siquiera garantiza que la respuesta esté completa: este bucle solo reconoce tool_use; si stop_reason pasa a ser cualquier otra cosa, va a salir, incluso cuando la salida quedó cortada a mitad de una oración por max_tokens. Nada en la condición de salida tiene que ver con la «calidad de la salida».
Entonces, ¿cómo se ve conectar una comprobación? Hay dos posiciones que funcionan.
Posición uno: convertir la comprobación en una herramienta que pueda llamar, y dejar que se ejecute dentro del bucle:
Posición dos: agregar una compuerta después de que el bucle sale; no confíes en su autorreporte, ejecútala tú mismo:
El código en sí no tiene trucos. La clave es que la condición de salida cambió de dueño: de «el modelo dice que no quiere llamar más herramientas» a «un pedazo de código determinista devolvió 0». Lo primero es la autoevaluación del modelo. Lo segundo no.
¿Y qué puede ser una «comprobación»? La documentación oficial da un rango más amplio de lo que esperarías: la comprobación es cualquier cosa que devuelva una señal que Claude pueda leer en la conversación: una suite de pruebas, el código de salida de una compilación, un linter, un script que compare la salida con un fixture, o una captura de pantalla del navegador comparada con un diseño1.
Aclaremos «fixture»: es un «archivo de respuesta de referencia» que guardaste de antemano; después de ejecutar, comparas la salida con él, y no puede diferir ni en un carácter. Suena tosco, pero para las tareas del tipo «el formato de salida debe ser estable» es la forma de comprobación más simple y más confiable.
Esta línea de pensamiento se alinea con la recomendación de Anthropic para la ejecución de agentes: durante la ejecución, es crucial que los agentes obtengan la «ground truth» del entorno en cada paso (por ejemplo, los resultados de las llamadas a herramientas o la ejecución de código) para evaluar su progreso4. Fíjate en «del entorno», no de su propio razonamiento. El razonamiento del modelo lo genera él mismo. Los valores que devuelve el entorno, no.
Qué resuelven las cinco lecciones siguientes
Con «darle una comprobación que se pueda ejecutar» como hilo conductor, las preguntas que quedan se vuelven concretas.
Lección 2: qué verificar. Si cotejar la trayectoria con un guion prescrito no funciona, ¿qué compruebas? Respuesta: primero el estado final; evalúa si alcanzó el estado final correcto, no si siguió algún proceso específico; para los flujos de trabajo complejos, divide la evaluación en puntos de control discretos donde deberían haber ocurrido cambios de estado específicos3. Esta lección también cubre cómo convertir un requisito difuso en un criterio de éxito medible.
Lección 3: verificadores deterministas. Cómo elegir y escribir comprobaciones que puedan producir un aprobado/fallido. Coincidencia exacta, comparación por script, suites de pruebas: qué encaja dónde, y una trampa contraintuitiva: un verificador demasiado estricto va a rechazar respuestas correctas. El catálogo concreto de verificadores y el orden de prioridad van en esa lección; aquí no los desarrollamos.
Lección 4: el juez LLM. El texto de forma libre no admite comparación de cadenas; hay que pedirle a un modelo que lo puntúe. Cómo escribir rúbricas, cómo restringir el formato de salida, si conviene razonar primero o puntuar primero, y por qué el modelo que hizo el trabajo no debería calificarse a sí mismo: ya lo tocamos en el cuestionario de más arriba. El diseño concreto de rúbricas va en la lección 4.
Lección 5: los conjuntos de evaluación. Una comprobación se ocupa de una tarea; un conjunto de tareas forma un conjunto de evaluación. Cómo recolectar casos del uso real, cómo completar los casos límite, para qué sirve un conjunto reservado y «cuántos alcanzan»: todo se responde en la lección 5; la respuesta puede ser más chica de lo que crees.
Lección 6: constrúyelo tú mismo. Conecta las cinco lecciones anteriores: cada tarea de evaluación recibe un bucle de arnés, lo ejecutas y produce un reporte; cambias una versión del prompt y ves si la puntuación se movió.
Proporcionalidad: no envuelvas cada cosita en un proceso de visto bueno
Llegados a este punto, es fácil irse al otro extremo: suponer que toda tarea necesita pruebas, un juez y un conjunto de evaluación. No es así.
La línea original de Anthropic es: la clave del éxito, como con cualquier funcionalidad basada en LLM, es medir el desempeño e iterar sobre las implementaciones. Lo repetimos: habría que considerar agregar complejidad solo cuando mejora los resultados de manera demostrable4. El mismo artículo trae una recomendación de ruta más específica: empieza con prompts simples, optimízalos con una evaluación exhaustiva, y agrega sistemas agénticos de varios pasos solo cuando las soluciones más simples se queden cortas4.
Aplicado a la verificación, los criterios de decisión se reducen a unas pocas líneas:
- ¿Esta tarea se va a ejecutar repetidamente? Un script de una sola vez, un procesamiento de datos ad hoc, un trabajo de tres minutos que piensas mirar: montar un mecanismo de visto bueno es una pérdida neta. Las cosas que se ejecutan repetidamente, que otros modifican o que se ejecutan cuando no estás cerca: ahí vale la pena.
- ¿Quién carga con el costo de un error? Corriges mal un typo, lo reviertes tú mismo y listo. Rompes la lógica de facturación y el costo lo carga contabilidad. Cuanto más aguas abajo esté el costo y más difícil sea revertirlo, más deberías ponerle una compuerta por adelantado.
- ¿Cuánto tiempo dedicas ahora a verificarla? Si cada vez tienes que abrir tres páginas a mano y compararlas, poner esa comparación de tres páginas en un script es lo que más merece automatizarse: ya estás pagando ese costo, solo que no lo habías notado.
Un caso más que merece mención aparte: algunas comprobaciones ya las tienes, solo que no las conectaste al agente. Esa suite de pruebas del proyecto, ese comando de lint, ese script de compilación: lo más probable es que ya existieran. Escribirlos en la descripción de la tarea o convertirlos en una herramienta no cuesta casi nada, pero la naturaleza de la sesión cambia. Este es el paso de mayor retorno, y es el punto de partida de las próximas lecciones de este curso.
💻 Ejercicios
Resumen
- Claude se detiene cuando el trabajo parece terminado. Sin una comprobación que pueda ejecutar, «parece terminado» es la única señal disponible, y tú te conviertes en el bucle de verificación: cada error espera a que tú lo notes1.
- La documentación oficial le pone nombre a esta brecha: la brecha de confiar-y-después-verificar, donde Claude produce una implementación de apariencia plausible que no maneja los casos límite. La segunda mitad de la solución que la acompaña es igual de importante: si no lo puedes verificar, no lo lances1.
- La línea entre afirmaciones y evidencia es «si una segunda persona puede volver a ejecutar esto exactamente igual». Haz que Claude muestre evidencia —la salida de las pruebas, el comando que ejecutó y lo que devolvió, una captura de pantalla del resultado— y no afirmaciones de éxito. Revisar evidencia es más rápido que volver a ejecutar la verificación tú mismo, y funciona para las sesiones que no estuviste mirando1.
- Los agentes son sistemas no deterministas: incluso con las mismas condiciones iniciales pueden generar respuestas variadas2; incluso con prompts idénticos, no hay garantía de que las decisiones de distintas ejecuciones coincidan3. Así que el supuesto de la evaluación tradicional —«dada la entrada X, sigue el camino Y, produce la salida Z»— falla3: puntos de partida idénticos pueden producir caminos completamente distintos pero válidos3.
- Los errores en los sistemas de agentes se componen: que un paso falle puede llevar a los agentes a explorar trayectorias completamente distintas, con resultados impredecibles3. La autonomía trae costos más altos y el potencial de errores que se componen, así que se recomiendan pruebas exhaustivas en entornos de sandbox con guardrails4.
- La salida es darle una comprobación que se pueda ejecutar. Con algo que produzca un aprobado o un fallido, el bucle se cierra solo: hace el trabajo, ejecuta la comprobación, lee el resultado, itera hasta que pasa1. La comprobación puede ser una suite de pruebas, el código de salida de una compilación, un linter, un script que compare la salida con un fixture, o una captura de pantalla del navegador comparada con un diseño1.
- Durante la ejecución, deja que el agente obtenga la «ground truth» del entorno en cada paso (resultados de herramientas, resultados de la ejecución de código) para evaluar su progreso, y no de su propio razonamiento4.
- El LLM operará potencialmente durante muchos turnos, y debes tener cierto nivel de confianza en su toma de decisiones4, pero esa confianza tiene que venir de algún lado.
- No envuelvas cada cosita en un mecanismo completo de visto bueno. Habría que considerar agregar complejidad solo cuando mejora los resultados de manera demostrable4; revisa primero si esta tarea se ejecuta repetidamente, quién carga con el costo de los errores y cuánto tiempo dedicas ahora a verificarla a mano.
- El paso de mayor retorno suele ser este: esa suite de pruebas, ese comando de lint, ese script de compilación de tu proyecto ya existen, solo que todavía no se los conectaste al agente.
>> Lección 2: Qué verificar: primero el estado final, el proceso como respaldo