No puedes hacer aserciones sobre el modelo.
Ejecuta el mismo prompt dos veces y obtendrás dos frases distintas, ambas correctas. Eso no es un problema de testabilidad que puedas resolver con ingeniería: es la naturaleza del componente. Así que el instinto que dice «las funciones de IA no se pueden probar de verdad» acierta en la primera mitad y saca la conclusión equivocada.
Todo lo que rodea al modelo es código ordinario, determinista y con excelente testabilidad. El bucle, los topes, el análisis, las herramientas, las compensaciones, la representación: todo se puede probar exactamente igual que pruebas cualquier cosa, y todo eso es donde vivían de verdad los fallos de este libro. Ni un solo capítulo hasta ahora ha descrito un fallo que fuera culpa del modelo.
Simula en la frontera que es tuya
El capítulo 1 puso al proveedor detrás de un driver para que existiera exactamente una costura. Aquí es donde se amortiza:
beforeEach(function () {
Http::preventStrayRequests();
Http::fake(['*' => Http::response(['error' => 'boom'], 500)]);
});
Http::fake es la mitad obvia. preventStrayRequests es la importante.
Sin ella, una petición que tu simulación no cubra sale a internet de verdad. En una base de código de IA eso significa una suite de pruebas que llama calladamente a una API de pago —despacio, de forma no determinista y a costa de alguien. Peor: significa que una prueba puede pasar porque llegó por accidente a producción.
Actívala globalmente, no por fichero de pruebas. La primera vez que haga fallar una prueba que no esperabas, ya se habrá amortizado.
Prueba el bucle, no el modelo
El bucle de agente del capítulo 8 es control de flujo puro sobre un valor que envía el proveedor. Dale ese valor directamente:
- Una respuesta con
stop_reason: end_turn→ el bucle sale y publica. - Una respuesta con
pause_turny sin bloques de herramienta → el bucle continúa. Esta es la prueba de regresión del fallo que hacía que un turno pausado pareciera terminado, y mantenerla no cuesta nada. - Una respuesta con
max_tokens→ se añade un mensaje de error y se fijahasError. - Una respuesta con
refusal→ un mensaje de negativa, y ningún reintento. - Diez respuestas seguidas con herramientas → el bucle para en el tope de iteraciones.
Ninguna llama a un modelo. Todas prueban el código donde están los errores interesantes. Cuando un proveedor añada una razón de parada nueva, añades un caso y descubres de inmediato qué hace tu bucle con ella.