Errores, retries y rate limits

Resumen

Cuando manejas errores de OpenAI API en producción, necesitas una capa que responda con inteligencia cuando algo falla, en lugar de simplemente volver a ejecutar el código como haríamos en una demo. Esta guía es para desarrolladores que construyen apps reales con OpenAI y quieren agregar resiliencia profesional a su infraestructura.

Una demo falla y no pasa nada: reinicias y listo. Pero una app en producción necesita reintentar, esperar y avisar qué está pasando. Aquí construimos exactamente esa capa protectora, un wrapper que envuelve las llamadas a la API y las hace más robustas.

Qué es una capa de manejo de errores y por qué la necesitas

Una capa de manejo de errores es una función intermedia que envuelve tus llamadas a OpenAI para capturar fallos, esperar y reintentar automáticamente. En lugar de que tu app se caiga ante el primer error, esta capa le da varias oportunidades de conectarse.

Para crearla, agregamos un archivo nuevo dentro del package app llamado safe_client.py [00:24]. Este archivo tiene una única función: safe_openai_call.

¿Para qué sirve un wrapper en una API? Un wrapper es una función que envuelve otra llamada para agregar comportamiento extra, como reintentos o manejo de errores, sin modificar la lógica original de tu app.

Qué errores de OpenAI vamos a capturar

La función importa time porque necesitamos esperar antes de volver a intentar [00:44]. Desde OpenAI importamos tres tipos de errores que vamos a manejar de forma específica:

  • RateLimitError: cuando superas el límite de peticiones permitidas.
  • ApiTimeoutError: cuando la API tarda demasiado en responder.
  • ApiError: un error general de la API.

Cada uno recibe un tratamiento distinto, pero todos comparten la misma lógica de espera y reintento.

Cómo funciona la función safe_openai_call

Esta función recibe dos parámetros: un callback, que es la función que queremos volver a intentar, y una cantidad de intentos o retries, que definimos inicialmente en tres [01:04].

La lógica es directa: por cada intento dentro del rango de retries disponibles, ejecuta el callback. Si algo sale mal, entra en acción el manejo específico según el tipo de error.

  • Ante un RateLimitError, espera dos segundos, imprime un mensaje avisando que es rate limit y que está reintentando, y usa time para pausar antes del siguiente intento [01:20].
  • Ante un ApiTimeoutError, la lógica es casi idéntica, pero el mensaje cambia a timeout en lugar de rate limit [01:38].
  • Ante un ApiError, imprime que hay un error de la API, muestra cuál es y avisa que reintentará tras esperar los segundos definidos [01:50].

Si el error no es ninguno de esos tres, la función levanta una excepción con el mensaje "No se pudo completar la llamada a OpenAI" [02:12]. Así evitas que un fallo desconocido pase desapercibido.

¿Qué es un RateLimitError en OpenAI? Es el error que aparece cuando envías más peticiones de las permitidas en un periodo. La solución habitual es esperar unos segundos y reintentar, justo lo que hace esta capa.

Por qué usamos un lambda para reintentar la llamada

En main.py borramos todo y lo reemplazamos por los imports del client, del nuevo safe_client y de la llamada open_ai_call [02:24]. La llamada se envuelve en una variable result.

Aquí viene lo interesante: dentro de safe_openai_call pasamos un lambda, una función anónima que contiene el llamado al endpoint de OpenAI [02:44]. Ese endpoint recibe el modelo gpt-5.4 y un input: "genera una campaña corta".

¿Por qué un lambda y no la llamada directa? Porque es la única forma de que la capa pueda volver a ejecutar la llamada tantas veces como sea necesario. Si pasáramos el resultado ya ejecutado, no habría nada que reintentar. Como el número de intentos ya está definido en tres, no hace falta pasarlo como parámetro [03:08].

Cómo probar y forzar errores para validar la capa

Al ejecutar main.py en la terminal, la API devuelve una respuesta completa: una campaña corta con eslogan "no dejes para mañana, haz que pase hoy", mensajes principales, copies para tres posts de redes, llamados a la acción como "descúbrelo hoy" y hasta una idea visual [03:20]. Pero el objetivo no era medir la calidad del resultado, sino confirmar que todo funciona incluso pasando por el cliente protector.

Después llega la prueba real: forzar un error. Simulamos una API mal configurada agregando una letra extra al valor de la API key [04:18].

  1. Al ejecutar de nuevo, aparece el error 401 indicando que la API key es incorrecta.
  2. La respuesta hashea la clave para que no quede expuesta.
  3. El sistema reintenta tres veces, exactamente el número seteado en la capa de protección [04:30].

Al corregir la API key, guardarla y volver a ejecutar, la app responde con normalidad porque se reconecta directamente [04:52]. Esa es la señal de que el wrapper está cumpliendo su función.

¿Qué significa el error 401 en OpenAI? Indica que la API key es inválida o está mal configurada. Por seguridad, la respuesta oculta la clave con un hash y te dirige al enlace donde puedes generar una nueva.

Con esta capa de resiliencia, ya sabes manejar errores comunes y aplicar prompt caching desde la terminal. El siguiente paso es llevar estos conceptos a la interfaz que venimos construyendo, y en la clase final desplegar el proyecto con los requisitos de producción para un entorno estable.

¿Ya probaste forzar tus propios errores para ver cómo responde tu capa protectora? Cuéntame en los comentarios qué tipo de error te costó más manejar.