Todo el que construye sistemas multi-agente en 2026 sigue escribiendo líneas rectas. Paso uno, luego paso dos, luego paso tres—cada uno esperando al anterior. Aquí te explicamos por qué es lento y cómo solucionarlo.

El problema que nadie revisa
Has construido un agente de múltiples pasos. Funciona. También es lento.
Asumes que el modelo es el cuello de botella. No lo es.
El cuello de botella es la forma que dibujaste. Una cadena —el paso 1 espera al paso 2, el paso 2 espera al paso 3— fuerza la ejecución secuencial incluso cuando la mitad de esos pasos no tienen nada que ver entre sí.
"Resume este documento, luego verifica el clima" son dos trabajos independientes disfrazados de un solo flujo. La tarea del clima no necesita el resumen. Nunca lo necesitó. Pero si lo escribiste como una cadena, igual espera.
Esa espera desperdiciada, multiplicada a lo largo de docenas de pasos, es donde desaparece la mayor parte de tu tiempo de ejecución.
Capítulo 1 - Bucles vs grafos
Un bucle es una unidad de auto-mejora:
1intenta algo → verifica el resultado → ajusta → vuelve a intentar
Ese es el átomo. Un agente, una métrica, ciclando hasta converger.
Los bucles tienen un modo de fallo conocido: optimizan exactamente lo que mides y nada más. Un bot de soporte ajustado para cerrar tickets rápido cerrará tickets rápido — mientras la satisfacción se desploma silenciosamente. El bucle no puede ver fuera de su propia métrica. Eso es la Ley de Goodhart manifestándose en tu arquitectura de agentes.
Un grafo soluciona esto por diseño. En lugar de un solo bucle persiguiendo un número, construyes una red de bucles que se vigilan y corrigen entre sí. La salida del Nodo A alimenta al Nodo B. El Nodo C se ejecuta de forma independiente y verifica a ambos. Ninguna métrica única impulsa todo el sistema — lo hace la estructura.

Para sistemas de agentes, esto significa un cambio concreto: deja de escribir un solo agente que lo hace todo de arriba a abajo. Diseña primero la forma del trabajo — qué tiene que pasar antes de qué, qué puede ejecutarse al mismo tiempo, qué realmente necesita esperar.
Capítulo 2 - Nodos, aristas y la prueba que las separa
Un grafo tiene exactamente dos componentes:
Nodo — una unidad de trabajo. Un agente, una tarea, una entrada, una salida.
Arista — una dependencia real. La entrada del Nodo B requiere la salida del Nodo A.
El error que casi todos cometen: tratar "y luego" como una arista por defecto.
1"Lee este código base y luego escribe el registro de cambios"2"Obtén la página de precios y luego resume las características de la competencia"
Hazte una pregunta por cada "y luego" en tu flujo de trabajo:
¿El siguiente paso realmente lee la salida del paso anterior?
Si sí → arista real. Mantén el orden secuencial. Si no → no hay arista. La espera es desperdiciada. Ejecútalos en paralelo.
Si ningún dato cruza el límite entre dos tareas, son independientes — y cada par independiente que estás ejecutando secuencialmente es tiempo de ejecución que estás desperdiciando gratis.
Aquí está la prueba aplicada en código:
1from dataclasses import dataclass23@dataclass4class TaskNode:5 id: str6 prompt: str7 depends_on: list[str] # IDs de nodos que realmente necesita89def has_real_edge(node_a: TaskNode, node_b: TaskNode) -> bool:10 """11 La prueba central de la ingeniería de grafos:12 ¿el prompt de node_b realmente requiere la salida de node_a?13 """14 return node_a.id in node_b.depends_on1516# Ejemplo: la mayoría de las "cadenas" se reducen a 2-3 grupos de dependencia real17nodes = [18 TaskNode("audit_routes", "Listar todos los archivos de rutas de la API", []),19 TaskNode("check_auth", "Verificar cobertura de middleware de autenticación", []),20 TaskNode("fetch_weather", "Obtener el clima de hoy", []),21 TaskNode("summarize", "Resumir hallazgos de rutas y autenticación",22 depends_on=["audit_routes", "check_auth"]),23]2425# audit_routes, check_auth, fetch_weather NO tienen aristas entre ellos26# Se ejecutan en paralelo. Solo "summarize" tiene aristas reales — espera.
Tu agente actual de "haz A, luego B, luego C" técnicamente ya es un grafo. Solo que es el peor posible: una cadena única donde si C se detiene, nada río abajo se ejecuta nunca.
Capítulo 3 - Construyendo tu primer grafo

Requisitos:
- Claude Code (versión reciente con soporte para Dynamic Workflows).
- Plan Max, Team o Enterprise: flujos de trabajo activados por defecto. En Pro, actívalos manualmente.
Abre un repositorio real. No un ejemplo de juguete: la recompensa solo se ve a escala real.
El prompt que inicia tu primer grafo:
1Crea un flujo de trabajo para auditar cada archivo de ruta en este código base.23Para cada archivo de ruta, verifica de forma independiente:4- middleware de autenticación presente5- validación de entrada en todos los parámetros6- limitación de tasa configurada7- manejo de errores que no filtre stack traces89Ejecuta estas verificaciones en paralelo en todos los archivos de ruta —10no dependen entre sí.1112Después de verificar todos los archivos, produce un informe consolidado13agrupado por severidad: crítico, advertencia, informativo.1415El paso de consolidación debe esperar a que todas las verificaciones terminen.16Todo lo anterior no debe hacerlo.
Observa la estructura incrustada en el propio prompt: el trabajo paralelo se menciona explícitamente, la única dependencia real (consolidación esperando todas las verificaciones) se nombra explícitamente. No estás esperando que el agente infiera el grafo, lo estás describiendo.
Lo que sucede bajo el capó: una versión simplificada de la orquestación:
1import asyncio2from anthropic import Anthropic34client = Anthropic()56async def audit_route_file(filepath: str) -> dict:7 """Un nodo. Se ejecuta independientemente de cualquier otro archivo de ruta."""8 response = await client.messages.create(9 model="claude-sonnet-5",10 max_tokens=1000,11 messages=[{12 "role": "user",13 "content": f"""Audita este archivo de ruta para:14 - middleware de autenticación, validación de entrada,15 limitación de tasa, manejo de errores1617 Archivo: {filepath}1819 Devuelve JSON: {{"file": "", "issues": [], "severity": ""}}"""20 }]21 )22 return {"file": filepath, "result": response.content[0].text}2324async def consolidate(results: list[dict]) -> str:25 """La única arista real — espera a que todos los nodos de auditoría terminen."""26 response = await client.messages.create(27 model="claude-opus-4-8",28 max_tokens=2000,29 messages=[{30 "role": "user",31 "content": f"""Consolida estas {len(results)} auditorías de rutas32 en un informe agrupado por severidad:3334 {results}"""35 }]36 )37 return response.content[0].text3839async def run_graph(route_files: list[str]):40 # Distribución — todos los nodos independientes se ejecutan concurrentemente41 audit_tasks = [audit_route_file(f) for f in route_files]42 results = await asyncio.gather(*audit_tasks)4344 # Recolección — el único nodo con una dependencia real45 report = await consolidate(results)46 return report4748# 40 archivos de ruta, un prompt, una pasada en paralelo49results = asyncio.run(run_graph([50 f"routes/{f}.py" for f in ["auth", "users", "billing", "orders"]51 # ...36 más
40 llamadas secuenciales a la API de ~8 segundos cada una son más de 5 minutos. Las mismas 40 llamadas distribuidas en paralelo: menos de 15 segundos, limitadas por tu archivo más lento, no por la suma de todos.
Capítulo 4 - Donde los grafos realmente fallan
La ingeniería de grafos falla en tres lugares predecibles. Conócelos antes de topar con ellos.
Colapso de contexto. Distribuye 1000 nodos e intenta alimentar las 1000 salidas en un solo paso de consolidación, y superarás cualquier ventana de contexto antes de que comience la síntesis.
Solución: estratifica tu entrada. Agrupa nodos en lotes de 20-50, resume cada lote, luego consolida los resúmenes — no las salidas brutas.
1async def layered_consolidate(results: list[dict], batch_size: int = 30):2 """Recolección en capas — nunca sintetices salidas brutas a escala."""3 batches = [results[i:i+batch_size]4 for i in range(0, len(results), batch_size)]56 batch_summaries = await asyncio.gather(*[7 summarize_batch(batch) for batch in batches8 ])910 # La consolidación final trabaja sobre resúmenes, no sobre 1000 resultados brutos11 return await consolidate(batch_summaries)
Falsa independencia. Supondrás que dos nodos son independientes porque sus prompts no se refieren entre sí, pero ambos escriben en el mismo archivo o golpean la misma API con límite de tasa. Eso es una arista oculta.
Solución: audita los recursos compartidos, no solo los datos compartidos. Dos nodos con conflicto de escritura necesitan una arista incluso sin dependencia de datos.
Fallo silencioso de nodo. En una cadena, un fallo lo detiene todo — molesto pero obvio. En un grafo, un nodo fallido entre 200 puede desaparecer en un informe que parece completo.
Solución: cada paso de entrada verifica el conteo de nodos contra el conteo esperado antes de sintetizar, y señala las brechas explícitamente en lugar de trabajar silenciosamente con datos parciales.
1async def safe_consolidate(results: list[dict], expected_count: int):2 if len(results) < expected_count:3 missing = expected_count - len(results)4 print(f"ADVERTENCIA: {missing} nodos fallaron silenciosamente. "5 f"El informe estará incompleto.")6 return await consolidate(results)
Capítulo 5 - Escalando a una flota real

Una vez que el patrón funciona con 40 nodos, escalar a cientos es un cambio de configuración, no un rediseño — siempre que hayas construido el grafo correctamente desde el Capítulo 2 en adelante.
La forma completa de producción:
1 Orquestador2 |3 +--------+-------+-------+--------+4 v v v v v5 Nodo 1 Nodo 2 Nodo 3 ... Nodo N6 (en paralelo, sin aristas entre ellos)7 | | | |8 +--------+-------+-------+-------+9 v10 Resumen por lotes <- capas de entrada11 (grupos de 30)12 v13 Informe final <- la única arista verdadera
El único trabajo del orquestador: descomponer la tarea en nodos, identificar aristas reales y despachar. No hace trabajo en sí mismo — dibuja el grafo.
1async def orchestrate(task: str, resources: list[str]):2 """3 El nodo orquestador — descompone, no ejecuta.4 """5 plan = await client.messages.create(6 model="claude-opus-4-8",7 max_tokens=2000,8 messages=[{9 "role": "user",10 "content": f"""Tarea: {task}11 Recursos disponibles: {resources}1213 Descompón en un grafo:14 - Lista cada nodo independiente (sin aristas compartidas)15 - Lista cualquier dependencia real entre nodos16 - Agrupa nodos en lotes de entrada si el conteo > 501718 Devuelve JSON con: nodes, edges, batch_groups"""19 }]20 )2122 graph = parse_plan(plan.content[0].text)2324 # Ejecuta nodos independientes en paralelo25 node_results = await asyncio.gather(*[26 execute_node(n) for n in graph["nodes"] if not n["depends_on"]27 ])2829 # Luego ejecuta nodos dependientes, respetando solo las aristas reales30 final = await execute_dependent_chain(graph["edges"], node_results)3132 return final
Este es el cambio real que representa la ingeniería de grafos: dejas de ser la persona que escribe cada paso y te conviertes en la persona que diseña la estructura de dependencias. Los agentes llenan los nodos. Tú eres dueño de las aristas.
Qué cambia cuando piensas en grafos en lugar de líneas
Un agente lineal con 40 pasos tiene 40 puntos de fallo secuencial y 40 veces la latencia de su paso individual más lento.
Un grafo con las mismas 40 unidades de trabajo tiene tantos puntos de fallo paralelo como dependencias reales tengas — normalmente de 3 a 5 en la mayoría de los flujos de trabajo — y una latencia limitada por tu capa más lenta, no por el conteo total de pasos.
Eso no es una mejora marginal. Es la diferencia entre un flujo de trabajo que toma 5 minutos y uno que toma 15 segundos, ejecutando exactamente el mismo trabajo subyacente.
El modelo nunca fue el cuello de botella. La línea que dibujaste lo fue.
Este es un desglose técnico de los patrones de orquestación multi-agente a julio de 2026. Los ejemplos de código son ilustrativos: adapta el manejo de errores, la limitación de tasa y la lógica de reintento a tu entorno de producción antes de implementar a escala.
Gracias por leer.





![[Memorándum] Los jefes están prescindiendo de los subordinados con bajo rendimiento](/cdn-cgi/image/width=1920,quality=90,format=auto,metadata=none/https%3A%2F%2Fcms-assets.youmind.com%2Fmedia%2F1784827522698_408j7z_HN3Kb76awAAvvjF.jpg)