Módulo 1: Por qué multi-agente (y cuándo no)
El costo de la coordinación
Descripción
La lección 02 definió qué es un sistema multi-agente: varios agentes, cada uno con su propia decisión, coordinados por un mecanismo que reparte el trabajo y junta los resultados. Esta lección responde la pregunta que esa definición deja abierta: ¿cuánto cuesta ese mecanismo? No en abstracto — en números que puedes calcular antes de escribir una sola línea de orquestación.
Cada agente adicional que un sistema consulta agrega, como mínimo, tres costos medibles: una llamada al modelo para decidir a quién delegar, las llamadas internas de ese especialista para resolver su parte, y los mensajes ("hops") que van y vuelven entre el coordinador y el especialista. Vas a ejecutar una fórmula que crece con la cantidad de especialistas consultados, y un segundo modelo, más simple, que muestra cómo cada paso adicional también es una oportunidad más de que algo salga mal. Ninguno de los dos ejemplos corre el runner completo todavía —eso es la lección 05, con la comparación real de dos sistemas—; aquí construyes el vocabulario y la intuición numérica que la lección 05 va a usar sobre un caso concreto.
Conexión con el módulo
La lección 01 lo dijo en prosa: "más agentes = más llamadas, más pasos, más superficie de
error". Esta lección lo convierte en código ejecutable. La lección 04 usa este mismo vocabulario
—llamadas al modelo, hops— para comparar el costo de un agente con muchas tools contra el de
repartir esas tools en varios agentes. La lección 05 aplica la fórmula de esta lección a un caso
real, con el runner de agent-fundamentals corriendo de verdad.
Analogía: cada persona nueva en la cadena es una oportunidad de malentendido
Retoma la analogía del equipo de personas de la lección 01. Si tú resuelves una tarea solo, hay exactamente un lugar donde algo puede salir mal: tu propio trabajo. Si le pides a alguien más que resuelva una parte y te la devuelva, agregaste dos lugares nuevos: el momento en que le explicas la tarea (¿la entendió bien?) y el momento en que te devuelve el resultado (¿te lo comunicó bien?). Ninguno de los dos es "trabajo" en el sentido de avanzar la tarea — son overhead de coordinación, y cada persona nueva en la cadena los multiplica.
Eso es exactamente lo que un sistema multi-agente paga: cada especialista que un supervisor consulta agrega una decisión de "a quién le mando esto" y un mensaje de ida y otro de vuelta — antes de que el especialista siquiera empiece a trabajar en la parte que solo él puede resolver.
Ejemplo trabajado: el costo crece con la cantidad de especialistas
Modelamos dos caminos para resolver una tarea que necesita el trabajo de n_specialists
especialistas: un solo agente que hace todo el trabajo él mismo (sin ningún mensaje de
coordinación), y un supervisor que delega en n_specialists agentes distintos. El número de
llamadas internas que le toma a un especialista resolver su parte —3, en promedio, para una
tarea típica de Reservo con una cotización y una acción— es el mismo número real que vas a ver
ejecutado en la lección 05.
def single_agent_cost(n_specialists, calls_per_specialist=3):
"""Un solo agente resuelve el trabajo de las N áreas él mismo -- sin
ruteo, sin síntesis, sin mensajes entre agentes."""
return {"model_calls": calls_per_specialist * n_specialists, "hops": 0}
def supervised_cost(n_specialists, calls_per_specialist=3):
"""Un supervisor delega en N especialistas: 1 llamada de ruteo, las
llamadas internas de cada especialista, 1 llamada de síntesis, y 2 hops
(ida y vuelta) por cada especialista consultado."""
route_calls = 1
compose_calls = 1
return {
"model_calls": route_calls + calls_per_specialist * n_specialists + compose_calls,
"hops": 2 * n_specialists,
}
print(f"{'especialistas':>14} | {'1 agente (calls/hops)':>24} | "
f"{'supervisor+N (calls/hops)':>26} | {'llamadas de más':>16}")
for n in (1, 2, 3):
single = single_agent_cost(n)
multi = supervised_cost(n)
extra = multi["model_calls"] - single["model_calls"]
print(f"{n:>14} | {single['model_calls']:>10} / {single['hops']:<10} | "
f"{multi['model_calls']:>12} / {multi['hops']:<10} | {extra:>16}")
Qué esperar:
especialistas | 1 agente (calls/hops) | supervisor+N (calls/hops) | llamadas de más
1 | 3 / 0 | 5 / 2 | 2
2 | 6 / 0 | 8 / 4 | 2
3 | 9 / 0 | 11 / 6 | 2
Lee la tabla con cuidado, porque tiene dos historias distintas adentro. La columna de llamadas
de más se mantiene constante en 2, sin importar cuántos especialistas consultes — es el
costo fijo del supervisor mismo (una llamada de ruteo, una de síntesis), y no crece con n
porque en este modelo el supervisor decide una sola vez a quién delegar todo, no una vez por
especialista. La columna de hops, en cambio, sí crece: 2 * n, porque cada especialista
nuevo agrega su propio viaje de ida y vuelta. Con un solo especialista (n=1), el sistema de
supervisor usa exactamente 5 llamadas y 2 hops frente a las 3 llamadas y 0 hops de un
agente único — el número exacto que vas a confirmar, ejecutado de punta a punta con el runner
real, en la lección 05.
El segundo costo: más pasos, más superficie de error
El conteo de llamadas y hops mide el costo en trabajo. Hay un segundo costo, distinto, que importa igual: cada llamada al modelo y cada tool call es un paso donde algo puede fallar —un argumento mal formado, un timeout, una decisión de ruteo equivocada. Si modelamos cada paso con una probabilidad fija de fallar (un número inventado con fines ilustrativos, no una medición real de ningún sistema), la probabilidad de que todo el camino termine sin ningún fallo cae con cada paso adicional — no de forma lineal, sino multiplicativa.
def end_to_end_success(steps, failure_rate_per_step=0.02):
"""Modelo simple e ilustrativo: si cada paso tiene una probabilidad fija
de fallar, la probabilidad de que TODOS los pasos salgan bien es el
producto de que cada uno, por separado, salga bien."""
return (1 - failure_rate_per_step) ** steps
steps_single = 3 # el agente único de la lección 05: 3 llamadas
steps_multi = 5 # el sistema de 2 agentes de la lección 05: 5 llamadas
success_single = end_to_end_success(steps_single)
success_multi = end_to_end_success(steps_multi)
print(f"Sistema A (1 agente, {steps_single} pasos): "
f"{success_single:.4f} ({success_single * 100:.2f}% de éxito end-to-end)")
print(f"Sistema B (2 agentes, {steps_multi} pasos): "
f"{success_multi:.4f} ({success_multi * 100:.2f}% de éxito end-to-end)")
print(f"diferencia: {(success_single - success_multi) * 100:.2f} puntos porcentuales "
f"menos confiable en Sistema B, con el mismo 2% de riesgo por paso")
Qué esperar:
Sistema A (1 agente, 3 pasos): 0.9412 (94.12% de éxito end-to-end)
Sistema B (2 agentes, 5 pasos): 0.9039 (90.39% de éxito end-to-end)
diferencia: 3.73 puntos porcentuales menos confiable en Sistema B, con el mismo 2% de riesgo por paso
El punto no es que 0.02 sea la probabilidad real de que una llamada falle en producción —esa
cifra depende del sistema, del proveedor y de mil factores que esta guía no mide—. El punto es
estructural: con la misma tasa de fallo por paso, un camino de 5 pasos es aritméticamente
menos confiable que uno de 3, porque la probabilidad de éxito se multiplica, no se resta.
Cada llamada de más que agrega la coordinación no es solo tiempo y costo — es una oportunidad más
de que el sistema completo falle, aunque cada paso individual sea igual de confiable que
cualquier otro.
Por qué esta lección no ejecuta el runner completo todavía
Puede llamar la atención que esta lección, tan centrada en "el costo de coordinar", no corra
run_agent_parallel ni construya ningún AgentMessage real. Es deliberado: las fórmulas de
arriba (single_agent_cost, supervised_cost, end_to_end_success) son modelos — capturan
la forma en la que el costo crece, para cualquier tarea con esa estructura, sin atarse a una tarea
específica de Reservo. La lección 05 toma exactamente el caso n=1 de la tabla de arriba —un
sistema con un solo especialista consultado— y lo hace concreto: una tarea de Reservo real, un
runner real, un guion real, y los mismos números (3 vs. 5, 0 vs. 2 hops) confirmados con el
historial completo impreso en pantalla, no con una fórmula.
Errores comunes
-
Confundir "llamadas de más" (fijo) con "hops" (crece con N). En el modelo de esta lección, agregar un tercer especialista no agrega una tercera llamada de ruteo o síntesis —el supervisor sigue decidiendo una sola vez—, pero sí agrega 2 hops más. Tratar ambos costos como si crecieran igual lleva a subestimar uno o sobrestimar el otro.
-
Tomar el
0.02del modelo de confiabilidad como un número real de producción. Es un valor ilustrativo elegido para que el ejemplo sea legible, no una medición de ningún sistema —el punto que hay que llevarse es la forma multiplicativa de la caída, no la cifra exacta. -
Pensar que el costo de coordinar siempre justifica evitar multi-agente. Esta lección mide el costo; no dice que el costo nunca vale la pena. La lección 06 muestra casos reales donde sí se justifica, a pesar del costo medido aquí.
-
Asumir que
calls_per_specialist=3es una constante universal. Es el número de esta guía, para la tarea concreta que vas a ver en la lección 05 (cotizar y reservar). Una tarea con más pasos internos —o con reintentos por errores, tema deagent-fundamentalsM7— tendría un número más alto, y la brecha entre los dos caminos crecería en la misma proporción. -
Olvidar que
single_agent_costno es gratis tampoco. Un agente único conn_specialistsveces más trabajo interno también tiene un costo que crece conn—solo que crece sin el costo adicional de ruteo, síntesis y hops. La comparación siempre es relativa, nunca "multi- agente cuesta, un agente no cuesta nada".
Ejercicios
Ejercicio 1: Lee la fórmula sin ejecutar (Fácil)
Sin correr código: (a) si n_specialists=4, ¿cuántas llamadas al modelo usa supervised_cost
con calls_per_specialist=3? (b) ¿cuántos hops? (c) ¿cuántas llamadas de más tiene sobre
single_agent_cost para el mismo n?
Ver solución
(a) route_calls + calls_per_specialist * n_specialists + compose_calls = 1 + 3*4 + 1 =
14 llamadas.
(b) 2 * n_specialists = 2 * 4 = 8 hops.
(c) single_agent_cost(4) = 3 * 4 = 12 llamadas. La diferencia es 14 - 12 = 2 llamadas
de más — el mismo costo fijo de siempre (1 ruteo + 1 síntesis), sin importar que n haya
subido de 1 a 4. Este es exactamente el patrón que muestra la tabla del ejemplo trabajado: las
llamadas de más se mantienen en 2 en todas las filas.
Ejercicio 2: Extiende la tabla y grafica el crecimiento de los hops (Medio)
Ejecuta supervised_cost y single_agent_cost para n_specialists de 1 a 6, e imprime, además
de las columnas del ejemplo trabajado, la razón hops / model_calls del sistema supervisado para
cada fila (redondeada a 2 decimales). ¿La razón crece, decrece o se mantiene estable a medida que
n aumenta?
Ver solución
def single_agent_cost(n_specialists, calls_per_specialist=3):
return {"model_calls": calls_per_specialist * n_specialists, "hops": 0}
def supervised_cost(n_specialists, calls_per_specialist=3):
route_calls = 1
compose_calls = 1
return {
"model_calls": route_calls + calls_per_specialist * n_specialists + compose_calls,
"hops": 2 * n_specialists,
}
print(f"{'n':>3} | {'calls':>6} | {'hops':>5} | {'hops/calls':>11}")
for n in range(1, 7):
multi = supervised_cost(n)
ratio = multi["hops"] / multi["model_calls"]
print(f"{n:>3} | {multi['model_calls']:>6} | {multi['hops']:>5} | {ratio:>11.2f}")
Salida esperada:
n | calls | hops | hops/calls
1 | 5 | 2 | 0.40
2 | 8 | 4 | 0.50
3 | 11 | 6 | 0.55
4 | 14 | 8 | 0.57
5 | 17 | 10 | 0.59
6 | 20 | 12 | 0.60
Explicación: la razón crece, aunque cada vez más despacio (0.40 → 0.50 → 0.55 → 0.57 →
0.59 → 0.60, acercándose a un techo). Tiene sentido algebraicamente: los hops crecen 2n (puro,
sin costo fijo) mientras que las llamadas crecen 3n + 2 (con el costo fijo de ruteo y síntesis
sumado una sola vez); a medida que n crece, el costo fijo pesa cada vez menos sobre el total, y
la proporción de hops se acerca a 2/3 ≈ 0.67 — el límite que tendría la razón si el costo fijo
no existiera. En sistemas con muchos especialistas, casi todo el costo de coordinar termina
siendo hops, no las dos llamadas fijas del supervisor.
Ejercicio 3: Diseña un modelo de costo para el patrón pipeline (Difícil)
Los Módulos 2 y 3 de esta guía distinguen el patrón supervisor (un coordinador decide a quién
delegar) del patrón pipeline (una secuencia fija de agentes, cada uno alimentando al
siguiente, sin una decisión de ruteo en cada paso). Escribe una función pipeline_cost(n_stages, calls_per_stage=3) que modele el costo de un pipeline de n_stages agentes en secuencia, donde
no hay una llamada de ruteo por cada etapa (el orden ya está fijo de antemano) pero sí hay 1
hop entre cada etapa consecutiva (el resultado de una pasa a la siguiente). Compara su resultado
con supervised_cost para n=3 y explica, en una frase, por qué el pipeline debería costar
menos hops que el supervisor para el mismo número de etapas.
Ver solución
def pipeline_cost(n_stages, calls_per_stage=3):
"""Un pipeline NO tiene llamada de ruteo por etapa -- el orden ya está
fijo -- pero sí un hop entre cada etapa consecutiva (n_stages - 1 hops
para n_stages etapas encadenadas)."""
return {
"model_calls": calls_per_stage * n_stages,
"hops": max(0, n_stages - 1),
}
def supervised_cost(n_specialists, calls_per_specialist=3):
route_calls = 1
compose_calls = 1
return {
"model_calls": route_calls + calls_per_specialist * n_specialists + compose_calls,
"hops": 2 * n_specialists,
}
pipe = pipeline_cost(3)
sup = supervised_cost(3)
print(f"pipeline (3 etapas): {pipe['model_calls']} llamadas, {pipe['hops']} hops")
print(f"supervisor (3 agentes): {sup['model_calls']} llamadas, {sup['hops']} hops")
Salida esperada:
pipeline (3 etapas): 9 llamadas, 2 hops
supervisor (3 agentes): 11 llamadas, 6 hops
Explicación: el pipeline usa menos llamadas (9 vs. 11, porque no paga la llamada de
ruteo ni la de síntesis del supervisor) y muchos menos hops (2 vs. 6). La razón de fondo:
en un pipeline, cada etapa solo necesita pasarle su resultado a la siguiente —un hop por
cada unión entre etapas consecutivas, n_stages - 1 en total—, mientras que en un supervisor
cada especialista tiene que ir y volver al coordinador central —2 hops por especialista,
sin importar cuántos especialistas haya en total—. Esta es exactamente la ventaja de costo que
el Módulo 3 de esta guía va a explotar cuando la tarea siempre necesita los mismos pasos, en el
mismo orden: un pipeline es más barato de coordinar que un supervisor, a cambio de perder la
flexibilidad de decidir el camino en cada paso.
Resumen y siguiente paso
- Cada especialista que un sistema multi-agente consulta agrega, como mínimo, llamadas al modelo internas (para resolver su parte) y hops (para recibir la tarea y devolver el resultado) — un costo que un agente único, resolviendo todo por sí mismo, no paga.
- Ejecutamos
single_agent_costysupervised_cost: para un solo especialista consultado, el patrón supervisor usa 2 llamadas de más (5 vs. 3) y 2 hops (vs. 0) frente a un agente único — el mismo caso concreto que la lección 05 va a confirmar con el runner real. - Un segundo costo, distinto y también medible: con la misma tasa de fallo por paso, un camino
con más pasos es aritméticamente menos confiable (
0.98**3 = 94.12%vs.0.98**5 = 90.39%en nuestro modelo ilustrativo) — más superficie de error, no solo más tiempo. - Ninguno de los dos costos dice "nunca uses multi-agente" — dice "conoce el precio antes de pagarlo". La lección 06 muestra cuándo el precio vale la pena.
Siguiente lección: 04 — Un agente con muchas tools vs. muchos agentes. Con el vocabulario de costo ya construido, lo aplicamos a la otra cara de la decisión: ¿es mejor hacer crecer el registro de tools de un solo agente, o repartir esas tools entre varios especialistas?
Recursos adicionales
- Anthropic — Building effective agents — Por qué agregar pasos y agentes tiene un costo en latencia y confiabilidad que hay que justificar contra el beneficio, no asumir gratis.
- Anthropic — Multi-agent research system — El costo real de coordinación que Anthropic reporta en un sistema multi-agente de producción (más tokens, más llamadas) frente a un agente único.
- Python — Funciones y
**para exponenciación — El operador usado enend_to_end_successpara el modelo de confiabilidad compuesta. - Python 3.14 — What's New — La versión con la que se ejecuta todo el código de esta lección.