- Clasificar errores antes de reintentar.
- Diseñar retries con backoff, jitter y límite.
- Escalar a revisión humana sin perder estado.
Clasifica antes de actuar
- Transitorio: 429, 503, timeout, conexión rota. Reintento con backoff.
- LLM-recuperable: formato JSON incorrecto, campo faltante. Reintento con corrección explícita.
- Usuario-recuperable: falta dato, permiso o aprobación. Preguntar o pausar.
- Definitivo: credencial inválida, recurso no existe, política bloqueada. Parar y reportar.
type AgentError =
| { kind: "transient"; code: 429 | 503 | "timeout"; retryAfterMs?: number }
| { kind: "model_format"; message: string }
| { kind: "needs_human"; reason: string }
| { kind: "fatal"; reason: string };
const retryPolicy = {
maxAttempts: 4,
initialDelayMs: 1000,
backoff: 2,
jitter: true,
};Estado mínimo para no entrar en spiral
{
"task_id": "research-2026-07-05-001",
"step": "fetch_sources",
"attempts": 2,
"last_error": "503 from search API",
"next_retry_at": "2026-07-05T10:31:00Z",
"fallback": "use cached sources",
"human_review": false
}Patrón de recuperación recomendado
- Ejecuta herramienta con timeout.
- Si falla, clasifica el error en código, no en texto libre.
- Si es transitorio, espera con backoff y registra intento.
- Si agota intentos, cambia a fallback o escala a humano.
- Resume el estado, no todo el historial, para continuar.
Fuentes oficiales
Si has guardado la evidencia de esta lección, continúa con «Evals, logs y observabilidad». Si no, repite la comprobación antes de avanzar.