Ir al contenido principal
Circuit Breaker en Agentes IA: Para Antes de Arder

Circuit Breaker en Agentes IA: Para Antes de Arder

AI Integration
••6 min read•Por Daily Miranda Pardo

Tu agente llama al LLM. Falla. Reintenta. Falla de nuevo. Cuatro reintentos con backoff exponencial: 1s, 2s, 4s, 8s. Quince segundos de espera. Y mientras tanto, los cuarenta usuarios activos en ese momento están haciendo exactamente lo mismo.

El LLM lleva dos minutos caído. Ningún reintento va a cambiar eso. Pero tu sistema sigue intentándolo, cuarenta veces por segundo, amplificando la presión sobre un servicio que no responde.

El retry te protege de los fallos transitorios. El circuit breaker te protege de los fallos sostenidos. Son dos patrones diferentes y ambos son necesarios en producción.

El cascade de fallos que no aparece en los logs

El fallo real del LLM dura 90 segundos. El impacto en tu sistema dura 10 minutos.

Sin circuit breaker, cada nuevo request activa su propia cadena de reintentos. Los timeouts se acumulan. El pool de conexiones se satura. Las latencias se disparan en toda la aplicación, no solo en las llamadas al LLM. Una caída de proveedor de 90 segundos se convierte en un incidente de 10 minutos porque cada request sigue intentando hasta agotar sus cuatro reintentos.

El circuit breaker corta ese ciclo. Cuando detecta que el servicio está caído, deja de intentarlo. Las peticiones que llegan durante la caída fallan rápido —en milisegundos, no en 15 segundos— y el sistema puede devolver una respuesta alternativa sin saturarse.

Esto es precisamente lo que el patrón de cadenas de fallback en agentes IA asume que ya tienes cuando menciona circuitBreaker.isHealthy(). Este artículo construye ese componente.

Tres estados, una sola regla

El circuit breaker tiene tres estados con transiciones predecibles:

CLOSED (circuito cerrado, operación normal): Las peticiones pasan al LLM con normalidad. El circuit breaker cuenta los fallos dentro de una ventana de tiempo. Si los fallos superan el umbral configurado, transiciona a OPEN.

OPEN (circuito abierto, cortado): Las peticiones fallan de inmediato sin llegar al LLM. El sistema responde en milisegundos con un fallback. Después de un tiempo configurable (típicamente 30 segundos), transiciona a HALF_OPEN para comprobar si el servicio se recuperó.

HALF_OPEN (probando recuperación): Deja pasar una petición de prueba. Si tiene éxito, el circuito cierra y vuelve a la operación normal. Si falla, vuelve a abrir.

La regla central: en estado OPEN, el sistema falla rápido y sirve una alternativa. Integrado con un servicio de agentes IA bien diseñado, el usuario no percibe la caída del proveedor.

Implementación completa en TypeScript

type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';

interface CircuitBreakerConfig {
  failureThreshold: number;       // Fallos para abrir
  monitoringWindow: number;       // Ventana en ms para contar fallos
  resetTimeout: number;           // ms en OPEN antes de probar
  halfOpenSuccessThreshold: number; // Éxitos para cerrar desde HALF_OPEN
}

class CircuitBreaker {
  private state: CircuitState = 'CLOSED';
  private failureTimestamps: number[] = [];
  private halfOpenSuccesses = 0;
  private openedAt: number | null = null;

  constructor(
    readonly name: string,
    private readonly config: CircuitBreakerConfig
  ) {}

  isHealthy(): boolean {
    this.maybeTransitionToHalfOpen();
    return this.state !== 'OPEN';
  }

  recordFailure(): void {
    const now = Date.now();
    this.failureTimestamps = this.failureTimestamps.filter(
      ts => now - ts < this.config.monitoringWindow
    );
    this.failureTimestamps.push(now);

    if (this.state === 'HALF_OPEN') {
      this.open();
    } else if (this.failureTimestamps.length >= this.config.failureThreshold) {
      this.open();
    }
  }

  recordSuccess(): void {
    if (this.state === 'HALF_OPEN') {
      this.halfOpenSuccesses++;
      if (this.halfOpenSuccesses >= this.config.halfOpenSuccessThreshold) {
        this.close();
      }
    }
  }

  private maybeTransitionToHalfOpen(): void {
    if (
      this.state === 'OPEN' &&
      this.openedAt !== null &&
      Date.now() - this.openedAt >= this.config.resetTimeout
    ) {
      this.state = 'HALF_OPEN';
      this.halfOpenSuccesses = 0;
    }
  }

  private open(): void {
    this.state = 'OPEN';
    this.openedAt = Date.now();
    console.warn(`[CircuitBreaker:${this.name}] OPEN — ${this.failureTimestamps.length} fallos en ventana`);
  }

  private close(): void {
    const recoveryTime = this.openedAt ? Date.now() - this.openedAt : 0;
    this.state = 'CLOSED';
    this.failureTimestamps = [];
    this.halfOpenSuccesses = 0;
    this.openedAt = null;
    console.info(`[CircuitBreaker:${this.name}] CLOSED — recuperado en ${recoveryTime}ms`);
  }
}

Parámetros de partida recomendados:

  • failureThreshold: 5 — Cinco fallos dentro de la ventana abren el circuito
  • monitoringWindow: 60_000 — Ventana deslizante de 60 segundos
  • resetTimeout: 30_000 — 30 segundos en OPEN antes de probar recuperación
  • halfOpenSuccessThreshold: 2 — Dos éxitos consecutivos para cerrar definitivamente

Integración con el cliente de Anthropic en Next.js

// lib/circuit-breakers.ts — singleton compartido entre requests
export const anthropicBreaker = new CircuitBreaker('anthropic', {
  failureThreshold: 5,
  monitoringWindow: 60_000,
  resetTimeout: 30_000,
  halfOpenSuccessThreshold: 2,
});

// app/api/agent/route.ts
import Anthropic from '@anthropic-ai/sdk';
import { anthropicBreaker } from '@/lib/circuit-breakers';

const client = new Anthropic();

export async function callAgent(prompt: string): Promise<string> {
  if (!anthropicBreaker.isHealthy()) {
    return getFallbackResponse(prompt);
  }

  try {
    const response = await client.messages.create({
      model: 'claude-sonnet-4-6',
      max_tokens: 1024,
      messages: [{ role: 'user', content: prompt }],
    });

    anthropicBreaker.recordSuccess();
    const content = response.content[0];
    return content.type === 'text' ? content.text : '';

  } catch (error) {
    anthropicBreaker.recordFailure();
    throw error;
  }
}

El detalle que lo arruina todo

El circuit breaker debe ser un singleton de módulo. Si lo instancias por request en Next.js, cada petición tiene su propio conteo de fallos y el circuito nunca se abre.

// ❌ INCORRECTO — cada request instancia su propio circuit breaker
export async function POST(request: Request) {
  const breaker = new CircuitBreaker('anthropic', config); // nunca llega a abrir
  // ...
}

// ✅ CORRECTO — importas el singleton compartido
import { anthropicBreaker } from '@/lib/circuit-breakers';

En Vercel Edge con múltiples instancias simultáneas, el estado del circuito necesita almacenamiento externo (Redis o Vercel KV) para ser compartido entre instancias. En un servidor de proceso único o en un contenedor Docker, el singleton de módulo es suficiente.

Qué monitorizar

Dos métricas bastan para empezar: duración de apertura y tasa de respuestas en fallback.

Las transiciones de estado ya están logueadas en la implementación anterior. Para un equipo pequeño, una alerta cuando el circuito lleva más de 60 segundos abierto cubre el 90% de los casos relevantes. El timestamp de openedAt te da la duración del incidente del proveedor directamente, sin instrumentación adicional.

A medida que escales, añade la métrica de porcentaje de requests que se están sirviendo desde el fallback. Si supera el 5% sostenido, hay algo más que un fallo de proveedor.

Conclusión

El circuit breaker no previene los fallos del LLM. Los aísla. Tu sistema deja de amplificarlos, deja de saturarse bajo carga y puede servir una alternativa mientras espera que el proveedor se recupere.

La implementación completa son menos de 60 líneas de TypeScript. El coste de no tenerla se mide en incidentes que duran diez veces más de lo necesario.

Circuit Breaker para Agentes IA en TypeScript — Tres estados: CLOSED, OPEN, HALF-OPEN — dailymp.es

¿Tu agente en producción tiene circuit breaker? Si no estás seguro, probablemente no. Revisamos la arquitectura de tu sistema juntos →

Compartir artículo

LinkedInXWhatsApp

¿Procesos repetitivos en tu empresa?

Descarga gratis el Mapa de Automatización IA — los 5 procesos que más tiempo roban y cómo resolverlos.

Sin spam. Solo el PDF. Puedes darte de baja cuando quieras.

Escrito por Daily Miranda Pardo

Ayudo a empresas a automatizar procesos, crear agentes IA y conectar sistemas inteligentes.