Cómo orquestar agentes de IA sin que se pisen el contexto ni te fundan en tokens
Multi-agente no es poner tres LLMs a hablar. Es separar roles, limpiar la sesión en cada handoff y meter un presupuesto duro antes de que la factura te dé un susto.
En este artículo
Llevas montando “multi-agente” como un chat con personalidades
Abres un framework, clonas tres “roles” (investigador, redactor, crítico), les das el mismo hilo y rezas. A los dos días el contexto es un basurero, el modelo de razonamiento devuelve turnos vacíos y la factura de tokens ha hecho el ridículo.
Eso no es orquestación. Es tres loros en la misma jaula.
Esta guía es el mapa operativo: qué montar, en qué orden, qué botón conceptual pulsar y dónde la caga todo el mundo la primera vez. Cuando acabes, deberías poder abrir tu stack y aplicar un patrón concreto, no un sermonario de “agentes autónomos 10x”.
Qué es orquestar de verdad (y para qué te sirve)
Orquestar agentes es decidir quién habla, con qué contexto mínimo, con qué modelo y con qué tope de gasto, y que el resto sea código deterministicamente aburrido.
Te sirve cuando tienes un flujo con etapas separables: planificar una tarea, ejecutar tools, verificar el resultado, devolver un artefacto. No te sirve, todavía, si ni siquiera has clavao una sola llamada con retrieval y ejemplos en contexto.
Anthropic lo deja clarísimo en Building Effective AI Agents: empieza simple; optimiza llamadas individuales con retrieval y ejemplos in-context antes de construir sistemas agentic. Los setups simples reducen desperdicio de tokens y el infierno del debug. Multi-agente solo cuando el workflow tiene etapas separables, especialización profunda o tareas paralelizables. Si es tarea simple, necesitas baja latencia, presupuesto corto o estás en prototipo, quédate en un solo agente y valida valor primero.
BCloud (2025) mete el número gordo: la orquestación multi-agente suele multiplicar el coste de tokens entre 2× y 5× frente a un agente único por el overhead de coordinación. No es un detalle. Es el motivo por el que “montar cinco agentes” sin disciplina es tirar dinero con estilo.
Seamos justos: hay quien defiende que el multi-agente desde el día uno fuerza modularidad y que, si el framework te da el checkpointer y el router casi regalados, empezar con un solo agente es retrasar lo inevitable. El argumento no es idiota: en equipos con experiencia previa en grafos y presupuestos, el salto directo evita reescribir el chaining luego. La pega es que esa experiencia no abunda, y sin ella el framework oscurece los prompts y dispara costes antes de que sepas qué estás pagando. Por eso la regla sensata no es “nunca framework”, sino “no framework hasta que entiendas el código que te está cobrando”.
El orquestador dirige. No computa. Si el “cerebro central” también redacta el informe, llama a la API y se critica a sí mismo, no tienes orquestación: tienes un monólogo caro.
Requisitos antes de tocar un framework
- Un problema con etapas claras (plan → hacer → comprobar), no un “que el agente se apañe”.
- Acceso a al menos dos tiers de modelo (barato/rápido y capaz/caro) por API.
- Forma de persistir estado fuera del prompt (base de datos, checkpointer, fichero de handoff). Sin esto, cada turno reinyecta la Biblia.
- Contador de tokens o de coste por petición. Si no mides, no orquestas: improvisas.
- Disciplina de no meter un framework el día uno. Anthropic avisa: los agent frameworks como primer paso oscurecen los prompts y empujan complejidad innecesaria. Llamadas directas a la API hasta que entiendas el código que te está cobrando.
LangGraph, CrewAI, AutoGen y compañía existen. No hay uno solo “correcto”. Lo que cambia el partido no es el logo: es el contrato de contexto y el presupuesto.
Paso 0, Una cadena con puertas, no un enjambre
Antes del multi-agente, monta prompt chaining: partes la tarea en llamadas secuenciales; cada una come la salida de la anterior; entre medias metes gates programáticos.
Ejemplo realista: extraer datos de un PDF → validar schema en código → si falla, stop → si pasa, redactar resumen → otro gate de longitud/campos obligatorios.
Por qué importa: si el paso 1 sale basura y no hay gate, los pasos 2–5 son tokens regalados al vacío. Anthropic lo formula tal cual: checks programáticos tras cada paso; si falla, la cadena corta pronto y no quemas llamadas río abajo.
Routing es el siguiente escalón barato: clasificas la entrada y mandas lo fácil a un modelo pequeño y lo difícil a uno capaz. Misma fuente: separar concerns mejora prompts y corta coste en lo trivial.
Parallelization cuando de verdad sobra independencia: un modelo criba contenido inapropiado mientras otro responde; o varias pasadas y votación. Velocidad o confianza, no postureo.
Solo cuando eso se te quede corto pasas a supervisor/workers. No al revés.
El patrón que aguanta producción: planificador, ejecutor, verificador
Tres agentes (o tres nodos) con cerebros distintos y sesiones que no se heredan sucias.
1. Planificador (LLM listo, contexto doctrinal corto)
Recibe el encargo del usuario + reglas que siempre aplican. Devuelve un plan estructurado: pasos, tools permitidos, criterios de hecho, presupuesto estimado.
No llama a la red. No escribe el informe final. Parsea y planifica.
2. Ejecutor (código + LLM mínimo o sin LLM)
Toma el plan y ejecuta. HTTP, SQL, filesystem, MCP tools. El LLM aquí, si aparece, es para adaptar un parámetro o leer un error; no para “pensar la estrategia otra vez”.
MCP (Model Context Protocol) encaja justo aquí: defines tools en un servidor MCP; el agente las invoca por cliente; las acciones viven fuera y el contexto del agente se mantiene flaco. Microsoft lo describe así en su intro a agentes con MCP en Azure: offload de acciones, contexto más lean. Ojo: MCP no te salva solo de ensuciar el contexto; si reinyectas logs enteros al planificador, te lo cargas igual.
3. Verificador (otro LLM o reglas + LLM)
Recibe solo el artefacto + los criterios del plan. No el chat del ejecutor. No los stack traces completos. Dice pass/fail y, si fail, un diff accionable.
Separar verificador del ejecutor evita el autoengaño clásico: el mismo contexto que generó el error “explica” por qué en realidad está bien.
El orquestador (grafo, supervisor, o un simple state machine en tu lenguaje) elige qué nodo corre, pega el handoff y corta cuando el presupuesto o el gate lo digan. En LangGraph, el patrón orchestrator elige workers de forma dinámica (LLM o reglas), los despacha en paralelo con send() cuando toca, y un agregador sintetiza. No enciendes todos los nodos “por si acaso”: eso es quemar tokens con método. Platzi documenta la selección dinámica; en producción la decisión la manda un LLM o reglas de verdad, no un random de tutorial.
LangGraph además empuja estado compartido y checkpointers (por ejemplo Postgres) para no perder ni duplicar contexto entre interacciones largas. BCloud insiste en lo mismo: estado centralizado para no liar inconsistencias; sin él, cada agente se inventa su versión de la verdad y vuelves a pegar los mismos tokens.
Handoff escrito y sesión limpia (la regla que más dinero ahorra)
Cuando el planificador termina, no le pases al ejecutor el historial completo. Escribes un handoff:
- Objetivo en una frase.
- Pasos restantes.
- Inputs concretos (IDs, paths, URLs ya resueltas).
- Constraints (timeouts, tools permitidos, formato de salida).
- Qué cuenta como éxito.
- Tokens/coste ya consumidos y techo restante.
Ese documento es el nuevo system/user seed del siguiente agente. Sesión nueva. Cero “como dijimos arriba”. Cero chistes del turno 3. Cero tool traces de 40 KB.
Si necesitas memoria a largo plazo, vive en la capa de datos determinista, no en el scroll del chat. El hilo es volátil; el estado es la fuente de verdad.
Lo que debe saber SIEMPRE va en reglas; lo que quizá necesite, en recall
Con un vault bonito y un buscador encima, la tentación es dejarlo todo a retrieval: “ya preguntará cuando haga falta”.
Mal. Una regla del tipo “el dinero nunca en coma flotante” o “no inventes IDs de pedido” solo sirve si está delante al escribir la línea. Un agente no busca lo que no sabe que ignora.
El error simétrico: inyectar doscientas notas de doctrina en cada llamada. Te comes el presupuesto de contexto y el modelo deja de distinguir lo crítico de lo decorativo.
Patrón operativo:
- Reglas: pocas, duras, siempre en el prefijo (y estables para cache; ya llegamos).
- Recall: under demand, con query explícita, trozos pequeños, citables.
- Handoff: el puente entre etapas; no es ni regla ni enciclopedia.
Si te suena al debate Obsidian/Claude Code vs RAG: son dos memorias para problemas distintos; no sustituyas una con la otra y llames al invento “agente con memoria”.
Router de modelos por tier, fallback y presupuesto duro
Aquí es donde dejas de rezar y empiezas a cobrar como adulto.
Define un ModelSpec por capacidad, no por romanticismo de marca:
- Tier 0, clasificar/rutear: modelo barato, poca salida, baja latencia.
- Tier 1, planificar / verificar estructurado: modelo medio o fuerte según riesgo.
- Tier 2, razonamiento duro / casos borde: modelo caro, tope de salida alto, uso escaso.
- Fallback: si Tier 2 timeout o 5xx → Tier 1 con prompt más estricto, o cola de retry; si el clasificador duda, sube de tier, no bajes a ciegas.
Una función tipo generate_with_fallback(spec, messages, budget) que:
- Estima tokens de entrada.
- Reserva techo de salida según el tier.
- Llama al proveedor.
- Suma coste real al acumulado de la sesión/flujo.
- Si el acumulado rompe el techo → lanza
BudgetExceededy el orquestador para. No “intenta una última vez con el modelo dios”.
Routing de Anthropic y este router son primos: lo fácil a Haiku-clase (el nombre concreto del modelo barato de tu proveedor hoy; verifica el catálogo actual), lo difícil al capable. La diferencia de producción es el presupuesto como excepción, no como dashboard que miras el viernes.
Si quieres el montaje con proveedor intercambiable y números de cableado, está la guía del router por tier con presupuesto y fallback. Aquí el punto de orquestación es otro: cada rol tiene un tier por defecto, y el orquestador no deja que el ejecutor “se auto-promocione” a Opus porque le apetezca razonar.
Trampa del modelo de razonamiento
En conversaciones multi-turno con modelos de razonamiento, se ve un fallo cabroncete: finish_reason: stop, sin error, y content vacío. No falló la API. El modelo se comió el presupuesto pensando.
Patrón observado en la trinchera: con poco contexto (turno 1) razona y aún le queda hueco para responder. Cuando el hilo engorda, el razonamiento interno se zampa el cupo (cientos de tokens de “thought”) y la respuesta visible sale vacía. Subir techos de forma asimétrica (por ejemplo diana ~3000, atacante/agresivo ~1500 según rol) desplomó los vacíos en pruebas internas de ~40% de turnos vacíos a algo del orden de 1 de 20.
Traducción operativa:
- No pongas el mismo
max_tokensal planificador razonador y al clasificador tonto. - No reutilices hilos kilométricos con reasoning models; handoff limpio otra vez.
- Si ves stops “exitosos” sin texto, mira el reparto thought vs content antes de culpar al proveedor.
El presupuesto de contexto se gestiona eligiendo, no resumiendo
Resumir el hilo entero “para que quepa” es la droga de entrada. Pierdes IDs, condiciones y matices; el agente alucina con seguridad renovada.
Gestionar es elegir:
- ¿Este tool result de 15 KB lo necesita el verificador? Casi nunca. Quédate con exit code, hash, y 20 líneas de error.
- ¿El planificador necesita el HTML crudo? No. Necesita el JSON ya parseado por tu código.
- ¿Hace falta el historial de intentos? Lista de “probado X → error Y”, no los cinco monólogos.
El LLM planifica y parsea estructuras; el código ejecuta y toca la red. Cada vez que dejas que el modelo “decida” un GET con headers y reintentos dentro del prompt, mezclas plano de control con plano de datos y engordas el contexto con ruido irreproducible.
Truncar por bytes es corrupción silenciosa
text[:4000] sobre un string UTF-8 o, peor, sobre un JSON o un mensaje multiparte, te parte un carácter, una clave o un cierre de bloque. El modelo no te dice “oye, me has castrado el JSON”. Sigue. Inventa el cierre. Envenena el siguiente paso.
Hazlo bien:
- Trunca por unidades semánticas: mensajes, turnos, secciones, tool results enteros.
- Si cortas texto libre, corta por tokens del tokenizer del modelo (o por párrafos) y marca explícitamente
[truncado]. - Nunca partas en medio de estructuras que luego vas a parsear.
- Prefiere drop del mensaje más viejo e irrelevante que un “resumen mágico” del medio del plan.
Prompt caching: igualdad de bytes del prefijo, no una etiqueta mental
Si tu system prompt es largo y estable, el caching de prefijo del proveedor te puede salir rentable. La condición no es “yo creo que es el mismo prompt”: es igualdad de bytes del prefijo.
Cualquier fecha dinámica, UUID de sesión o “hoy es martes” metido al principio rompe la caché. Mételo después del bloque estable.
No aplica si el prefijo estático es corto: por debajo del mínimo de tokens del proveedor la caché ni entra y reorganizar no compensa.
Orden sano del prefijo:
- Reglas inmutables del negocio / seguridad.
- Esquemas y formatos de salida.
- Catálogo estable de tools (nombres y specs).
- A partir de aquí lo volátil: fecha, user id, handoff del turno.
Canario antes de que el enjambre vea producción
Orquestación sin canario es fe en la prompt engineering. Monta un puñado de casos fijos:
- Encargo simple que no debe escalar a multi-agente.
- Encargo con dos subtareas que sí debe paralelizar workers.
- Encargo malicioso o fuera de política (el ejecutor no debe tener la tool).
- Encargo que agota presupuesto a propósito → esperas
BudgetExceeded, no una factura sorpresa. - Reasoning largo con techo justo → no quieres content vacío.
Mide: tokens totales, nodos tocados, tasa de handoffs limpios (¿el ejecutor recibió historial basura?), tasa de pass del verificador, latencia p95. Si el orchestrator enciende todos los workers en el caso simple, tienes un bug de routing, no un “agente proactivo”.
Errores comunes (donde se va el dinero)
- Tres agentes, un solo contexto compartido tipo chat grupal. Se pisan conclusiones, se reescriben hechos y nadie sabe quién metió el ID malo.
- Orquestador que también escribe la respuesta final. Mezclas dirección y trabajo; el estado se vuelve ilegible.
- Framework el día uno sin haber hecho chaining con gates. Luego no sabes si el fallo es del grafo, del prompt o del modelo.
- Todo en recall, nada en reglas. El agente viola la política que “estaba en el vault” porque nadie la puso delante.
- Todo en reglas. Contexto obeso; el modelo atiende al ruido.
- Mismo tier para clasificar y para razonar. O te arruinas o te quedas corto.
- Sin
BudgetExceeded. El “ya lo limitamos en el dashboard” no detiene un bucle a las 3:00. - Resúmenes agresivos y truncate por bytes. Corrupción elegante. Los peores bugs no lanzan excepción.
- Verificador con el mismo hilo que el ejecutor. Goma de mascar cognitiva: todo le parece coherente.
- Multi-agente por moda. Fuentes serias coinciden en el contraste: Anthropic y BCloud empujan simple-first; LangGraph/Platzi brillan cuando ya hay etapas y paralelismo real. La tensión se resuelve fácil: complejidad solo contra un cuello de botella medido, no contra el FOMO del timeline.
Montaje mínimo reproducible (checklist)
- Escribe el flujo en una pizarra: entradas, etapas, salidas, gates.
- Implementa una cadena con checks en código. Sin framework si puedes.
- Extrae reglas eternas a un system prefijo estable (cache-friendly).
- Introduce handoff JSON/Markdown entre etapas; sesiones nuevas.
- Separa planificador / ejecutor (código + tools/MCP) / verificador.
- Pon router por tier +
generate_with_fallback+ contador yBudgetExceeded. - Estado central (checkpointer o DB). El prompt no es tu base de datos.
- Canarios en CI con techos de tokens. Falla el build si el caso simple toca Tier 2.
- Solo entonces evalúa workers en paralelo tipo orchestrator-worker para encargos multi-tarea (consejo + booking, análisis + tickets, etc.).
Si en el paso 2 ya cumples el SLA y el margen, para. El multi-agente heroico que nadie pidió es la forma más sofisticada de regalar margen a la API.
Cierre
Orquestar no es tener más agentes. Es tener contratos de contexto, roles que no se solapan, código donde toca la red y un presupuesto que manda parar. El resto es teatro con temperatura 0.7.
Abre tu flujo actual, localiza el primer sitio donde tres roles leen el mismo hilo sucio, y rompe esa sesión hoy. El ahorro se ve en la factura; la cordura, en el debug.
Preguntas frecuentes
¿Cuándo compensa pasar de un solo agente a multi-agente?
Cuando el workflow tiene etapas separables, especialización real o subtareas paralelizables y ya mediste un cuello de botella. En tareas simples, prototipos, baja latencia o presupuestos justos, un solo agente suele bastar. El multi-agente puede costar de 2× a 5× más tokens por coordinación; solo págalo si el valor está demostrado.
¿Qué es un handoff limpio entre agentes?
Un documento estructurado con objetivo, pasos restantes, inputs concretos, constraints, criterio de éxito y presupuesto consumido, usado como semilla de una sesión nueva. No reenvíes el chat completo ni los tool traces crudos. Así evitas que un agente arrastre basura de contexto y pise hechos del anterior.
¿Por qué un modelo de razonamiento devuelve respuestas vacías sin error?
Porque el razonamiento interno se come el max_tokens y no queda cupo para el content visible. La API puede devolver finish_reason: stop igual. Sube el techo de salida según el rol, acorta el hilo con handoffs y no uses el mismo límite en clasificadores baratos que en planificadores razonadores.
¿El orquestador tiene que ser un LLM?
No necesariamente. Puede ser reglas, un state machine o un grafo que solo a veces consulta un LLM para elegir workers. Lo crítico es que dirija: despachar, aplicar gates y cortar por presupuesto. Si el orquestador también ejecuta tools y redacta el entregable, vuelves al monólogo caro con marketing de “multi-agente”.