Patrones de arquitectura para agentes de IA autónomos
El agente monolítico es un callejón sin salida
Empezamos como todo el mundo. Un único prompt, un modelo, una lista de herramientas, y a ver qué pasa. El primer agente que pusimos en producción procesaba emails de clientes de una empresa de logística. Clasificaba, extraía datos y generaba un borrador de respuesta. Todo en una sola llamada.
Funcionó tres semanas. Después, un cliente envió un email con un PDF adjunto que contenía una imagen escaneada de un albarán. El agente intentó parsear el PDF, falló, reintentó con una estrategia diferente, falló otra vez, y entró en un bucle de razonamiento que consumió 47.000 tokens antes de que el circuit breaker lo cortara. Coste: 1.20 euros por un email. La media era 0.03.
Ese incidente nos forzó a repensar la arquitectura. Lo que sigue son los cuatro patrones que usamos ahora, con los tradeoffs reales de cada uno.
Patrón 1: ReAct con límites estrictos
ReAct (Reasoning + Acting) es el patrón más simple que puede funcionar en producción. El agente razona sobre la tarea, decide qué herramienta usar, observa el resultado, y repite hasta completar la tarea o alcanzar un límite.
La clave está en los límites. Sin ellos, ReAct es un cheque en blanco. Nuestras restricciones:
- Máximo de pasos: 8 para tareas simples, 15 para complejas. Si el agente no resuelve en 15 pasos, escala.
- Presupuesto de tokens: techo por ejecución. Al 80% del límite, el agente recibe una instrucción de comprimir su razonamiento.
- Timeout por herramienta: 30 segundos. Si una API externa no responde, el agente registra el fallo y decide si usa un fallback o escala.
- Lista de herramientas cerrada: el agente solo puede usar las herramientas que le asignamos. No descubre herramientas dinámicamente.
El ciclo es: Observar -> Pensar -> Actuar -> Verificar resultado -> Repetir o finalizar.
Dónde funciona bien: tareas con 2-5 pasos, con herramientas predecibles, donde el modelo puede razonar linealmente. Clasificación de documentos con extracción de campos. Consultas a APIs con interpretación de resultados. Generación de respuestas basadas en datos.
Dónde falla: tareas que requieren coordinación entre múltiples fuentes de datos, o donde el espacio de decisiones es demasiado amplio para un solo agente.
Implementación práctica: usamos LangGraph con un grafo de un solo nodo que ejecuta el ciclo ReAct. El estado incluye el historial de acciones, tokens consumidos, y un contador de pasos. La condición de salida es: tarea completada, límite alcanzado, o error no recuperable.
Patrón 2: Supervisor con trabajadores especializados
Este es nuestro patrón por defecto para tareas complejas. Un agente supervisor orquesta varios agentes trabajadores, cada uno especializado en una capacidad concreta.
La estructura:
Supervisor
├── Lector de documentos (extraccion, OCR)
├── Consultor de datos (APIs externas, bases de datos)
├── Generador de salida (respuestas, informes)
└── Validador (verifica calidad del resultado)
El supervisor no ejecuta herramientas directamente. Su trabajo es: recibir la tarea, descomponerla en subtareas, asignar cada subtarea al trabajador adecuado, recibir resultados, decidir si hacen falta más pasos, y componer la salida final.
Cada trabajador es un agente ReAct acotado con su propio conjunto de herramientas y límites. El lector de documentos solo tiene acceso a herramientas de parseo y OCR. El consultor de datos solo a APIs y bases de datos. Esta separación tiene tres beneficios:
Seguridad. Un trabajador comprometido o alucinante no puede ejecutar herramientas que no le corresponden. El lector de documentos no puede enviar emails.
Testabilidad. Puedes testear cada trabajador en aislamiento con inputs y outputs conocidos.
Coste. Cada trabajador puede usar un modelo diferente. El clasificador usa Haiku (barato, rápido). El generador de salida usa Sonnet (mejor calidad de texto). Solo el supervisor necesita un modelo con buena capacidad de razonamiento.
El tradeoff principal es latencia. Una tarea que un agente monolítico resolvería en 3 segundos puede tardar 8-12 segundos con supervisor + trabajadores porque hay múltiples roundtrips al LLM. Para tareas de back-office, eso es irrelevante. Para interacciones en tiempo real con usuarios, puede ser un problema.
Implementación: en LangGraph, el supervisor es un nodo que contiene un subgrafo por cada trabajador. El estado global del grafo contiene la tarea, las subtareas, los resultados parciales, y el resultado final. Las transiciones entre nodos están condicionadas por las decisiones del supervisor.
Patrón 3: Máquina de estados finitos con LLM
Este patrón es para los procesos donde el flujo es conocido pero las decisiones dentro de cada paso requieren un LLM. Piensa en un workflow de aprobación de facturas:
Recibir factura -> Extraer datos -> Validar contra pedido ->
[OK] -> Registrar en ERP -> Notificar
[Error] -> Solicitar correccion -> Esperar -> Volver a validar
[Duda] -> Escalar a humano
El flujo es una máquina de estados. Cada transición es determinista. Pero dentro de cada estado, el LLM decide. En “Extraer datos,” el agente parsea el documento. En “Validar contra pedido,” compara campos extraídos con datos del ERP. En “Solicitar corrección,” redacta un email al proveedor.
La ventaja sobre el patrón supervisor: es mucho más predecible. El flujo no puede salirse de los estados definidos. No hay posibilidad de que el agente decida “voy a hacer algo completamente diferente.” Los costes son predecibles porque cada estado tiene un presupuesto fijo de tokens.
La desventaja: es rígido. Si llega un caso que no encaja en los estados definidos, no hay forma de manejarlo sin modificar el flujo. Cada caso nuevo requiere actualizar el código, no solo ajustar un prompt.
Cuándo lo usamos: para procesos de negocio regulados o con SLA estrictos. Procesamiento de facturas, flujos de aprobación, onboarding de clientes. Cualquier proceso donde la predecibilidad es más importante que la flexibilidad.
Implementación: LangGraph es ideal para esto. Cada estado es un nodo. Las transiciones son aristas condicionales. El estado del grafo contiene los datos del proceso y el resultado de cada paso. Podemos serializar el estado completo, lo que permite pausar y reanudar procesos (por ejemplo, cuando se espera aprobación humana).
Patrón 4: Event-driven con agentes reactivos
El patrón para sistemas que necesitan responder a eventos en tiempo real sin un orquestador central.
La arquitectura:
Cola de eventos (Kafka / Redis Streams)
├── Agente de clasificacion (escucha: email.received)
├── Agente de procesamiento (escucha: document.classified)
├── Agente de notificacion (escucha: task.completed, task.failed)
└── Agente de monitorizacion (escucha: *.*)
Cada agente se suscribe a tipos de eventos específicos. Cuando llega un evento, lo procesa y puede emitir nuevos eventos que activan otros agentes. No hay un controlador central; el flujo emerge de la composición de eventos.
Este patrón es el más escalable. Puedes añadir o quitar agentes sin tocar los existentes. Si necesitas un nuevo tipo de procesamiento, despliegas un agente nuevo que escuche los eventos relevantes. Si un agente falla, los eventos quedan en la cola y se reintentan.
El riesgo principal lo mencionamos en nuestro whitepaper sobre agentes de IA: las tormentas de eventos. Un evento que genera otro evento que genera otro puede crear cascadas que consumen recursos sin control. La solución tiene tres capas:
- Deduplicación. Cada evento tiene un ID único. Si un agente ya procesó ese ID, lo ignora.
- Rate limiting. Cada agente tiene un máximo de ejecuciones por minuto. Si lo alcanza, los eventos quedan en la cola hasta que haya capacidad.
- Dead letter queue. Eventos que fallan tres veces van a una cola muerta para revisión manual.
Cuándo lo usamos: para sistemas que ya tienen una arquitectura de microservicios basada en eventos. Si tu backend ya usa Kafka o RabbitMQ, añadir agentes como consumers es natural. Si tu arquitectura es monolítica, este patrón introduce complejidad que probablemente no necesitas.
Componentes transversales
Independientemente del patrón, hay tres componentes que implementamos en todos los proyectos.
Structured outputs con validación
Nunca dejamos que un agente devuelva texto libre cuando necesitamos datos estructurados. Cada herramienta define un schema Pydantic o Zod para su salida. Si la salida del LLM no conforma al schema, se rechaza y se reintenta con una instrucción explícita del error.
En la práctica, Claude y GPT-4o cumplen con el schema correcto el 95-98% de las veces en la primera llamada. Pero ese 2-5% restante es suficiente para generar decenas de errores al día en volumen alto. La validación es obligatoria, no opcional.
Observabilidad integrada
Cada agente emite trazas OpenTelemetry con spans personalizados para cada tipo de acción. Las trazas incluyen: tokens de entrada y salida, latencia de cada llamada, resultado de cada herramienta, y decisión del agente en cada paso.
Usamos LangSmith para visualización y debugging, pero las trazas van también a nuestro stack de observabilidad general (Grafana + Loki) para correlacionar con métricas de infraestructura.
Circuit breakers y fallbacks
Cada herramienta que un agente puede llamar tiene un circuit breaker. Si falla 3 veces consecutivas, se desactiva durante 5 minutos. El agente recibe una notificación de que la herramienta no está disponible y puede decidir usar un fallback o escalar.
A nivel de agente, si la tasa de error supera el 20% en una ventana de 5 minutos, todo el agente se desactiva y las tareas se enrutan a la cola de procesamiento manual. Esto previene degradaciones silenciosas donde el agente sigue funcionando pero produciendo resultados de baja calidad.
Cómo elegir el patrón correcto
La decisión depende de tres variables:
| Variable | ReAct | Supervisor | Máquina de estados | Event-driven |
|---|---|---|---|---|
| Complejidad de la tarea | Baja-media | Alta | Media-alta | Variable |
| Predecibilidad del flujo | Baja | Media | Alta | Baja |
| Requisitos de latencia | Bajos | Medios | Bajos | Medios |
| Facilidad de testing | Media | Alta | Muy alta | Media |
| Coste de infraestructura | Bajo | Medio | Bajo | Alto |
La regla práctica: empieza con ReAct. Si se queda corto, pasa a supervisor. Si el flujo es conocido y regulado, usa máquina de estados. Si ya tienes una arquitectura de eventos, usa event-driven.
No mezcles patrones sin necesidad. Hemos visto equipos que implementan un supervisor que dentro tiene máquinas de estado que emiten eventos que activan otros supervisores. El resultado es inmantenible. Elige un patrón principal y úsalo consistentemente.
Para profundizar en estos patrones aplicados a casos de uso reales, puedes consultar nuestro servicio de IA y Machine Learning. Si estás evaluando qué patrón se adapta a tu caso, nuestro equipo de consultoría ofrece assessments técnicos de 2 semanas.
También recomendamos revisar nuestra serie sobre ingeniería de datos para entender cómo preparar los datos que alimentarán a tus agentes.

