Saltar al contenido
25/30Capítulo 25 de 30

Orquestación multi-agent: cinco patrones y cuándo gana uno

La misma factura resuelta de cuatro formas y con costes: el orchestrator costó 1,66 veces más que un solo agent y llegó al mismo veredicto.

En esta página

Capítulo 24 terminó con una pregunta que se había ganado: cuando un sub-agent se equivoca, ¿qué puede ver exactamente el padre?

Este capítulo la responde con una factura. Una tarea —un cliente disputa una factura y quiere una respuesta— resuelta de cuatro formas, todas ejecutando el harness del capítulo 23 contra el mismo proveedor guionizado, todas contando los mismos tokens con el mismo codificador, todas valoradas con las tarifas que el capítulo 16 leyó el 6 de septiembre de 2026.

disposiciónllamadas al modeloinput tokensoutputcostetiempo realveredicto
prompt chaining4900165$0.0037801,648 msincorrecto
un agent, cuatro herramientas52,697179$0.0075422,224 mscorrecto
secciones en paralelo92,910324$0.0097082,165 mscorrecto
orchestrator-workers123,628438$0.0125125,090 mscorrecto, y no puede demostrarlo

Lee juntas la primera y la última fila: entre ellas está todo el debate que ahora mismo tiene esta industria. La disposición más barata fue también la más rápida y produjo una respuesta segura, incorrecta y lista para enviar. La más cara acertó, costó 3,3 veces más dinero y 3,1 veces más tiempo, y terminó citando la conclusión de un worker que no tiene forma de comprobar.

La fila que nadie pone en estas tablas es la segunda: un agent con las cuatro herramientas llegó al mismo veredicto que el orchestrator por el 60 % del dinero y el 44 % del tiempo real. Eso no es una preferencia por la simplicidad. Es una medición, y el resto de este capítulo trata de cuándo deja de ser cierta.

Mostrar detalles

Lo que este capítulo necesita de los anteriores.

  • Capítulo 18 por el contrato de herramienta: un esquema que el modelo ve, un endpoint que nunca ve. Un agent completo cabe detrás de esa interfaz, y eso es todo lo multi-agent.
  • Capítulo 22 por las dos definiciones publicadas de "agent" que discrepan, y por la aritmética de que una cadena de prompts son N llamadas.
  • Capítulo 23 por el bucle, las cinco salidas, el estado de ejecución y la traza. Cada disposición de abajo es ese archivo, llamado de otra forma.
  • Capítulo 24 por lo que cuesta una ventana y lo que se queda fuera de ella. Un sub-agent es la cuarta de sus cuatro estrategias, y la única que es un segundo agent en lugar de una política.

Sin tensores. Todo aquí es TypeScript, salvo dos mediciones realizadas contra un modelo local real.

Una empresa portuguesa escribe sobre la factura FT-2026-0918. El correo dice que el IVA parece incorrecto y adjunta la factura: neto EUR 248.00, IVA cobrado al 21 %, EUR 52.08, total EUR 300.08.

Los datos necesarios para responder viven en tres sitios, y solo uno de ellos está en el correo:

dóndequé dice
la factura adjuntavendedor en España, IVA aplicado al 21 %, EUR 52.08
el registro del pedidoel comprador está registrado en Portugal, con un identificador de IVA válido, business-to-business
la tabla fiscaltipo doméstico español 21 %; business-to-business intra-UE con identificador válido, inversión del sujeto pasivo, 0 %

Junta los tres y la factura está mal: se aplicaba inversión del sujeto pasivo, el IVA debería haber sido cero y se debe una factura rectificativa por EUR 52.08. Mira solo la factura y es aritméticamente perfecta —248.00 más 52.08 son 300.08— y eso dirás.

El correo sí afirma "somos una empresa portuguesa". Eso es una afirmación, no un registro, y ningún sistema de facturación emite una factura rectificativa basándose en una afirmación. La trampa no es un truco: es la forma habitual del trabajo empresarial, donde la decisión necesita un dato que a nadie se le ocurrió recuperar.

Todo lo anterior se ejecuta contra un proveedor guionizado al estilo del capítulo 23, con exactamente una regla:

Una respuesta solo puede usar un dato que esté en su prompt.

El "modelo" pide cada herramienta que tiene, una vez, en orden de catálogo, y luego aplica una regla fija al texto que puede ver. Nada está guionizado por disposición, así que las diferencias de la tabla inicial no son afirmaciones sobre la inteligencia del modelo: son information routing, medido. Un modelo real añade sus propios fallos encima; no elimina estos.

Los cinco nombres de abajo son de Anthropic, de Building effective agents, que es donde se asentó este vocabulario.1 Ninguna de las cinco ideas es nueva, y decir qué casa puso nombre a qué —y qué idea es más antigua— es la mitad del valor de conocerlas.

patterns.tsTS
/* 1. Prompt chaining: a fixed pipeline. The control flow is yours. */
export async function chain(steps: Step[], first: string) {
  let carry = first, all = first;
  for (const s of steps) {
    const r = await step(s.role, s.system, s.accumulate ? all : carry);   
    carry = r.text;
    all = `${all}\n${r.text}`;
  }
  return carry;
}

/* 2. Routing: one cheap call picks the branch. The fallback is not a model. */
export async function route<T>(input: string, classify: Classifier,
                               routes: Record<string, Branch<T>>, fallback: Branch<T>) {
  let label: string | undefined;
  try { label = await classify(input); } catch { label = undefined; }
  return ((label && routes[label]) || fallback)(input);                    
}

/* 3. Parallelisation. The pattern IS this line. */
export const parallel = <T>(workers: Branch<T>[], input: string) =>
  Promise.all(workers.map((w) => w(input)));                              

/* 4. Orchestrator-workers: an agent behind a tool. Chapter 18's interface, unchanged. */
export function agentTool(o: WorkerSpec): Tool {
  return {
    name: o.name, description: o.description, readOnly: true,
    parameters: { type: "object", properties: { question: { type: "string" } } },
    async run(args: { question: string }) {
      const child = newRun(o.system, args.question);          // its own window
      await runTracked(child, o.tools, o.usage);              // its own limits
      const conclusion = child.output ?? "no result";
      if (!o.carryFindings) return conclusion;                             
      return `${conclusion}\nFINDINGS ${evidence(child)}`;                 
    },
  };
}

/* 5. Evaluator-optimiser: make, judge, remake. Rounds are calls. */
export async function refine(make: Make, judge: Judge, maxRounds: number) {
  let draft = "", feedback: string | undefined;
  for (let r = 1; r <= maxRounds; r++) {
    draft = (await make(feedback)).text;
    const j = await judge(draft);
    if (j.ok) return { draft, rounds: r };
    feedback = j.note;
  }
  return { draft, rounds: maxRounds };
}

Ese es todo el kit de herramientas: cinco funciones, ningún framework, y la paralela es una sola línea; ese es precisamente el motivo de escribirla en lugar de dibujarla. Ahora una por una, con su genealogía, su precio y el caso en que se equivoca.

Prompt chaining "descompone una tarea en una secuencia de pasos, donde cada llamada al LLM procesa el resultado de la anterior".1 La idea es anterior a los modelos de lenguaje: es un pipeline, con el intercambio propio de un pipeline: claridad a cambio de un flujo de control fijado antes de que lleguen los datos.

Cuatro pasos para nuestra tarea: extraer los campos de la factura, comprobar la aritmética, decidir qué se debe, escribir la respuesta. Aquí falla de dos formas distintas, lo que enseña más que fallar una sola vez.

TEXT
--- relay: each step sees only the previous step's output
extract: FIELDS invoice_id=FT-2026-0918 net=248.00 vat_rate_applied=21 vat_amount=52.08 ...
check:   ARITHMETIC ok 248.00+52.08=300.08
decide:  VERDICT=unknown reason=no_invoice_in_context
draft:   "we are looking into invoice FT-2026-0918 and will come back to you."

--- accumulating: each step sees the email and everything produced so far
extract: FIELDS invoice_id=FT-2026-0918 net=248.00 vat_rate_applied=21 ...
check:   ARITHMETIC ok 248.00+52.08=300.08
decide:  VERDICT=invoice_correct reason=net_248.00_plus_21pct_vat_52.08_equals_300.08
draft:   "we have checked FT-2026-0918 and it is correct... Nothing is owed back."

La cadena de relevo costó $0.001940 y perdió los campos de la factura entre los pasos dos y tres, porque al paso tres se le entregó una frase sobre aritmética y nada más. Produjo un mensaje de espera: inútil, y visiblemente inútil.

La cadena acumulativa —la fila de la tabla inicial— costó $0.003780, un 95 % más por cuatro llamadas idénticas, porque ahora cada paso lleva todo lo anterior. Produjo la salida peligrosa. Fluida, citando su aritmética, correcta en cada número que menciona, y diciéndole a un cliente que no se le debe nada cuando se le deben EUR 52.08.

La diferencia entre ambas es un ternario. Una cadena que lleva menos produce respuestas obviamente incompletas; una cadena que lo lleva todo produce respuestas confiadamente incorrectas —y solo las segundas se envían.

Ninguna de las dos es el fallo real. El fallo real es que el pipeline decidió, antes de leer nada, que esta tarea son cuatro pasos sobre el contenido de un correo. En ningún lugar de esa estructura hay sitio para decir "el país de registro no está en este correo; ve a buscarlo". Chaining es correcto cuando la descomposición se conoce de antemano y es estable. Aquí era una suposición, y la suposición se envió.

Routing, el más antiguo, y el plan B que nadie escribe

Enlace a la sección: Routing, el más antiguo, y el plan B que nadie escribe

Routing "clasifica una entrada y la dirige a una tarea de seguimiento especializada".1 El nombre es nuevo; el mecanismo es el dispatcher, más antiguo que casi todo lo demás de este libro. Lo nuevo es que el clasificador puede ser un modelo, que es lo que hace que falle de formas en que un switch nunca lo hizo.

route.tsTS
const answer = await route(email,
  (q) => classifyWithSmallModel(q),          // cheap model, one call
  { billing: billingAgent, tax: taxAgent, dunning: dunningAgent },
  taxAgent,                                  // deterministic, chosen in advance
);

Dos cosas sobre ese último argumento. No es gestión de errores; es el patrón. Un router basado en modelo tiene un modo de fallo que un dispatcher no tiene: puede devolver una etiqueta que no existe, agotar el tiempo de espera o —el caro— devolver una etiqueta plausible pero incorrecta sin ninguna señal de que lo es. Los tres tienen que aterrizar en algún sitio, y ese sitio no puede ser otra llamada al modelo, porque ya estás en la rama donde las llamadas al modelo fallaron.

La segunda cosa es que el prompt del propio router no es gratis. Para elegir un modelo, un router necesita un catálogo de modelos entre los que elegir, y cada entrada de ese catálogo es input que el router paga antes de haber leído la pregunta del usuario. A la tarifa de input con la que este curso calcula costes, un catálogo de unos 3,800 tokens ya cuesta tanto como toda la ejecución del agent de cinco llamadas de la tabla inicial. En la práctica, la llamada de routing se ejecuta en un modelo barato, que es justamente la razón por la que routing se amortiza; pero merece la pena hacer la aritmética en esa dirección, en lugar de darlo por hecho. Routing es incorrecto precisamente cuando la tarea enrutada es más barata que la decisión de routing.

Paralelización: secciones y votación, que es self-consistency

Enlace a la sección: Paralelización: secciones y votación, que es self-consistency

Anthropic divide este patrón en dos: sectioning —"dividir una tarea en subtareas independientes ejecutadas en paralelo"— y voting —"ejecutar la misma tarea varias veces para obtener salidas diversas".1 Comparten diagrama y casi nada más.

Sectioning es la victoria barata, y es la línea de patterns.ts: tres especialistas —facturación, fiscalidad, política—, cada uno con su propia ventana y herramientas, sobre el mismo correo, con una llamada de síntesis al final. Trabajo idéntico, ordenado de dos formas:

llamadas al modeloinputoutputcostetiempo real
los tres workers, uno tras otro92,910324$0.0097083,894 ms
los mismos tres, Promise.all92,910324$0.0097082,165 ms

Mismo token por token, 1,8 veces más rápido. Por eso el patrón se gana su propio nombre: es el único de los cinco que mejora algo sin costar nada. La pega es que las secciones deben ser genuinamente independientes: dale a la sección B un dato que produce la sección A y Promise.all ejecuta ambas contra un estado que aún no existe. El bucle for ocultaba ese bug; la línea única lo expone.

Voting es otro animal con el mismo dibujo. Ejecutar la misma pregunta k veces y tomar la mayoría es self-consistency, publicado por Wang et al. en marzo de 2022 como estrategia de decoding, casi tres años antes de que nadie lo llamara patrón de orquestación. Su resumen es preciso sobre el mecanismo —"primero samplea un conjunto diverso de rutas de razonamiento en lugar de tomar solo la greedy, y luego selecciona la respuesta más consistente marginalizando las rutas de razonamiento sampleadas"— y sobre la mejora: +17,9 puntos en GSM8K.2

De ahí se siguen dos cosas que el dibujo oculta. Primero, voting requiere el sampling del capítulo 17: a temperature cero, las k muestras son la misma muestra, y la mayoría es una respuesta pagada k veces. Segundo, solo funciona donde una mayoría tiene sentido: en la respuesta de factura anterior no hay nada que contar, porque cinco borradores son cinco frases distintas. Voting es para tareas con una respuesta corta y comparable, exactamente los benchmarks de Wang y casi nada de lo que hace un agent de cara al cliente.

Medido aquí sobre 20 problemas verbales de tres pasos cuyas respuestas se calculan en lugar de juzgarse, con el modelo local del capítulo 23 razonando paso a paso:

llamadas al modeloinputoutputcoste de los 20correctasintervalo del 95 %
una cadena greedy201,3302,649$0.0344489/2026–66 %
mayoría de 5, temperature 0.81006,65013,245$0.1722409/2026–66 %

Cinco veces las llamadas, cinco veces los tokens, exactamente cinco veces la factura, y ni una sola respuesta correcta adicional. Voting es una apuesta, no una mejora, y esta ejecución la perdió.

Dos advertencias antes de que nadie cite esto como una refutación de Wang. Veinte ensayos no distinguen un 45 % de un 60 %: el intervalo tiene el ancho de la afirmación, que es la disciplina del capítulo 4 aplicada a mi propio resultado. Y las mejoras publicadas vienen de modelos órdenes de magnitud mayores, donde las rutas de razonamiento diversas que voting marginaliza son realmente diversas. Lo que se transfiere no es el número: es que el multiplicador es exacto y se conoce de antemano, mientras que la mejora no.

Orchestrator-workers, y lo que no es un resumen

Enlace a la sección: Orchestrator-workers, y lo que no es un resumen

En el workflow orchestrator-workers, "un LLM central descompone dinámicamente las tareas, las delega en worker LLMs y sintetiza sus resultados", y la diferencia con sectioning es que "las subtareas no están predefinidas, sino que las determina el orchestrator".1 La genealogía aquí no viene de los modelos de lenguaje en absoluto: esto es master-worker, y la versión en la que los workers escriben hallazgos en un espacio compartido que lee un controlador es la arquitectura blackboard, procedente de la investigación en reconocimiento del habla de los años setenta. Lo nuevo en 2026 es que el controlador es un modelo y, por tanto, la descomposición puede decidirse por entrada: la flexibilidad y el coste, en una sola frase.

Costó 12 llamadas al modelo frente a las 5 del agent único, y llegó al mismo veredicto. Luego hizo algo que conviene mirar de cerca:

TEXT
orchestrator final: VERDICT=credit_note_due amount=52.08 source=worker_unverified
                  | PO_MISMATCH=yes source=worker_unverified
single agent:       VERDICT=credit_note_due amount=52.08 reason=reverse_charge_should_have_applied
                  | PO_MISMATCH=yes invoice_says=PO-4417 order_says=PO-4471

Ambas son correctas. Solo una sabe por qué. El worker fiscal tenía la factura, el pedido y la tabla fiscal en su propia ventana, llegó a la conclusión y además observó —nadie se lo pidió— que el número de pedido de compra de la factura no coincide con el del pedido. Luego devolvió un resumen. El orchestrator puede repetir ambas afirmaciones y comprobar ninguna, porque la evidencia se quedó en una ventana que nunca vio. Esa es la pregunta final del capítulo 24, respondida: el padre puede ver aquello que el hijo decidió escribir.

La solución es un flag, y tiene precio:

lo que devuelve el workerinput tokens del orchestratorcostequé puede hacer el padre
su conclusión3,628$0.012512repetirla
su conclusión y su evidencia4,065$0.013554derivarla de nuevo, y discrepar

Un 12 % más de input tokens, un 8,3 % más de dinero, y la frase source=worker_unverified desaparece de la respuesta. Ese es el intercambio en todo sistema multi-agent y casi nunca se declara: merece la pena tener la ventana limpia del hijo, merece la pena pagar por la capacidad del padre de auditarla, y no puedes tener ambas gratis.

Entonces, ¿cuándo es incorrecto orchestrator-workers? Aquí, en esta tarea. Compró una respuesta correcta a la que también llegó un agent con las mismas cuatro herramientas, por 1,66 veces el coste y 2,3 veces el tiempo real, e hizo que esa respuesta fuera más difícil de defender. La propia guía de Anthropic dice lo mismo antes de empezar con los patrones: encontrar "la solución más sencilla posible, y aumentar la complejidad solo cuando sea necesario", porque "los sistemas agentic suelen intercambiar latencia y coste por un mejor rendimiento en la tarea".1 Las tablas de arriba son esa frase con números debajo.

Evaluator-optimiser, y el juez que escribió el examen

Enlace a la sección: Evaluator-optimiser, y el juez que escribió el examen

Una llamada genera, otra evalúa, y el bucle se repite hasta que la evaluación pasa.1 Los antepasados publicados son Self-Refine —el mismo modelo como "generator, refiner, and feedback provider", con unos 20 puntos de mejora absoluta de media en siete tareas3— y Reflexion, que guarda la crítica en un búfer episódico entre intentos y comunica un 91 % de pass@1 en HumanEval, donde el baseline alcanzó el 80 %.4

El modelo de costes es el más sencillo de los cinco: dos llamadas por ronda, y el número de rondas no es tuyo. Tres rondas de refinamiento en una tarea que llevaba una llamada son seis llamadas, así que el suelo del patrón es 6× y su techo es el límite que pongas; eso convierte la salida por presupuesto del capítulo 23 en obligatoria, no en ordenada.

El techo es más sutil, y medible. En los mismos 20 problemas, el modelo local acertó 9. Luego se le mostró cada una de esas respuestas y se le preguntó si era correcta —sin decirle que la respuesta era suya, lo que elimina el confusor de la adulación y deja el de la capacidad—:

la propia respuesta del modelodijo "sí"dijo "no"
las 9 correctas90
las 11 incorrectas38

Es un juez mejor de lo que implica el título de la sección, y decirlo es precisamente el sentido de medir en lugar de afirmar: no bloqueó nada correcto y detectó 8 de 11 errores. Como filtro, merece sus llamadas.

Como regla de parada, que es para lo que en realidad lo usa un bucle evaluator-optimiser, esas tres aprobaciones son toda la historia: terminan el bucle con una respuesta incorrecta en la mano, y ninguna cantidad de rondas adicionales llega nunca a ellas. Un bucle de refinamiento no puede volverse más correcto que su juez. Comprar más rondas compra intentos sobre los errores que el juez puede ver, a precio completo, y absolutamente nada contra los que no puede.

De ahí la regla: un evaluator se gana sus llamadas solo cuando tiene algo que el generator no tiene. Un compilador, una suite de tests, un validador de esquemas, un modelo diferente, un humano. Los propios resultados de Self-Refine se miden contra preferencia humana y métricas de tarea, nunca contra la opinión del modelo sobre sí mismo. Si la única ventaja de tu evaluator es un prompt diferente, estás pagando el doble por estar de acuerdo. El capítulo 29 construye la versión con una ventaja real: un conjunto dorado con las respuestas escritas de antemano.

Los cinco anteriores son formas para tu código. Debajo de ellos se sienta una segunda familia que a menudo se lista junto a ellos y no debería: ReAct, Reflexion, plan-and-execute y tree of thoughts son bucles de razonamiento, y su coste está en peticiones.

El capítulo 12 trataba del razonamiento dentro del modelo, que pagas en output tokens en una llamada. Este es el otro tipo. La diferencia importa cuando llega la factura: una chain of thought más larga encarece una llamada, y un bucle de razonamiento convierte una tarea en muchas llamadas, cada una de las cuales reenvía todo lo anterior: la cuadrática que el capítulo 23 midió en su tabla desbocada.

buclellamadas, por tareaqué compran las llamadas extra
ReActuna por paso, hasta que se detieneel modelo reacciona a lo que devolvieron las herramientas5
plan-and-executeuna para planificar, luego una por pasoel plan se fija antes de que se ejecute el primer paso6
Reflexionintentos × (act + reflect)la crítica sobrevive al siguiente intento4
tree of thoughtsfactor de ramificación × profundidad, más una evaluación por nodobúsqueda, con backtracking7

El paper de tree of thoughts publica su propia tabla de costes, algo más raro de lo que debería. En Game of 24 con GPT-4: input/output prompting best-of-100 resolvió el 33 % a $0.13 por caso, chain of thought best-of-100 resolvió el 49 % a $0.47, y tree of thoughts resolvió el 74 % a $0.74, con los autores señalando que "podría requerir entre 5 y 100 veces más tokens generados que CoT".7

Casi seis veces el precio del método barato por algo más del doble de tasa de éxito. Que sea una ganga depende de cuánto te cueste un caso fallido: la pregunta que debes hacer antes de adoptar cualquiera de estos cuatro.

Este curso no los reimplementa. Los cuatro tienen implementaciones de referencia de sus propios autores, en Python, y su valor está en ser la fuente en lugar de una traducción: ysymyth/ReAct, noahshinn/reflexion, princeton-nlp/tree-of-thought-llm y AGI-Edgerunners/Plan-and-Solve-Prompting. Lee los prompts de esos repositorios; los prompts son los papers.

Ahora sí, multi-agent propiamente dicho, donde vive la mayor parte de la confusión. Hay dos formas de que un agent implique a otro; no son variantes, y la diferencia es quién manda después.

Agent como herramienta. El padre lo llama, obtiene una respuesta y continúa. Es la interfaz de herramienta del capítulo 18 con todo un agent detrás, y el padre nunca pierde el control. Esto es lo que hace el orchestrator de arriba.

Handoff. El padre transfiere la conversación y no la recupera. La guía de OpenAI es la declaración publicada más clara: los handoffs son "una transferencia en una sola dirección que permite a un agent delegar en otro agent... Si un agent llama a una función de handoff, empezamos inmediatamente la ejecución en ese nuevo agent al que se ha hecho handoff, transfiriendo también el estado de conversación más reciente".8

Una advertencia de vocabulario, porque esto confunde constantemente: "handoff" es la palabra de un SDK, no un estándar. Es terminología del OpenAI Agents SDK y de esa guía, que también llama a las dos disposiciones "manager" y "decentralized" y señala que en el patrón manager "las aristas representan tool calls, mientras que en el patrón decentralized las aristas representan handoffs".8 Sí hay un estándar abierto en este espacio —A2A, en versión 1.0.0, bajo copyright de la Linux Foundation, con historial de versiones y una lista documentada de breaking changes— cuyo principio declarado es opaque execution: los agents "colaboran en función de capacidades declaradas e información intercambiada, sin necesidad de compartir sus pensamientos internos, planes ni implementaciones de herramientas".9 Eso no es un handoff, y la comparación corresponde al capítulo 26. Lo importante aquí es que una de las dos palabras es la API de una biblioteca y la otra es una especificación con gobernanza.

La distinción es una estructura de datos, no un diagrama:

graph.tsTS
export type EdgeKind = "tool" | "handoff";
export interface AgentEdge { from: string; to: string; kind: EdgeKind }
export interface AgentGraph { root: string; agents: Record<string, AgentSpec>; edges: AgentEdge[] }

/** One agent may not be both a tool of X and a handoff target of X. */
export function conflicts(g: AgentGraph): AgentEdge[] {
  const seen = new Map<string, EdgeKind>();
  const bad: AgentEdge[] = [];
  for (const e of g.edges) {
    const key = `${e.from}->${e.to}`;
    const other = seen.get(key);
    if (other && other !== e.kind) bad.push(e);                            
    else seen.set(key, e.kind);
  }
  return bad;
}

/** Every agent reachable from the root, and at what depth. */
export function reachable(g: AgentGraph): Map<string, number> {
  const depth = new Map([[g.root, 0]]);
  const queue = [g.root];
  while (queue.length) {
    const id = queue.shift()!;
    for (const e of g.edges.filter((x) => x.from === id)) {
      if (depth.has(e.to)) continue;
      depth.set(e.to, depth.get(id)! + 1);
      queue.push(e.to);
    }
  }
  return depth;
}

Veinte líneas, dos bugs que de otro modo encontrarías en producción. reachable encuentra el agent al que nadie puede llegar: configurado, pagado, nunca llamado. conflicts rechaza la arista que es de ambos tipos a la vez, algo que suena pedante hasta que lo lees en voz alta: el padre conserva el control y lo entrega a la vez. Ejecútalo sobre un sistema de cinco agents con un huérfano y una arista doble:

TEXT
reachable: lead@0 billing@1 tax@1 dunning@1
orphans:   ghost
conflicts: lead->tax

Ahora la medición para la que existe esta sección, y la única del capítulo tomada contra un modelo real en lugar de uno guionizado.

Un cliente declara una restricción en su primer mensaje —nuestra cuenta está registrada en Portugal, no en España; todo lo relacionado con impuestos tiene que usar Portugal—, charla sobre otra cosa y luego hace una pregunta que debe responder facturación. El caso se transfiere. Veinticuatro ensayos, un país y una empresa distintos cada vez, cuatro payloads de transferencia, y al agent receptor se le hace después una pregunta: ¿en qué país está registrada la cuenta de este cliente?

qué se transfiriópayload mediola restricción estaba dentroel especialista la recordóintervalo del 95 %
toda la conversación173 tokens24/2420/24 — 83 %64–93 %
un resumen escrito por el agent emisor62 tokens1/240/24 — 0 %0–14 %
solo el último mensaje del usuario61 tokens0/240/24 — 0 %0–14 %
un registro tipado69 tokens24/2424/24 — 100 %86–100 %

La tercera fila es un control y se comporta como tal: el dato no está ahí, así que no puede recordarse. Las otras tres son el hallazgo.

La transcripción completa tiene 173 tokens y funciona el 83 % de las veces; sus cuatro fallos pertenecen al tema del capítulo 24, no al de este. El registro tipado tiene 69 tokens —siete más que el resumen— y funciona siempre, porque la restricción está en un campo con nombre en lugar de una frase.

Y la fila del resumen es la que hay que mirar fijamente. Falló 24 veces de 24, y la razón no es que el lector no lo viera. La restricción apareció solo en 1 de los 24 resúmenes. El agent receptor no fue descuidado; se le entregó un texto que no contenía la respuesta. Un resumen es una compactación que tú no escribiste, producida por un modelo cuya ventana no puedes ver, optimizada para leerse como un resumen; y "el cliente dice que nuestros registros tienen el país equivocado" es exactamente el tipo de cláusula que un summariser elimina como ruido procedimental.

Un límite honesto para ese número: el summariser es un modelo de medio billón de parámetros y uno mayor conservaría más. Lo que no mejora con el tamaño es la forma del riesgo: el agent emisor decide, por handoff, por redacción y de forma inobservable, qué datos sobreviven. El registro tipado no depende de ese juicio en absoluto, por eso gana por construcción y no por inteligencia. Todo lo que deba sobrevivir a una transferencia debería ser un campo, no una frase.

El mismo razonamiento se aplica en la otra dirección, a la topología agent-como-herramienta, y la tabla anterior ya le puso precio: lo que vuelve de un worker también es un resumen, y pagar un 8,3 % más para recibir la evidencia con él es la misma solución vista desde el lado del padre.

Tres hechos finales, todos de las tablas anteriores.

Un sistema multi-agent multiplica las llamadas, y las llamadas son cuadráticas en context. El orchestrator hizo 12 llamadas al modelo donde un agent hizo 5, y cada una lleva su propia transcripción creciente: 3,628 input tokens frente a 2,697, una brecha que se ensancha con la longitud de la tarea.

Cada frontera es un canal con pérdidas. Dos agents significan un resumen. Cuatro agents en cadena significan tres, compuestos, cada uno escrito por un modelo que optimiza algo distinto de tu decisión.

El agent único encontró algo que nadie pidió. La discrepancia del pedido de compra afloró porque una sola ventana contenía la factura y el pedido a la vez. Dividir el trabajo entre especialistas también divide la capacidad de notar que dos datos discrepan.

Nada de esto argumenta contra los frameworks multi-agent publicados, que merece la pena leer como fuentes primarias y no a través de tutoriales.10 Argumenta a favor de hacer que el segundo agent se gane su sitio.

Así que, una prueba en lugar de una preferencia. Añade un segundo agent cuando al menos una de estas cosas sea cierta: la subtarea necesita una ventana limpia que el padre no debe heredar (capítulo 24); las subtareas son genuinamente independientes y el tiempo real importa, que es el 1,8× de arriba; la subtarea necesita permisos diferentes o un modelo distinto, algo que el capítulo 30 convierte en un argumento de seguridad; o la subtarea es propiedad de otra persona, que es donde un protocolo real empieza a importar. Si la respuesta es "para que cada agent tenga un prompt más claro", dale al agent único un prompt más claro. Es gratis.

Ya puedes nombrar los cinco patrones, compararlos en coste sobre una tarea, distinguir un orchestrator de un sectioner y una tool call de un handoff, y defender un agent único con una tabla en lugar de una preferencia.

Todas las disposiciones de aquí compartían una comodidad que no sobrevivirá al contacto con nada real: todas las herramientas nos pertenecían. Factura, pedido, tabla fiscal, los workers detrás del orchestrator: mismo repositorio, mismo deploy, mismos tipos, mismas personas.

Ahora pon una de ellas al otro lado de la frontera de una empresa. La tabla fiscal pertenece a un proveedor contable, el registro del pedido a un sistema de almacén, y ninguno ha leído tu interfaz Tool. Necesitas una forma de que un modelo que no escribiste descubra, describa y llame a una capacidad operada por otra persona: con autenticación (que es la mitad del capítulo 27), versionado y la garantía de que un servidor no puede leer el resto de tu conversación. Eso es un problema de protocolo, tiene una especificación con un esquema normativo, y casi todo lo indexado sobre él describe una revisión que ya no existe.

El capítulo 26 lee esa especificación en lugar de resumirla, y empieza tecleando JSON-RPC en un terminal a mano.


Cada coste y recuento de tokens anterior procede del proveedor guionizado descrito en la segunda sección, en Node 22 sobre una interfaz loopback, contando con la codificación o200k_base y valorado con las tarifas que el capítulo 16 leyó el 6 de septiembre de 2026: $2.00 por millón de input tokens y $12.00 por millón de output. Las cifras de tiempo real proceden de las mismas ejecuciones con la latencia del proveedor fijada en 400 ms por llamada y las herramientas en 50 ms, de modo que miden la disposición y no ningún proveedor. Las dos mediciones con modelo real —la tabla de handoff y la tabla de voting y judging— usaron Qwen/Qwen2.5-0.5B-Instruct en float32 sobre CPU detrás de un endpoint con la misma forma, greedy salvo donde se indica una temperature, con intervalos calculados mediante el método de Wilson del capítulo 4. Ninguna petición de este capítulo fue a un endpoint de pago, y ningún número de él fue estimado.

  1. Anthropic, Building effective agents, 19 de diciembre de 2024, anthropic.com/engineering/building-effective-agents, leído el 7 de septiembre de 2026. Fuente de los cinco nombres de workflow usados arriba y de cada frase citada de ellos —prompt chaining, routing, parallelisation con sus variantes sectioning y voting, orchestrator-workers, evaluator-optimiser—, así como de la recomendación de encontrar "la solución más sencilla posible, y aumentar la complejidad solo cuando sea necesario" y la observación de que "los sistemas agentic suelen intercambiar latencia y coste por un mejor rendimiento en la tarea". Los capítulos 22 y 23 citan su definición de agent. 2 3 4 5 6 7

  2. Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A. y Zhou, D. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (marzo de 2022). El origen del patrón voting, descrito allí como una estrategia de decoding en lugar de una arquitectura: samplear rutas de razonamiento diversas y luego "seleccionar la respuesta más consistente marginalizando las rutas de razonamiento sampleadas", con mejoras comunicadas de +17,9 en GSM8K, +11,0 en SVAMP, +12,2 en AQuA, +6,4 en StrategyQA y +3,9 en ARC-challenge.

  3. Madaan, A. et al. Self-Refine: Iterative Refinement with Self-Feedback. arXiv:2303.17651 (2023). El bucle evaluator-optimiser con un modelo en los tres roles —"generator, refiner, and feedback provider"— que mejora "en torno a un 20 % absoluto de media en rendimiento de tarea" en siete tareas, medido por preferencia humana y métricas automáticas en lugar de por el veredicto del propio modelo.

  4. Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. y Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023). Añade una memoria episódica de autocríticas entre intentos —"reforzar language agents no actualizando pesos, sino mediante feedback lingüístico"— y comunica un 91 % de pass@1 en HumanEval frente al 80 % del baseline GPT-4. Observa el requisito del que dependen sus resultados: una señal real del entorno, como un test fallido, en lugar de la opinión del modelo sobre sí mismo. 2

  5. Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. y Cao, Y. ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629 (2022). Trazas de razonamiento y acciones intercaladas; el capítulo 23 construyó este bucle. Citado aquí por su forma de coste más que por sus resultados: una llamada al modelo por paso, con toda la transcripción reenviada cada vez.

  6. Wang, L., Xu, W., Lan, Y., Hu, Z., Lan, Y., Lee, R. K.-W. y Lim, E.-P. Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models. arXiv:2305.04091 (2023). "Primero, idear un plan para dividir toda la tarea en subtareas más pequeñas, y luego llevar a cabo las subtareas según el plan": la forma planificar-y-luego-ejecutar, y la fuente del intercambio que le importa a este capítulo: el plan se fija antes de que llegue la primera observación, que es prompt chaining con la descomposición escrita por un modelo en lugar de por ti.

  7. Yao, S., Yu, D., Zhao, J., Shafran, I., Griffiths, T. L., Cao, Y. y Narasimhan, K. Tree of Thoughts: Deliberate Problem Solving with Large Language Models. arXiv:2305.10601 (2023). Búsqueda sobre "thoughts" intermedios con autoevaluación y backtracking; 74 % en Game of 24 frente al 4 % de chain-of-thought prompting. Las cifras de coste citadas arriba son las del propio paper, del apéndice B.3, tabla 7: por caso, input/output prompting best-of-100 a $0.13 para 33 %, chain of thought best-of-100 a $0.47 para 49 %, y tree of thoughts a $0.74 para 74 %, con la nota de los autores de que ToT "podría requerir entre 5 y 100 veces más tokens generados que CoT". 2

  8. OpenAI, A practical guide to building agents (PDF), leído el 7 de septiembre de 2026. La división manager frente a decentralized, el encuadre de grafo citado arriba ("en el patrón manager, las aristas representan tool calls, mientras que en el patrón decentralized las aristas representan handoffs") y la definición de handoff como "una transferencia en una sola dirección... empezamos inmediatamente la ejecución en ese nuevo agent al que se ha hecho handoff, transfiriendo también el estado de conversación más reciente". Observa lo que resuelve esa última cláusula: en este SDK el estado de conversación sí viaja, lo cual es una decisión de diseño de esa biblioteca y no una propiedad de los handoffs en general. 2

  9. Agent2Agent (A2A) Protocol Specification, última versión publicada 1.0.0, a2a-protocol.org/latest/specification/, leído el 7 de septiembre de 2026; copyright de la Linux Foundation, Apache-2.0. Citado arriba: un "estándar abierto diseñado para facilitar la comunicación y la interoperabilidad entre sistemas AI agent independientes y potencialmente opacos", y el principio de opaque execution: los agents "colaboran en función de capacidades declaradas e información intercambiada, sin necesidad de compartir sus pensamientos internos, planes ni implementaciones de herramientas". La página incluye un historial de versiones (0.1.0, 0.2.6, 0.3.0, 1.0.0), un apéndice de breaking changes y un apéndice sobre su relación con MCP. El capítulo 26 hace esa comparación.

  10. Los frameworks multi-agent que este capítulo no enseña, para quien quiera las fuentes primarias en lugar de un tutorial: Wu, Q. et al., AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation, arXiv:2308.08155 (2023), donde los agents son "customizable, conversable" y la propia conversación es el modelo de programación; Hong, S. et al., MetaGPT: Meta Programming for a Multi-Agent Collaborative Framework, arXiv:2308.00352 (2023), que codifica procedimientos operativos estándar en role prompts y explicita que "las soluciones a tareas más complejas se complican por inconsistencias lógicas debidas a alucinaciones en cascada causadas por encadenar LLMs ingenuamente": la cadena confiadamente incorrecta medida al inicio de este capítulo, nombrada en un resumen; y Park, J. S. et al., Generative Agents: Interactive Simulacra of Human Behavior, arXiv:2304.03442 (2023), veinticinco agents con memoria, reflexión y planificación, que es la mayor respuesta publicada a "qué pasa si sigues añadiendo agents".

¿Listo para dejar que elija LIA?

Crea con todos los modelos de IA en un mismo sitio. Empieza gratis hoy.