El problema
La solicitud parece normal: revisar un caso de cliente y preparar una respuesta breve.
En trazas se ve otra cosa: el orchestrator lanzó 5 agentes,
tres de ellos hicieron casi la misma subtarea,
la cantidad de handoffs entre agentes llegó a 14 en un solo run,
y la respuesta final no se formó antes del timeout.
El sistema no cae de inmediato.
Empieza a hacer ruido: crecen duplicados, handoffs, cola y latency.
Analogía: imagina un turno en restaurante donde los meseros no repartieron mesas. Tres personas toman el mismo pedido y otras mesas esperan. Hay más trabajo, pero peor resultado. El caos multiagente en sistemas de IA funciona igual: más acciones y menos progreso útil.
Por qué pasa
El caos multiagente no aparece por la cantidad de agentes en sí, sino por falta de coordinación estricta entre ellos.
En producción normalmente ocurre así:
- los roles de agentes se solapan y una subtarea recibe varios owners;
- la delegación avanza sin límites claros de profundidad y número de transferencias;
- no existe una regla única de arbitration para decidir el resultado final;
tool_callduplicados desde distintos agentes multiplican carga;- sin stop reasons ni budget gates, el run tarda demasiado en converger.
El problema no es el enfoque multiagente en sí.
Varios agentes actúan sin un solo loop de control.
Fallos más frecuentes
En producción se ven cuatro patrones de caos multiagente con más frecuencia.
Solapamiento de roles (Role overlap)
Dos o más agentes toman la misma subtarea y devuelven resultados intermedios distintos.
Causa típica: no hay role map ni owner explícito de la subtarea.
Loop de delegación (Delegation loop)
El agente A delega en B, B delega en C, C vuelve a A. Desde fuera el run parece "activo", pero no hay progreso.
Causa típica: no hay límite de profundidad de delegación ni budget de handoffs.
Trabajo duplicado entre agentes (Cross-agent duplicate work)
Agentes distintos llaman el mismo tool con argumentos iguales o casi iguales.
Eso pasa rápido a tool spam.
Causa típica: falta dedupe a nivel de run completo, no solo por agente.
Fan-out excesivo (Unbounded fan-out)
Un agente genera muchas tareas hijas, y el sistema consume recursos más rápido de lo que termina trabajo útil.
Causa típica: no hay caps para agentes activos y tareas paralelas.
Cómo detectar estos problemas
El caos multiagente se ve bien con combinación de métricas de orchestration y runtime.
| Métrica | Señal de caos multiagente | Qué hacer |
|---|---|---|
agent_handoffs_per_run | muchas transferencias de tareas sin cierre | introducir max_handoffs y stop reason |
delegation_depth_p95 | cadenas de delegación demasiado profundas | limitar profundidad y forzar retorno al orchestrator |
duplicate_subtask_rate | varios agentes hacen la misma subtarea | lock de owner + dedupe signatures |
cross_agent_tool_overlap_rate | suben tool_call idénticos entre agentes | shared cache, per-run dedupe, bounded fan-out |
multi_agent_chaos_stop_rate | stop reasons multi_agent_chaos:* frecuentes | revisar roles de agentes y arbitration policy |
Cómo distinguir caos multiagente de especialización útil
No todo run multiagente largo significa caos. La pregunta clave: cada agente aporta una contribución única al resultado final.
Normal si:
- cada subtarea tiene un owner y responsabilidad clara;
- un handoff cambia estado de la tarea, no solo la reenvía;
- cantidad de agentes y llamadas sube junto con la calidad de respuesta.
Peligroso si:
- una subtarea tiene varios owners;
- los agentes se pasan la tarea sin señal nueva;
- costo y latency suben, pero el run no converge a
final_answer.
Cómo frenar estos fallos
En práctica:
- definir role map: quién hace qué y quién es owner de cada subtarea;
- poner límites de agentes activos, cantidad de handoffs y profundidad de delegación;
- introducir arbitration step antes de cada nueva delegación;
- ante conflictos o exceso de presupuesto, cambiar a fallback (single-agent o respuesta parcial).
Guard mínimo para coordinación multiagente:
from dataclasses import dataclass
import json
def task_signature(task: dict) -> str:
return json.dumps(task, sort_keys=True, ensure_ascii=False)
@dataclass(frozen=True)
class MultiAgentLimits:
max_agents_per_run: int = 4
max_handoffs: int = 8
max_delegation_depth: int = 3
max_parallel_subtasks: int = 6
max_duplicate_signature: int = 2
class MultiAgentChaosGuard:
def __init__(self, limits: MultiAgentLimits = MultiAgentLimits()):
self.limits = limits
self.seen_agents: set[str] = set()
self.handoffs = 0
self.in_flight_signatures: set[str] = set()
self.signature_claims: dict[str, int] = {}
self.owner_by_signature: dict[str, str] = {}
def register_agent(self, agent_id: str) -> str | None:
self.seen_agents.add(agent_id)
if len(self.seen_agents) > self.limits.max_agents_per_run:
return "multi_agent_chaos:agent_fanout"
return None
def on_handoff(self, _from_agent: str, to_agent: str, depth: int) -> str | None:
self.handoffs += 1
if self.handoffs > self.limits.max_handoffs:
return "multi_agent_chaos:handoff_budget"
if depth > self.limits.max_delegation_depth:
return "multi_agent_chaos:delegation_depth"
return self.register_agent(to_agent)
def claim_subtask(self, agent_id: str, task: dict) -> str | None:
sig = task_signature(task)
owner = self.owner_by_signature.get(sig)
if owner is not None and owner != agent_id:
return "multi_agent_chaos:ownership_conflict"
self.owner_by_signature.setdefault(sig, agent_id)
self.signature_claims[sig] = self.signature_claims.get(sig, 0) + 1
if self.signature_claims[sig] > self.limits.max_duplicate_signature:
return "multi_agent_chaos:duplicate_subtask"
if sig not in self.in_flight_signatures:
if len(self.in_flight_signatures) >= self.limits.max_parallel_subtasks:
return "multi_agent_chaos:parallel_fanout"
self.in_flight_signatures.add(sig)
return None
def finish_subtask(self, task: dict) -> None:
self.in_flight_signatures.discard(task_signature(task))
Este es un guard base.
En esta versión, seen_agents también cuenta intentos de expandir fan-out,
no solo agentes ya admitidos.
max_agents_per_run limita la cantidad de agentes únicos por run.
En producción normalmente se amplía con shared state store,
priority queue para subtareas y fallback explícito a single-agent mode.
on_handoff(...) se llama antes de transferir tarea a otro agente,
y claim_subtask(...) antes de ejecutar, para frenar el caos desde la entrada.
Dónde se implementa en la arquitectura
En producción, el control de caos multiagente normalmente se reparte entre tres capas del sistema.
Orchestration Topologies define cómo interactúan los agentes, quién es owner del estado y dónde ocurre arbitration. Sin esta capa, el caos entre agentes es casi inevitable.
Agent Runtime gestiona execution limits,
stop reasons (multi_agent_chaos:*) y transiciones de fallback.
Aquí se fijan handoff/depth budgets y condiciones de parada forzada.
Tool Execution Layer cierra llamadas de herramientas duplicadas entre agentes: dedupe, retries, timeout y shared caching dentro del run.
Checklist
Antes de enviar un escenario multiagente a producción:
- [ ] role map y owner de cada subtarea definidos explícitamente;
- [ ]
max_agents_per_run,max_handoffs,max_delegation_depthdefinidos; - [ ] lock de owner de tarea y per-run dedupe signatures en su lugar;
- [ ] bounded fan-out para subtareas paralelas activado;
- [ ] stop reasons cubren
multi_agent_chaos:*; - [ ] existe fallback: single-agent mode o respuesta parcial;
- [ ] alertas sobre
agent_handoffs_per_run,duplicate_subtask_rate,queue_backlog; - [ ] runbook describe cómo aislar conflicto de roles durante incidente.
FAQ
Q: ¿Más agentes siempre significa mejor calidad?
A: No. Sin coordinación, más agentes suele dar más duplicación y conflictos, no mejor resultado.
Q: ¿Se puede quitar el caos solo cambiando prompt?
A: No. Prompt ayuda, pero la raíz está en control de orchestration: roles, ownership de tareas, budgets y arbitration.
Q: ¿Qué hacer si el caos ya empezó en producción?
A: Limitar fan-out temporalmente, reducir agentes activos, activar fallback single-agent y revisar stop reasons en trazas.
Q: ¿Quién debe tomar la decisión final en sistema multiagente?
A: Normalmente un orchestrator o un arbitration step. Sin un único owner de decisión final, el sistema pasa rápido a conflicto o duplicación.
El caos multiagente casi nunca parece una gran rotura única. Más bien es acumulación de conflictos pequeños entre agentes. Por eso los sistemas de producción necesitan no solo agentes "inteligentes", sino también disciplina estricta de orchestration.
Páginas relacionadas
Si este problema aparece en producción, también conviene revisar:
- Por qué fallan los agentes de IA — mapa general de fallos en producción.
- Deadlocks — cómo espera cíclica entre agentes bloquea workflow.
- Cascading failures — cómo un fallo local se expande por el sistema.
- Tool spam — cómo llamadas duplicadas de tools consumen presupuesto.
- Agent Runtime — dónde fijar budgets, stop reasons y fallback.
- Orchestration Topologies — cómo diseñar interacción controlada entre agentes.
- Tool Execution Layer — dónde centralizar retries, dedupe y timeout.