Lección 2: Encadenar y enrutar: encadenamiento y enrutamiento
Objetivos de aprendizaje:
- Partir un prompt de cuatro tareas en una cadena y enunciar qué estás cambiando y qué estás ganando
- Instalar compuertas programáticas entre las etapas de la cadena para que los resultados intermedios que no califican se detengan donde corresponde
- Decidir cuándo una tarea necesita encadenamiento, enrutamiento, ambos o ninguno, y escribir la llamada de enrutamiento como una sola llamada barata con la salida apretada
Requisitos: Leíste la Lección 1, puedes escribir a mano un bucle de arnés impulsado por stop_reason (curso 7 de esta serie), entiendes los verificadores deterministas (curso 10 de esta serie) | Anterior: << Lección 1 | Siguiente: Lección 3 >>
Un solo prompt haciendo cuatro cosas: una se va a caer
Necesitas escribir la documentación de ayuda de una función nueva: leer los requisitos del producto → redactar un esquema → escribir el texto completo a partir del esquema → revisar el documento en busca de terminología obsoleta.
Tu primera versión probablemente meta los cuatro pasos en un solo prompt y se lo entregue a un bucle de arnés. La primera ejecución se ve bien. El problema aparece en la segunda, y en la tercera: esta vez el esquema es bueno pero al texto le falta una sección; la siguiente vez el texto está completo pero viene mezclado con «grupos de usuarios», que quedaron obsoletos en la versión anterior; después reescribe el esquema a mitad de camino y entrega un esquema que no coincide con el texto.
Estas fallas se ven distintas en la superficie, pero comparten la misma raíz: en una sola llamada, el modelo tiene que hacer malabares al mismo tiempo con entender los requisitos, diseñar la estructura, generar el texto y hacer revisiones de consistencia. No puedes controlar cuál queda apretada hasta salirse, y no puedes verlo ocurrir. Peor todavía, no tienes ningún lugar donde intervenir: para cuando tienes la salida, las cuatro cosas ya están hechas, y «el esquema no cumplió la especificación» quedó enterrado dentro del borrador final.
La Lección 1 habló del eje de «quién tiene el plan». Este prompt de un solo tiro le entrega el plan entero al modelo. Lo primero que hace esta lección es recuperarlo.
Encadenamiento: cambiar latencia por precisión
La definición oficial de este patrón son solo dos oraciones, y cada palabra carga peso.
El encadenamiento de prompts descompone una tarea en una secuencia de pasos, donde cada llamada al LLM procesa la salida de la anterior. Puedes añadir comprobaciones programáticas (ver "gate" en el diagrama de abajo) en cualquier paso intermedio para asegurarte de que el proceso sigue en curso1. Cuándo usar este flujo de trabajo: este flujo de trabajo es ideal para situaciones donde la tarea se puede descomponer fácil y limpiamente en subtareas fijas. El objetivo principal es cambiar latencia por mayor precisión, haciendo de cada llamada al LLM una tarea más fácil1.
«Hacer de cada llamada al LLM una tarea más fácil»: esa media oración te da a la vez el diagnóstico y la cura. Una llamada que hace cuatro cosas es una tarea difícil; una llamada que solo redacta un esquema y no escribe nada más es una tarea fácil. El encadenamiento no reduce el trabajo: hace más simple el trabajo que el modelo tiene que completar en cada llamada.
El costo viene impreso en la etiqueta de precio: latencia. Cada etapa adicional suma una ida y vuelta completa. Anthropic dejó planteada esta contabilidad al principio del mismo artículo: los sistemas agénticos a menudo intercambian latencia y costo por un mejor desempeño en la tarea, y habría que considerar cuándo tiene sentido ese intercambio1. «Lento y caro» no es un efecto secundario accidental del encadenamiento.
La entrada de cada segmento es la salida del segmento anterior. Si un eslabón se tuerce, todo lo que viene después lo sigue.
Cada etapa es un bucle de arnés completo
Una etapa de la cadena no es «una llamada a la API»: es un bucle de arnés completo. El mismo bucle while que escribiste a mano en el curso 7 de esta serie: envía los mensajes, revisa stop_reason, si es tool_use entonces ejecuta la herramienta y devuelve el resultado, si no devuelve el texto.
Este uso tiene una fuente. Cuando Anthropic describió cómo evaluar agentes, la configuración recomendada era exactamente esta forma: llamadas directas a la API del LLM, bucles agénticos simples (bucles while que envuelven llamadas alternadas a la API del LLM y a herramientas), un bucle por tarea de evaluación, y a cada agente de evaluación se le da un solo prompt de tarea y tus herramientas2. Aquel artículo trataba de evaluación, pero el bloque de construcción en sí es de propósito general: una tarea, un bucle, impulsado por código. El encadenamiento es ensartar estos bloques con el código decidiendo el orden.
El resto de las lecciones usa la misma notación:
La cadena entera es código secuencial que puedes leer de un vistazo:
Fíjate en lo que no está en estas líneas: no hay espacio para «el modelo decide qué hacer a continuación». La secuencia está fijada en duro, y los resultados intermedios outline y doc son variables corrientes del script. El modelo sigue siendo autónomo dentro de cada etapa (puede llamar a herramientas tantas veces como quiera), pero el control entre etapas está en manos del código. Un beneficio adicional: el prompt de cada etapa puede ser estricto en una sola cosa. El prompt del esquema exige solo títulos y prohíbe cualquier texto de cuerpo; el prompt de escritura se concentra en el estilo y en los términos prohibidos; estos dos conjuntos de requisitos chocarían si se empacaran en un solo prompt.
Esta forma aparece también en los productos. La documentación oficial de Claude Code recomienda, para los flujos de trabajo de varios pasos, que Claude use subagentes de forma secuencial, y que cada uno complete su tarea y devuelva los resultados a Claude, que luego pasa el contexto relevante al siguiente subagente3. La diferencia aterriza sobre el eje de la Lección 1: en la forma de producto, Claude decide «qué pasar»; cuando escribes el script, eso es tu código.
Compuertas: mover los verificadores del curso 10 entre etapas
La última media oración de la definición es lo que el encadenamiento de verdad añade por encima de «un prompt grande»: puedes añadir comprobaciones programáticas en cualquier paso intermedio para asegurarte de que el proceso sigue en curso1. El texto original llama a estas comprobaciones "gate", y va entre comillas: (see "gate" in the diagram below) —una recta, una curva, exactamente como en la fuente, no es una errata de aquí—.
«Programáticas» es la clave: es código, no otra llamada al modelo, apenas unos cuantos if.
El curso 10 de esta serie enseñó verificadores deterministas: cuando algo se puede juzgar como correcto o incorrecto con código, no gastes dinero preguntándole al modelo. Aquel curso instalaba los verificadores en el estado final: después de que todo se ejecuta, revisar si la salida es aceptable. El encadenamiento le ofrece a esa misma comprobación una ubicación nueva: entre etapas.
Siete líneas, ni una sola llamada al modelo, y la misma entrada produce siempre el mismo juicio. Bloquea exactamente esa falla del «texto mezclado con términos obsoletos»; una compuerta que cuente cuántos títulos de capítulo hay en el esquema es igual de simple.
Qué hacer cuando una compuerta falla es una decisión de diseño: detenerse y reportar el error (lo mejor mientras todavía estás afinando esta cadena, pero el mensaje de falla tiene que decir qué etapa falló, si no solo sabes «no funcionó», no qué prompt de etapa arreglar), realimentar el motivo de la falla al prompt de la misma etapa y reintentar (con un tope de reintentos), o registrarlo y continuar con un valor de repliegue (solo cuando esta etapa no carga peso). El ejercicio de Nivel 2 usa el primer enfoque.
Esto además salda la cuenta del curso 6 de esta serie: el trabajo que delegas tiene que llevar prompts autocontenidos —objetivo, formato de salida, herramientas disponibles, límites, los cuatro escritos—. La tarea de cada etapa es un prompt de delegación con exactamente esa forma. Estos cuatro elementos tienen una fuente primaria precisa, que la Lección 4 desglosará punto por punto cuando cubra cómo delegan los orquestadores.
Enrutamiento: primero clasificar, luego despachar
El encadenamiento se ocupa de «una tarea partida en pasos». Otra clase de tareas tiene una forma completamente distinta: lo que entra no es una cosa, son varias clases de cosas, cada una con su propio tratamiento.
La definición oficial: el enrutamiento clasifica una entrada y la dirige hacia una tarea de seguimiento especializada. Este flujo de trabajo permite la separación de responsabilidades y construir prompts más especializados. Sin este flujo de trabajo, optimizar para un tipo de entrada puede perjudicar el desempeño en otras entradas1.
La última oración es la razón de que exista el enrutamiento. Supón que los correos de clientes caen en tres categorías: reembolso, incidencia, facturación. Usas un solo prompt para manejar todo. Para manejar bien los reembolsos añades una línea: «confirma primero el número de pedido y el canal de pago»; esta regla es puro ruido para los correos de incidencia, y el modelo la usará para pedirle el canal de pago a alguien que reporta una página en blanco. Añades otra línea, «si es una incidencia, no pidas el número de pedido», y el prompt empieza a criar parches sobre parches.
Cuándo usar este flujo de trabajo: el enrutamiento funciona bien para tareas complejas donde hay categorías distintas que conviene manejar por separado, y donde la clasificación se puede resolver con precisión, ya sea con un LLM o con un modelo o algoritmo de clasificación más tradicional1. Esa última precondición no es la guinda del pastel: si la clasificación se equivoca, se equivoca de forma sigilosa —un correo de reembolso enrutado al flujo de incidencias recibe una respuesta concienzuda de diagnóstico técnico—.
En código, el enrutamiento es más simple que el encadenamiento:
Tres cosas que vale la pena notar.
Aprieta la salida de la llamada de clasificación a una sola palabra: el curso 10 de esta serie usó el mismo truco al hablar de los jueces LLM —enumera los valores permitidos, di que no haya explicación; apretar la salida vuelve determinista el paso de análisis sintáctico—. Si no encaja en la tabla, al repliegue: esa línea LABELS.includes(label) ? label : 'other' no es pedantería defensiva. El modelo ocasionalmente devuelve «creo que podría ser incidencia, o quizá otra cosa», y entonces HANDLERS[esa cadena entera] es undefined y la línea siguiente se cae. Deja una rama de repliegue y la incertidumbre de la clasificación queda contenida en esta única línea.
El clasificador no tiene por qué ser un modelo: la definición dice explícitamente que los modelos o algoritmos de clasificación tradicionales también cuentan1. Si el correo lleva un formato fijo de número de pedido o viene de un punto de entrada de formulario dedicado, una sola expresión regular alcanza y es mucho más rápida.
Después del despacho, cada manejador puede ser cualquier cosa: un bucle de arnés, una cadena, incluso un tramo de código completamente sin modelo.
Dos variantes de enrutamiento en el vocabulario actual de la API
La definición de enrutamiento de arriba viene del artículo de patrones de finales de 2024, que lleva un cartel diciendo que sus descripciones del ecosistema de herramientas están desactualizadas. Así que vale la pena comprobarlo: ¿este patrón sigue vivo en el vocabulario actual de primera mano? Sí, y se lo nombra explícitamente. La documentación de orquestación multiagente de la plataforma Claude tiene dos entradas que son enrutamiento:
- Especialización (Specialization): Enrutar hacia agentes con prompts de sistema y herramientas centrados en un dominio, como un agente de seguridad o un agente de documentación, en lugar de cargar un solo agente con todas las capacidades4. Esta es la formulación oficial de la tabla
HANDLERS.
- Escalamiento (Escalation): Consultar a un agente o modelo más capaz para un subconjunto de subtareas complejas4.
La segunda merece mención aparte: despacha por dificultad, no por tema. El clasificador no juzga «¿esto es reembolso o incidencia?» sino «¿este correo lo puede manejar mi nivel barato?». Esto es más difícil de juzgar con precisión que la clasificación por tema, así que el camino de escalamiento tiene una escritura más estable: ejecuta primero el nivel barato, y si la salida no pasa la compuerta entonces escala; cambias un problema de clasificación difícil de juzgar por un problema de verificación comprobable.
Saber cuándo no partir
Cada eslabón de la cadena suma latencia. Esto no es una implementación sin optimizar, es el precio que fija la definición oficial: cambiar latencia por mayor precisión1. La persona usuaria espera la suma de cada segmento. Si está esperando de forma síncrona los resultados en una interfaz, antes de añadir otro eslabón a la cadena, considera si sigue ahí.
Cuando solo hay una categoría, el enrutamiento es puro sobrecosto. El beneficio del enrutamiento viene de la separación de responsabilidades1. Si la entrada de verdad tiene un solo tipo, pagaste el costo y la latencia de una llamada de clasificación y no recibiste nada a cambio, más una oportunidad extra de clasificar mal.
Cuando la tarea no se puede partir limpiamente, no la fuerces. La condición «descomponer fácil y limpiamente en subtareas fijas» tiene dientes1. Un borrador que necesita mirar el panorama completo de ida y vuelta para revisarse bien, si lo partes en «primero revisar la estructura, luego revisar la redacción», la segunda etapa no tiene acceso a las razones que la primera etapa no escribió, y solo revisará según el texto literal. En este caso un bucle, un contexto, es de hecho mejor: este es exactamente el uso de las condiciones inversas de la Lección 1.
Cuando tengas dudas, mide primero. Anthropic lo dijo dos veces: habría que considerar añadir complejidad solo cuando mejora demostrablemente los resultados1. La vía de evaluación del curso 10 de esta serie está construida para esto: ejecuta la versión de un solo prompt y saca una puntuación, ejecuta la versión partida y saca otra, mira cuánta diferencia hay y si vale esos segundos extra de latencia; esa es la evidencia que puedes llevar a una discusión con un colega.
Por último, marca la frontera. El encadenamiento y el enrutamiento son ambos orquestación de forma fija: cuántas etapas tiene la cadena, qué categorías tiene el enrutador, todo se decide cuando escribes el código. Ejecutar varias etapas a la vez y luego agregar es la paralelización de la Lección 3; ni siquiera saber cuántas subtareas hay hasta ver la entrada es el orquestador-trabajadores de la Lección 4.
💻 Ejercicios
Resumen
- El encadenamiento descompone una tarea en una secuencia de pasos donde cada llamada procesa la salida anterior, haciendo de cada llamada una tarea más fácil1; viene cotizado explícitamente: el objetivo principal es cambiar latencia por mayor precisión1.
- Una etapa de la cadena es un bucle de arnés completo, no una llamada a la API: la configuración que Anthropic recomendó para la evaluación es exactamente este bloque de construcción —una tarea, un bucle while, código llamando directamente a la API—2.
- Las posiciones que se añaden después de partir son la clave: puedes añadir comprobaciones programáticas en cualquier paso intermedio para asegurarte de que el proceso sigue en curso1. Este es el verificador determinista del curso 10 movido a otra ubicación de instalación —del estado final a entre etapas—; en forma de producto se ve como subagentes ejecutándose secuencialmente, cada uno completa y la capa superior pasa el contexto relevante al siguiente3.
- El enrutamiento clasifica la entrada y la despacha hacia tareas de seguimiento especializadas, ganando separación de responsabilidades y prompts más especializados; sin él, optimizar para un tipo de entrada puede perjudicar el desempeño en otras entradas1. Precondición: categorías claras y que la clasificación misma se pueda resolver con precisión, ya sea con LLM o con algoritmos de clasificación tradicionales1.
- Aprieta la salida de la llamada de clasificación a una sola etiqueta, y deja una rama de repliegue para atrapar las respuestas que no encajan en la tabla.
- Este patrón está vivo en el vocabulario actual de primera mano: despachar por dominio hacia agentes con prompts y herramientas dedicados se llama especialización, y consultar a un agente o modelo más capaz para un subconjunto de subtareas complejas se llama escalamiento4; este último es enrutamiento despachando por dificultad.
- No lo fuerces: cuando solo hay una categoría el enrutamiento es puro sobrecosto, y cuando la tarea no se puede partir limpiamente forzarlo perderá información entre etapas1. Cuando tengas dudas, mide primero: la complejidad tiene que pasar el umbral de «mejora demostrablemente los resultados»1.
>> Lección 3: Paralelización: seccionamiento y votación