Multi-Agent Coordination en 2026: Por Qué 3 Agentes Mal Coordinados Son Peores Que 1 Agente Bien Hecho
Aprende a construir sistemas multi-agente que funcionan en producción. Patrón orchestrator-worker, contratos tipados con Pydantic, manejo de errores y memoria compartida. Guía práctica 2026.
3 Agentes Mal Coordinados Son Peores Que 1 Agente Bien Hecho
Si tu sistema multi-agente tiene tres LLMs hablando entre sí para resolver una tarea que un solo GPT-4 haría en un paso, no es una arquitectura avanzada.
*Es un problema de latencia mal diseñado con sobreingeniería.*
La conversación actual asume que "más agentes = mejor descomposición del problema". La industria promociona los agentic workflows como si poner varios LLMs a conversar fuera inherentemente superior.
La realidad es la opuesta.
Sin un protocolo de coordinación explícito — contratos de entrada/salida, memoria compartida con políticas de acceso, y manejo de errores por timeout — un sistema multi-agente introduce más puntos de fallo, latencia acumulada, y deriva semántica que un solo agente bien prompteado.
Este artículo es para cuando SÍ necesitas multi-agente. Y para que no lo hagas mal.
---
El Problema: El Acoplamiento Frágil Entre Agentes
Cuando el orquestador pasa contexto en texto libre a un subagente, y este devuelve otro texto libre, cualquier variación en el formato o semántica cascada al siguiente agente.
Esto es acoplamiento por contenido. El término viene de sistemas distribuidos: dos componentes comparten un formato de datos implícito que se rompe ante cualquier cambio.
En la práctica se ve así:
❌ Anti-patrón común:
```
orquestador → "Analiza este artículo y dime los puntos clave"
subagente → "Los puntos clave son: 1. bla 2. bla 3. bla"
orquestador → "Ahora escribe un tuit sobre esos puntos"
subagente → "Aquí tienes un hilo de Twitter..."
```
El problema: el segundo subagente recibe "Los puntos clave son: 1. bla 2. bla 3. bla". No hay schema. No hay validación. Si el primer agente cambia el formato, el segundo recibe basura y tú no te enteras hasta que alguien se queja en producción.
✅ Patrón correcto:
```
orquestador → contrato tipado {topic: str, key_points: list[str], source_url: str}
subagente → devuelve JSON validado contra Pydantic/Zod
orquestador → pasa el campo key_points al siguiente agente con su propio contrato
```
Cada agente tiene una interfaz explícita. Como una API entre microservicios, pero entre LLMs.
---
La Evidencia: Por Qué Más Agentes No Escala Linealmente
Añadir agentes especializados no escala como esperas. Cada agente introduce:
Latencia de inferencia: 1-5 segundos por llamada a LLM.
Coste de tokens: cada interacción suma.
Ruido semántico: cada agente reinterpreta el input a su manera.
En benchmarks internos de sistemas como AutoGen, duplicar el número de agentes no duplica la precisión en tareas complejas. A menudo la degrada.
El motivo es el error compounding: errores pequeños en agentes tempranos se amplifican en etapas posteriores. Piensa en el teléfono escacharrado, pero con cada repetición el mensaje se reescribe desde cero.
El coste computacional crece O(n × m) donde n es agentes y m es profundidad de coordinación. La precisión raramente escala mejor que O(log n).
*Cada agente que añades debe justificar su existencia con una reducción medible de error o latencia, no con la promesa teórica de "especialización". *
---
Los 3 Patrones de Coordinación que Debes Conocer
La literatura técnica mezcla estos patrones como si fueran intercambiables. No lo son. Cada uno tiene implicaciones distintas en latencia, coste y robustez.
1. Supervisor
Un agente observa y critica, pero no descompone tareas. Útil para validación y control de calidad.
Cuándo usarlo: cuando tienes un pipeline existente y quieres añadir una capa de verificación sin reestructurar todo.
Riesgo: el supervisor puede alucinar correcciones. Si no tiene un schema de validación, puede "corregir" cosas que ya estaban bien.
2. Orchestrator (el patrón estrella)
El agente principal descompone activamente la tarea y delega a subagentes. Es el patrón más usado en agentic workflows y el que implementamos en este artículo.
Cuándo usarlo: tareas complejas que requieren múltiples dominios de conocimiento (investigación web + análisis + generación de contenido).
Riesgo: el cuello de botella es el orquestador. Si su prompt de descomposición es malo, todo el sistema falla.
3. Hierarchical
Sub-orquestadores que a su vez delegan. Necesario cuando la tarea original es demasiado compleja para un solo orquestador.
Cuándo usarlo: sistemas enterprise con pipelines de más de 10 pasos.
Riesgo: latencia acumulativa. Un orquestador que llama a otro que llama a otro... el tiempo de respuesta puede dispararse a minutos.
El patrón más infravalorado: parallel fan-out con aggregation
La mayoría implementa coordinación secuencial (agente A → B → C). Las tareas que más se benefician de multi-agente son las que permiten ejecución paralela.
```
orquestador → llama simultáneamente a B, C, D
↳ agrega resultados
```
Esto reduce la latencia total de O(n) a O(1) y minimiza el error compounding porque los subagentes no dependen unos de otros.
El reto técnico: ¿cómo unifica el orquestador respuestas contradictorias de múltiples subagentes? Ahí entra el contrato de agregación.
---
El Framework: Protocolo de Contrato Tipado Entre Agentes
Vamos a implementarlo. Este es el patrón que uso en producción para sistemas multi-agente que no se rompen.
Paso 1: Define contratos de interfaz para cada subagente
Especifica el schema exacto de entrada, el schema exacto de salida, y el contexto compartido.
Usa modelos tipados. No diccionarios sueltos.
```python
from pydantic import BaseModel
from typing import List, Optional
class ResearchInput(BaseModel):
topic: str
max_sources: int = 5
include_summary: bool = True
class ResearchOutput(BaseModel):
topic: str
sources: List[str]
key_findings: List[str]
summary: Optional[str] = None
class WriterInput(BaseModel):
key_findings: List[str]
tone: str = "professional"
max_words: int = 500
class WriterOutput(BaseModel):
draft: str
word_count: int
sections: List[str]
```
Cada agente recibe su contrato y devuelve su contrato. El orquestador valida ambos antes de pasar al siguiente paso.
Paso 2: Implementa el bucle de orquestación con límite de iteraciones
El orquestador nunca debe poder hacer llamadas infinitas a subagentes.
```python
class Orchestrator:
def __init__(self, max_steps: int = 10):
self.max_steps = max_steps
self.step_count = 0
self.history = []
async def run(self, task: str) -> dict:
context = {"original_task": task}
while self.step_count < self.max_steps:
next_action = await self.plan_next(context)
if next_action["type"] == "complete":
return next_action["result"]
result = await self.execute_subagent(next_action)
context.update(result)
self.history.append(next_action)
self.step_count += 1
raise MaxStepsExceededError(f"Exceeded {self.max_steps} steps")
```
Fija max_steps entre 5 y 10. Añade un mecanismo de decisión de finalización: un validation check o un critic agent que confirme que la tarea está completa.
Paso 3: Establece memoria compartida con alcance definido
Cada subagente solo accede al contexto que necesita. Principio de mínimo privilegio.
Usa un buffer de mensajes estructurado, no el historial crudo del LLM.
```python
from typing import Dict, Any
class SharedMemory:
def __init__(self):
self._store: Dict[str, Any] = {}
self._access_policies: Dict[str, List[str]] = {}
def register_agent(self, agent_id: str, allowed_keys: List[str]):
self._access_policies[agent_id] = allowed_keys
def read(self, agent_id: str) -> Dict[str, Any]:
allowed = self._access_policies.get(agent_id, [])
return {k: v for k, v in self._store.items() if k in allowed}
def write(self, agent_id: str, data: Dict[str, Any]):
allowed = self._access_policies.get(agent_id, [])
for key, value in data.items():
if key in allowed:
self._store[key] = value
```
Cada agente solo ve lo que necesita ver. El orquestador controla los permisos.
Paso 4: Manejo de fallos por subagente individual
Si un subagente falla (timeout, formato inválido, alucinación), el orquestador debe poder reintentar, derivar a otro agente, o degradar gracefulmente.
```python
import asyncio
from tenacity import retry, stop_after_attempt, wait_exponential
class SubAgent:
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=1, max=10)
)
async def execute(self, input_data: BaseModel) -> BaseModel:
try:
response = await asyncio.wait_for(
self._call_llm(input_data),
timeout=15.0
)
return self.output_model.model_validate(response)
except asyncio.TimeoutError:
raise AgentTimeoutError(f"Agent {self.name} timed out")
except ValidationError as e:
raise AgentValidationError(f"Invalid output: {e}")
```
Tres reintentos con backoff exponencial. Timeout de 15 segundos por agente. Validación del output contra el schema antes de devolverlo.
Si después de 3 intentos sigue fallando, el orquestador deriva a un agente de respaldo o degrada:
```python
async def execute_with_fallback(self, task: dict) -> dict:
try:
return await self.primary_agent.execute(task)
except AgentError:
if self.fallback_agent:
return await self.fallback_agent.execute(task)
return {"error": True, "partial_result": task.get("fallback_data")}
```
Paso 5: Logging y trazado de cada paso de coordinación
Registra qué agente llamó a qué agente, con qué input, qué output devolvió, cuánto tardó, y si hubo reintentos.
```python
class TraceStep(BaseModel):
step: int
agent: str
input_schema: str
output_schema: str
duration_ms: float
retries: int
success: bool
class TraceLog:
def __init__(self):
self.steps: List[TraceStep] = []
def log(self, step: TraceStep):
self.steps.append(step)
def export(self) -> dict:
return {
"total_steps": len(self.steps),
"total_duration_ms": sum(s.duration_ms for s in self.steps),
"total_retries": sum(s.retries for s in self.steps),
"failed_steps": [s for s in self.steps if not s.success],
}
```
Usa LangFuse, LangSmith o tu propio sistema de tracing. Sin trazado, estás operando a ciegas.
---
¿Realmente Necesitas Multi-Agent?
Antes de implementar nada, hazte esta pregunta.
Un solo agente con tool-calling y un buen prompt puede resolver el 80% de los casos de uso que la industria vende como "multi-agent workflow".
*La primera regla de la coordinación multi-agente es saber cuándo no usarla. *
Usa multi-agente solo cuando:
La tarea requiere múltiples dominios de conocimiento que ningún prompt puede cubrir.
Necesitas paralelización real para reducir latencia.
Tienes agentes especializados que ya existen y quieres orquestarlos.
El coste de error de un agente monolítico es inaceptable.
Si no cumples al menos dos de estas condiciones, un solo agente bien prompteado con tool-calling es la respuesta correcta.
---
Herramientas para 2026
LangGraph (Python): para grafos de estado complejos con ciclos controlados. El más maduro para el patrón orchestrator-worker.
CrewAI: buen punto de partida para equipos con roles definidos. Limitado en control fino.
AutoGen (Microsoft): patrones de conversación multi-agente con manejo de contexto compartido.
Semantic Kernel (Microsoft): integración enterprise con C#/.NET.
LangFuse: tracing open source. Mejor que LangSmith en privacidad de datos y coste a escala.
---
La Tesis, Resumida
*La coordinación multi-agente no es un problema de cuántos LLMs pones a hablar. Es un problema de diseño de protocolos. *
Los contratos tipados entre agentes, la memoria con mínimo privilegio, el manejo de fallos por agente individual, y el límite de iteraciones no son opcionales. Son la diferencia entre un sistema que escala y uno que introduce más problemas de los que resuelve.
En 2026, la habilidad más valiosa no es saber promptear un LLM. Es saber diseñar sistemas donde varios LLMs cooperen sin romperse entre sí.
Y eso empieza por aceptar que más agentes no es mejor. Es solo más complejo.
Lee el artículo completo en brianmenagomez.com
Más sobre mis servicios en brianmenagomez.com
Herramientas: Conversor IAE CNAE · Gestorias cerca de ti · Calculadora IRPF

