Pasé las últimas semanas armando una wiki de 16 módulos sobre sistemas agénticos, desde qué es físicamente un LLM hasta lo de frontera con multiagente. No la escribí a mano. Corrí workflows de Claude Code, un pipeline de investigación multiagente, para redactarla y verificarla de forma cruzada, y después la estudié hasta entenderla lo suficiente como para poder discutirle.
Este post es lo que saqué de ahí. Es la versión condensada y práctica: qué priorizar y qué ignorar si quieres construir agentes que de verdad aguanten. Todo lo que sigue está destilado de esa wiki, y cada sección enlaza al módulo donde vive el argumento completo y las fuentes calificadas.
La parte incómoda es que casi nada de la lista de prioridades tiene que ver con el modelo.
Haz la aritmética p^t antes de escribir una línea de código
Este es el número que nadie calcula. Si cada paso de tu agente acierta de forma independiente con probabilidad p, y la tarea toma t pasos, la tarea entera acierta con probabilidad p^t. Los errores no se suman. Se multiplican.
Una tarea de 10 pasos donde cada paso es fiable al 90% aterriza en 0.9^10 ≈ 35%. Sube cada paso al 95%, ponle 20 pasos, y aun así estás en 0.95^20 ≈ 36%. La intuición humana subestima esto con fuerza, y por eso tantos agentes lucen perfectos en el demo (un happy path corto) y mueren en producción (uno real y largo).
Esa única curva orienta todas las demás decisiones. Te da exactamente tres palancas: subir p (fiabilidad por paso), reducir t (acortar la cadena), o partir la cadena en segmentos que reinicien el error. "Usa un modelo más listo" es una forma débil de mover p y no hace nada por t. La mayoría de las cosas que "necesitan un agente" funcionan mejor como un workflow determinista o una sola llamada, una vez que ves lo que la aritmética te exige. Esa decisión es lo primero que te obliga a enfrentar el módulo de agente como política.
Rompe la cadena: verifica contra ground truth
Si la fiabilidad decae de forma geométrica, lo de mayor palanca que puedes construir (después de conocer tu número) es algo que reinicie el error a mitad de la cadena. Pon una compuerta de verificación en medio y un catastrófico p^20 se vuelve dos segmentos más amables de p^10.
El truco está en que la verificación tiene que venir de fuera del modelo. Un resultado real de un tool. Un test que pasó o falló. La fila que de verdad se escribió en la base de datos. Preguntarle al modelo "¿lo lograste?" y creerle no sirve, porque el evaluador comparte los puntos ciegos del generador. La autocorrección intrínseca no mejora el razonamiento de forma fiable y a veces lo empeora. El ground truth es lo único que de verdad reinicia el error por paso, y por eso el módulo del loop de control trata el feedback observable como la pieza que carga el peso del loop, no el prompt.
Controla el loop desde código; el modelo es un reducer
El instinto es entregarle todo el flujo a un framework que "solo le da vueltas al LLM". Está al revés. Escribe tú el loop externo, en código normal y testeable, y deja que el modelo decida solo lo que de verdad no puedes hardcodear: qué tool llamar, cómo redactar la respuesta.
Piensa en el modelo como un reducer sin estado: (estado, observación) → (pensamiento, llamada_a_tool). Todo lo durable (locks, presupuestos de tokens, ruteo, persistencia, reintentos) es software aburrido que puedes testear y matar cuando quieras. Sacar eso del plano estocástico es de donde sale la fiabilidad que separa el demo de producción. El modelo no tiene frenos, ni dirección, ni memoria entre turnos. Las tres se las pones tú.
La guarda de ese diagrama es la condición que todos saltan. Sin un chequeo de no-progreso, un agente quemará feliz todo su presupuesto de tokens repitiendo una sola llamada que falla. La terminación necesita varias condiciones: objetivo alcanzado, presupuesto agotado y sin progreso desde el último turno. Más sobre la forma del loop en el módulo del agent loop.
Los tools SON el espacio de acción: diséñalos como UX, no como un wrapper de API
El modelo solo puede ser tan preciso como los tools que le des. Razona sobre los nombres, los schemas y (esta es la parte que la gente pasa por alto) los strings de error que tú escribiste. Reacciona a texto. No puede pasar por un debugger.
El error más común es espejar tu base de datos: un tool por tabla, UUIDs crudos de ida y vuelta, un bloque de 8K tokens de respuesta. Eso maximiza el número de llamadas secuenciales que el modelo tiene que orquestar, lo que (recuerda la aritmética) maximiza las formas en que puede fallar. Colapsa N llamadas en un tool que complete un workflow entero, devuelve valores que un humano podría leer, y escribe los errores como instrucciones sobre las que el modelo pueda actuar.
// Un tool por tabla. El modelo tiene que orquestar todo el baile,
// sostener UUIDs en el contexto y adivinar el orden correcto cada vez.
get_user(id) -> { user_id: "8f3c...", tz_id: 42 }
list_slots(resource_id, day) -> [ bloque de 5000 tokens de filas crudas ]
create_booking(user_id, slot_id) -> 201
// Ante un input malo recibes: 400. Cada flecha es otra p. Cinco tablas, cinco oportunidades de soltar la cadena.
// Un tool para el workflow que el agente de verdad completa.
// Resuelve, chequea disponibilidad y agenda, de forma idempotente.
schedule_event({ customer: "Ana", service: "corte", when: "mar 5pm" })
-> { status: "agendado", with: "Ana", at: "2026-06-30 17:00", id: "evt_91" }
// Ante un input malo, el error ES el siguiente prompt:
-> { error: "usa ISO-8601 en `when`; enviaste '5pm'. ¿Querías 17:00?" } Una flecha. Retornos semánticos. El error le dice al modelo cómo corregirse solo.
Un tool que devuelve 8K tokens no acertó, envenenó los siguientes turnos. Limita y pagina la salida, dale namespace a los catálogos grandes, y haz idempotente cada escritura. El tratamiento completo está en un tool es UX para un LLM.
Gasta el contexto como un presupuesto de atención
Una ventana de 1M de tokens hace que "mételo todo" parezca gratis. No lo es. La atención es aproximadamente O(n²), y la recuperación se hunde en una curva en U bastante antes del límite nominal. Cada token irrelevante diluye la señal a la que el modelo está atendiendo y cuadruplica el costo. Más contexto no es más inteligencia.
Trata la ventana como el estado de creencia del agente y cúrala en cada turno. Mantén identificadores ligeros dentro de la ventana y trae los datos pesados justo a tiempo a través de un tool. Desaloja salidas de tools que ya quedaron viejas en cuanto destilaste lo que importaba. Pon los hechos que cargan el peso al principio y al final, donde la recuperación es mejor. Cuando el agente empieza a alucinar, a repetir acciones o a perder el hilo, esas son patologías del estado de creencia. Se arreglan desalojando, no agrandando la ventana con la esperanza de que mejore. El módulo de ingeniería de contexto le pone nombre a cada modo de fallo para que puedas diagnosticar cuál estás viendo.
Tu eval es el sistema de control
Tu tasa de acierto está limitada por la fidelidad de tu eval, sin matices. Si el eval lee ruido, manejas a ciegas por más rápido que iteres. Y la parte que sorprende: el grader del eval, la recompensa de RL y cualquier fitness de automejora son matemáticamente el mismo objeto. Un grader que el modelo puede engañar es un grader que entrena activamente a tu agente para engañarte.
Dos reglas cargan casi todo el valor. Primero, construye los graders de abajo hacia arriba, desde un análisis de errores sobre trazas reales (codifica a mano unas 50 en temas de fallo, y luego escribe graders para las categorías frecuentes y costosas) en lugar de hacerlo de arriba hacia abajo contra las métricas que imaginaste. La distribución real de fallos casi nunca coincide con tu modelo mental previo. Segundo, condiciona los releases a pass^k, no a pass@1. Una sola corrida en verde no es fiabilidad.
Por qué pass^k, y por qué cae más rápido de lo que crees
pass@1 es un promedio en el mejor caso. pass^k pregunta si el agente acierta k veces seguidas, que es lo que "fiable" de verdad significa para cualquier cosa irreversible. Decae de forma exponencial: una tarea que pasa el 90% de las veces baja a 0.9^8 ≈ 43% en ocho corridas consecutivas. Y los errores por paso están correlacionados positivamente en la práctica (un contexto malo envenena cada paso siguiente), así que la realidad suele caer más rápido que lo que sugiere la aritmética de errores independientes. Califica el estado persistido (la fila en la base de datos), nunca la afirmación del modelo de que hizo la cosa. El módulo de evaluación recorre la calificación de trayectoria y los graders en código frente al LLM como juez.
La seguridad y la aprobación humana son arquitectura, no un mejor prompt
El prompt injection no tiene arreglo a nivel de modelo. El LLM concatena tu system prompt y los datos envenenados en un solo flujo indiferenciado sin frontera de privilegio, el clásico confused deputy. En un estudio sistemático, 12 defensas conductuales publicadas cayeron ante ataques adaptativos con más del 90% de éxito. El spotlighting y el "trata los documentos como datos, no como instrucciones" recortan la inyección medida de ~50% a menos del 2%, lo que suena estupendo hasta que un atacante adaptativo borra el residuo. Útil como defensa en profundidad. Nunca lo único entre el texto no confiable y una escritura.
La frontera tiene que vivir en código determinista. Capacidades default-deny acotadas a la tarea. Una allowlist de egress de salida (a menudo el único borde cuya eliminación parte toda la cadena del ataque). La Regla de Dos de los agentes: nunca dejes al agente sin supervisión con más de dos de estos tres a la vez: input no confiable, datos sensibles, y una acción que cambia estado o hace egress. Defiéndete del adversario en que el modelo podría convertirse bajo inyección, no del educado que rinde bien en los benchmarks de hoy.
El human-in-the-loop es la misma disciplina apuntada a la irreversibilidad. No confirmes todo (eso solo entrena al humano a aprobar de forma automática, y la única acción que importaba se aprueba junto con el resto). Pon compuerta solo a la cola del ~1% de escrituras irreversibles. Y cierra el hueco que casi nadie revisa:
Ambas son principios arquitectónicos generales, no features de un framework. El detalle vive en seguridad agéntica y human-in-the-loop.
Haz que cada paso sea barato y seguro de reintentar
La entrega distribuida es at-least-once. Un worker puede terminar una escritura y morir antes de registrar que la hizo, la cola la reentrega, y el paso corre otra vez. Un reintento ingenuo son dos bombas a la vez: una bomba de costo de tokens (vuelves a cobrar cada paso del modelo) y una bomba de doble reserva (vuelves a cobrar la tarjeta del cliente).
Envuelve cada paso en ejecución durable para que los pasos completados queden memoizados, y deriva una clave de idempotencia determinista de (workflow_id, step_id) que pases a cada llamada con efectos secundarios. En el reintento el motor reproduce los resultados cacheados y la API externa deduplica por la clave. Modela una aprobación humana como una suspensión durable, no como un worker bloqueado tres horas. Esto se compone con la aritmética p^t: cuando cada paso es barato y seguro de reintentar, reintentar una cadena inestable deja de dar miedo. El módulo de producción plantea el agente entero como un workflow distribuido durable, que es lo que es.
Qué ignorar (o al menos posponer)
Igual de importante es dónde no gastar la tarde. Cada fila de aquí es algo que se siente como progreso y en su mayoría no lo es.
| Movida tentadora | Por qué es una trampa | Haz esto en su lugar |
|---|---|---|
| Recurrir a multiagente 'porque escala' | ~79% de los fallos son de coordinación, no del modelo; el fan-out quema ~15× los tokens por cómputo paralelo, no por mejor razonamiento | Un solo agente lineal + compactación. Haz fan-out solo en exploración de solo lectura; mantén cada escritura en un único hilo |
| Confiar en el chain-of-thought como bitácora de auditoría | Los modelos actúan sobre pistas que nunca verbalizan y racionalizan después; la cadena visible suele ser no causal | Construye evals, compuertas y observabilidad sobre la trayectoria de llamadas a tools — lo que HIZO, no lo que dijo |
| Hacer fine-tuning primero | Enseña forma sobre fondo, ~1.5× de premium en inferencia, y entrenar sobre hechos nuevos sube la alucinación | Sube la escalera: prompt → few-shot → contexto/harness → RAG → fine-tuning al final. El harness es ~90% del ROI |
| Comprar una ventana de contexto más grande | La recuperación se hunde en una curva en U antes del límite; los tokens irrelevantes diluyen la atención aunque todo quepa | Minimiza la densidad de señal, no el encaje. Mide tu ventana efectiva real |
| Montar una vector DB por defecto | Un pipeline de embeddings para 50 docs es un pasivo de staleness y seguridad a cambio de nada | Corpus bajo ~200k tokens: cárgalo en contexto con caching. Léxico (BM25/grep) para identificadores y códigos |
| Tratar el spotlighting como la frontera de seguridad | Recorta la inyección ~50%→<2% pero un atacante adaptativo borra el residuo | Pon la frontera de privilegio en código determinista; deja el spotlighting solo como defensa en profundidad |
| Subir el thinking/effort al máximo 'por si acaso' | Pasado el codo entras en un régimen de sobrepensar: el acierto se aplana o cae mientras pagas por cada token de razonamiento | Mide la curva acierto-vs-tokens por ruta y fija el effort en el codo |
El patrón en las siete: cada una es el trabajo del modelo disfrazado de arquitectura, o arquitectura esquivada con un prompt. Las movidas tentadoras apuntan al LLM. Las movidas que funcionan apuntan al código a su alrededor.
Las preguntas que de verdad te estás haciendo
¿En serio necesito un agente para esto?
Haz primero la aritmética p^t. Si tu fiabilidad por paso y tu número de pasos no alcanzan tu objetivo, descompón el horizonte o baja a un workflow determinista o una sola llamada. La mayoría de las tareas que "necesitan un agente" no lo necesitan.
¿Debería usar un sistema multiagente?
No por defecto. Cerca del 79% de los fallos multiagente son de coordinación, no límites del modelo, y el fan-out quema unas 15× los tokens por cómputo paralelo, no por mejor razonamiento. Usa un solo agente lineal con compactación, haz fan-out solo en exploración de solo lectura, y mantén cada escritura en un único hilo.
¿Vale la pena el fine-tuning para mi agente?
Casi siempre es el último recurso, no el primero. Sube la escalera: prompt, few-shot, ingeniería de contexto y harness, RAG, y al final fine-tuning. El harness es cerca del 90% del ROI, y entrenar sobre hechos nuevos en realidad sube la alucinación.
¿Una ventana de contexto más grande hará a mi agente más fiable?
No. La recuperación se hunde en una curva en U bastante antes del límite nominal, y los tokens irrelevantes diluyen la atención aunque todo quepa. Minimiza la densidad de señal y mide tu ventana efectiva real.
Un agente con alta tasa de acierto se gana haciendo que cada paso sea barato y seguro de reintentar, y rompiendo la cadena de error con verificación contra ground truth. No con un prompt más listo, ni con un modelo más listo.
Si mañana te llevas una sola cosa a las manos, que sea la aritmética. Abre un cuaderno, escribe tu p y tu t, y mira p^t antes de arquitecturar nada. El número te dirá si necesitas un agente siquiera, dónde poner la compuerta de verificación, y cuál de estas prioridades es de verdad tuya para arreglar. Todo lo demás en este post está río abajo de esa única multiplicación.
La versión completa, con cada fuente calificada y las pruebas detrás de las afirmaciones, es la wiki de sistemas agénticos. Esto fue el mapa. Aquello es el territorio.
Conversación
Los comentarios viven en GitHub Discussions — inicia sesión con GitHub para responder.