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

  1. 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.

  2. Tomar el 0.02 del 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.

  3. 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í.

  4. Asumir que calls_per_specialist=3 es 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 de agent-fundamentals M7— tendría un número más alto, y la brecha entre los dos caminos crecería en la misma proporción.

  5. Olvidar que single_agent_cost no es gratis tampoco. Un agente único con n_specialists veces más trabajo interno también tiene un costo que crece con n —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_cost y supervised_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

  1. 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.
  2. 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.
  3. Python — Funciones y ** para exponenciación — El operador usado en end_to_end_success para el modelo de confiabilidad compuesta.
  4. Python 3.14 — What's New — La versión con la que se ejecuta todo el código de esta lección.