Anoche desplegué AutoML en una flota de diez agentes en una sola sesión. El coste mensual adicional fue cero euros. No porque encontrara un descuento, sino porque la matemática en el corazón del routing de agentes no necesita una llamada a un LLM.
La flota corre cada dos domingos y escribe informes de diez a quince páginas para un cliente real que paga por el servicio. Hasta ayer, los nueve worker corrían en cada ejecución, incluso cuando solo cuatro o cinco realmente tenían algo que decir sobre ese cliente concreto. La nueva capa observa cómo de bien rinde cada worker, aprende qué workers valen la pena para cada perfil de cliente, y en unas semanas estará lista para disparar solo los mejores cuatro o seis. La factura sigue igual. El throughput sube.
Escribo esto porque el patrón es brutalmente simple, transferible a casi cualquier setup con varios agentes, y fuera de los círculos académicos casi nadie habla de lo barato que realmente es.
El setup que nadie había cuestionado
Operamos un servicio llamado StudioMeyer Agents. Diez agentes especializados trabajan sobre un cliente a la vez, y un Master Agent cose sus findings en un informe coherente. Cuatro agentes revisan señales del sitio web como visibilidad, traffic, competencia y SEO técnico. Tres revisan visibilidad en IA, es decir LLM Citations, Brand Mentions y fuentes citadas. Dos revisan tendencias del sector. El último, el Master Synthesizer, lee los nueve informes y escribe la versión que llega al cliente.
Para nuestro cliente piloto, una agente inmobiliaria anti-lujo en Mallorca, el Master dispara cada dos domingos. Para el propio StudioMeyer también cada dos domingos, en otro slot. Cada ejecución consume una buena porción de tokens del Anthropic Max Plan. Cada ejecución produce también 40 a 80 KB de informes estructurados de los workers, más el markdown que llega al cliente.
Aquí está la parte que nadie había preguntado. ¿Cuáles de estos nueve workers realmente contribuyen? Algunas semanas el Technical SEO Agent no tiene nada que decir porque nada cambió en la capa técnica. Algunas semanas el KI Visibility Agent encuentra doce nuevas citations y el Master construye medio informe alrededor de eso. Distintos tipos de cliente tiran de distintos agentes. Un cliente de turismo probablemente se beneficia más de los agentes de visibilidad y de búsqueda local. Un cliente B2B SaaS tira más de los agentes de competencia y citation.
La flota corre productivamente desde la Phase D a mediados de mayo 2026. Funciona. Pero dejábamos señal sobre la mesa al tratar a los nueve agentes como igualmente relevantes para cada cliente.
Por qué AutoML normalmente significa una factura del vendor
Si le dices a la mayoría de engineers "deberíamos meter AutoML en nuestra flota de agentes", ellos escuchan "paguemos a DataRobot, SageMaker Autopilot o Vertex AI por el privilegio". Eso es una solución real para un problema distinto. Ninguna de esas plataformas es barata, y ninguna se construyó para la pregunta de qué subset de mis LLM agents debo correr para el cliente X este martes.
El otro instinto es dejar que el LLM decida. Construye un Meta Agent cuyo trabajo es leer el perfil de cada cliente, decidir qué Sub Agents disparar, y orquestarlos. Funciona. Pero también significa que cada decisión de routing es ahora una llamada a un LLM, con latencia, presupuesto de tokens y superficie de alucinación.
Hay una tercera opción, y es Production Standard para problemas de routing desde principios de los 2010 en adtech y sistemas recomendadores. Solo ha hecho falta esperar hasta AAAI 2026 para que alguien preparara un tutorial aplicándolo explícitamente al routing de LLM agents. IBM Research presentó dos en enero, "Bandits, LLMs, and Agentic AI" y "Multi-Armed Bandits Meet Large Language Models". El equipo de vLLM Semantic Router hizo el mismo punto en su vision paper de abril 2026 y recomendó Multi Armed Bandits para enrutar queries según features contextuales.
El patrón es más antiguo que la era LLM. El problema del Multi Armed Bandit asume que tienes un número fijo de opciones (slot machines, ad creatives, bloques de contenido, o en nuestro caso worker agents) y un presupuesto finito de intentos. Quieres aprender cuáles opciones rinden y explotarlas, pero ocasionalmente probar las otras para asegurarte de que tus creencias siguen siendo actuales. El código en producción lo hace en docenas de líneas.
El AdaptOrch Benchmark del Augment Code Orchestration Guide midió el routing overhead en menos de 50 milisegundos. En comparación, la inferencia de LLM está entre 2 y 15 segundos por agent call. La matemática es prácticamente gratis.
Doce líneas de matemática
Aquí está la fórmula que desplegué anoche. Es Bayesian Additive Smoothing, también conocido como Laplace Smoothing o Beta Binomial Conjugate Prior, según en qué artículo de Wikipedia caigas primero. La página de Additive Smoothing tiene la versión más limpia.
export function bayesianMean(
observed: Array<number | null>,
priorMean: number,
priorWeight: number,
): number {
const valid = observed.filter(
(x): x is number => x !== null && Number.isFinite(x),
);
if (valid.length === 0) return priorMean;
const sum = valid.reduce((acc, x) => acc + x, 0);
return (priorWeight * priorMean + sum) / (priorWeight + valid.length);
}
Ese es el núcleo completo. La intuición. No empiezas desde "no tengo datos, así que no puedo rankear". Empiezas desde una creencia prior, expresada como una media y un pseudo sample count. Con priorMean = 0.6 y priorWeight = 5 el prior dice que cada worker es decentemente bueno (0.6 en una escala de 0 a 1), y que estoy tan seguro de ello como si hubiera observado ya cinco samples.
Cuando llega el primer sample real, se promedia con los cinco pseudo samples. La estimación se mueve, pero no violentamente. Tras cinco observaciones reales, el prior tiene exactamente el mismo peso que los datos. Tras veinte observaciones reales, el prior es esencialmente ruido y las mediciones reales dominan.
¿Sobre qué se puntúa cada worker? En nuestro caso sobre tres señales, todas extraídas del propio informe del worker.
La Verify Confidence es un valor entre 0 y 1 que el worker se asigna a sí mismo al final de cada informe en un bloque destinado a ello. Lo hicimos obligatorio en la Session 1068 como parte de la capa contra alucinación. Ahora es la entrada primaria para el ranking.
El Source Citation Count cuenta cuántos tool calls y fuentes externas el worker citó en su bloque de fuentes. Un número alto significa trabajo respaldado por evidencia. Un número bajo significa que el worker se apoyó en su training data.
La Domain Lock Pass Rate es un sí o no por ejecución. ¿Se mantuvo el worker en el dominio real del cliente o se desvió a subdominios de staging o sitios de la competencia?
El Composite Score es una suma ponderada.
rankScore =
smoothedConfidence * 0.5 +
normalize(smoothedSourceDensity) * 0.3 +
domainLockPassRate * 0.2;
Cincuenta por ciento en la autoinforme del worker, treinta por ciento en densidad de evidencia, veinte por ciento en higiene. Tres palancas afinables más tarde, cuando haya suficientes datos para discutir la ratio correcta. Ninguna de estas tres señales requirió infraestructura nueva. Ya estaban en cada informe del worker, escritas por los propios agentes, para el guard contra alucinación. La capa de ranking solo las lee.
Cold Start es el problema real
La mayoría de tutoriales sobre Multi Armed Bandit empiezan con Exploration versus Exploitation. El dilema clásico. ¿Sigues jugando con la slot machine que mejor ha pagado hasta ahora, o pruebas la que no has tirado en un rato?
En producción ese no es el problema difícil. El problema difícil es qué hacer el día uno, cuando tienes cero datos, o el día tres, cuando tienes datos sobre tres de nueve workers y nada sobre los seis restantes.
El equipo de Facebook Reels lo resolvió en 2023 con Thompson Sampling sobre Posterior Samples para Content Cold Start, sacando de la distribución posterior en vez de de un estimador puntual, de modo que contenido nuevo seguía teniendo una oportunidad justa. Los papers de 2026 sobre bandits que incorporan un LLM van más allá. Dejan que un LLM prediga las observaciones que faltan y las inyectan en el bandit como pseudo datos, ponderadas por cómo de bien las predicciones del LLM han coincidido con la realidad hasta ahora.
Consideré ambas. Por ahora desplegué algo más simple, un guard duro para cold start. Si el número total de ejecuciones observadas está por debajo de tres, la función de recomendación simplemente devuelve "los nueve workers, fase de exploración". No se toma ninguna decisión de routing con un dataset tan pequeño. Tras tres ejecuciones tenemos nueve workers por tres samples más el prior, lo cual basta para una recomendación suave. Tras diez a veinte ejecuciones, el prior se desvanece en el ruido.
if (totalRunsObserved < MIN_SAMPLES_FOR_RECOMMENDATION) {
return {
coldStart: true,
recommendedWorkers: rankings.map((r) => r.agentKuerzel), // los 9
...
};
}
Es un trade-off deliberado. Un bandit más sofisticado como LinUCB o Thompson Sampling también haría una recomendación suave desde el día uno. Pero una recomendación suave en el día uno es exactamente el tipo de cosa que te muerde en la semana tres, cuando te das cuenta de que el sistema ha favorecido desproporcionadamente al agente que tuvo suerte en su primera ejecución. Mejor pagar nueve ejecuciones completas durante la ventana de cold start y desplegar una decisión de routing segura en la semana seis que una decisión inestable de inmediato.
Tools en Closure, o por qué Tenant Isolation aquí tampoco cuesta nada
El Master Synthesizer tiene que llamar esto efectivamente. Lo hacemos con dos Inline Tools, track_worker_performance y get_worker_ranking. Ambos se registran en el Master Agent en buildtime.
El patrón con el Customer Slug en el closure merece un párrafo, porque es el tipo de cosa que te muerde el día en que onboardeas al cliente número dos. Aquí está la firma relevante.
export function buildTrackPerformanceInlineTool(
customerSlug: string,
agentResolver: (kuerzel: string) => SmaAgentDef | undefined,
options: { dryRun?: boolean } = {},
): SdkMcpToolDefinition {
return {
name: "track_worker_performance",
description: `... Customer-Slug locked a "${customerSlug}". ...`,
handler: async (args) => {
// customerSlug capturado por closure, NO como argumento del tool
const metrics = buildMetricsFromReport({ customerSlug, ... });
return await recordWorkerPerformance(metrics);
},
};
}
El LLM nunca ve el Customer Slug como un parámetro que pueda escribir. El slug está horneado en el tool a buildtime. Incluso si el Master Synthesizer alucina a media ejecución "déjame también trackear este informe para el otro cliente", no hay parámetro que pueda pasar, y no hay ruta que pueda enrutar el write al bucket de otra persona. Es el mismo patrón de aislamiento que usamos para el Inline Tool de analytics de la Session 1069, y no nos ha fallado ni una vez en unas treinta ejecuciones del master.
Para defense in depth, la capa de base de datos valida adicionalmente el formato del slug, por si alguien más tarde construye un script que llama directamente a la librería y le pasa accidentalmente un valor parecido a Path Traversal. Nuestro Code Critic Agent lo encontró en la misma sesión y me obligó a añadirlo.
Qué despliega Phase 1, y qué desplegará Phase 2
Phase 1, la que pasó anoche a live, es informativa. El Master recoge datos de performance de cada informe que lee, los persiste en una tabla nueva sma_worker_performance con un cap duro de 5000 filas por cliente, para que la memoria quede acotada, y ofrece una vista de ranking a quien pregunte. La lógica real de routing, la parte que decide "dispara solo smasicht y smakonk para clientes de turismo", aún no está cableada. La flota sigue disparando los nueve agentes en cada cycle.
Eso es a propósito. La flota ha corrido productivamente solo un puñado de veces. Aún no tenemos suficientes datos para sacar conclusiones. Si hubiera desplegado routing directamente, ahora estaríamos optimizando contra un patrón de ruido.
Phase 2 es la capa de routing. Vivirá en sma-run-all.ts, el script que dispara el cron schedule. Lee la recomendación de la capa de ranking, escoge los Top Dos del módulo Website más los tres del módulo GEO más los Top Dos del módulo Business, un default de siete en vez de nueve, y respeta un Anti Stale Guard. Cualquier worker que no haya corrido en sesenta días, corre igual, independientemente de su rank. Eso mantiene viva la exploración incluso cuando entra la exploitation.
El ahorro de coste en el presupuesto de tokens al saltar dos agentes por ejecución, cada dos semanas, sobre dos clientes, ronda entre el veinte y el veinticinco por ciento menos de tokens del Anthropic Max Plan por cycle. Calculado para un año, equivale aproximadamente a un cliente adicional de margen dentro del mismo flat rate.
A qué voy a estar atento
Algunas cosas que podrían salir mal y que quiero atajar antes de que pasen.
El Verify Confidence Score lo da el propio worker. Los workers podrían aprender a inflarlo, igual que los empleados aprenden cuál es su métrica de performance y la juegan. En nuestro caso los workers no saben en realidad que el score se usa para el ranking. El System Prompt no lo menciona. Pero en cuanto lo metamos en el prompt, aparece este incentivo. Voy a mantener las fuentes de señal para el ranking sin mencionar en los prompts de los workers.
La regla "los nueve en cold start" podría atraparnos. Si un cliente fundamentalmente nunca necesita el KI Visibility Agent porque es un B2B SaaS sin branding público, el sistema lo va a disparar para siempre, le pondrá puntuación baja para siempre, y nunca cruzará del todo el umbral para dejarlo caer. Un refinamiento futuro es un floor para confidence baja. Si un worker está por debajo de 0.4 durante más de cinco ejecuciones, pídele al master que argumente a favor o en contra de dejarlo caer, con el perfil del cliente en contexto.
La ponderación de 50 a 30 a 20 es una conjetura. Tras diez cycles en Phase 2 deberíamos tener suficiente varianza para preguntarnos si la división realmente correlaciona con la calidad del informe en el cliente. Si no, las ponderaciones deberían moverse.
La parte replicable
Vuelvo a esto. La capa matemática son doce líneas, el SQL es una tabla, la integración son dos Inline Tools. Desplegar Phase 1 costó una sesión enfocada. Phase 2 costará similar, principalmente porque todo el plumbing de datos ya existe.
Si operas cualquier tipo de flota con varios agentes, ya sea un pipeline de Customer Onboarding, una Research Squad, un sistema de generación de contenido o un Code Review Orchestrator, el mismo patrón aplica. Ya tienes probablemente una señal de confidence en algún sitio de tu pipeline, sean Eval Scores, Judge Models, Retry Rates, longitudes de output o simplemente un número auto-reportado. Ya tienes probablemente una señal de higiene, es decir, ¿se mantuvo el agente en la tarea, citó fuentes, escribió más de 500 caracteres de contenido real? Lo que no tienes, hasta que lo construyas, es un récord de esas señales a lo largo del tiempo, normalizado a través de clientes o queries, y una función de menos de 100 milisegundos que convierte el récord en una decisión de routing.
Así es como AutoML realmente se ve cuando no se compra a un vendor. Se ve como una tabla, una función y un guard. El "ML" es un archivo SQL de 1.96 KB y un estimador bayesiano que un estudiante de grado podría escribir. El "Auto" viene del hecho de que nadie tiene que mirar los datos. El sistema se actualiza solo en cada ejecución.
La factura del vendor es cero porque el LLM es la cosa que se enruta, no la cosa que enruta. La matemática no necesita un modelo de mil millones de parámetros. Necesita un prior, un counter y un sort.
Si quieres ver la implementación completa, la migration en SQL, el wiring de los Inline Tools en el Master Synthesizer y la test suite que cubre Bayesian Smoothing, Extract Logic y Cold Start, el código de StudioMeyer Agents está documentado en studiomeyer.io/services/agents. O si quieres un patrón similar construido para tu propia flota, el mismo servicio se encarga de la implementación.
