Skip to content
This page has been auto-translated and may contain errors.View in English

Agentes ​

docs.scrimba.com

Un agente es un modelo que corre en un bucle, eligiendo la siguiente herramienta que llamar hasta que la tarea esté terminada. El resto de este capítulo trata sobre qué significa eso, dónde vale la pena usarlo y dónde te cuesta caro sin que te des cuenta.

El bucle del agente ​

En uso de herramientas el modelo llamaba a una sola función y tú devolvías el resultado. Pero algunas tareas requieren varios pasos, y no conoces esos pasos de antemano. "Encuentra el vuelo más barato y resérvalo" puede implicar buscar, comparar, revisar un calendario y luego reservar, y el modelo tiene que ir descubriendo esa secuencia sobre la marcha.

Entonces, en lugar de manejar una sola llamada a una herramienta, pones todo el proceso dentro de un bucle. Este ciclo que se repite es el bucle del agente, un turno que se repite hasta que la tarea está terminada:

  1. Envía la conversación y las herramientas disponibles al modelo.
  2. El modelo llama a una herramienta o da una respuesta final.
  3. Si llamó a una herramienta, ejecútala, agrega el resultado a la conversación y vuelve al paso 1.
  4. Si dio una respuesta final, detente.

En cada turno, el modelo ve todo lo que ha pasado hasta ese momento, incluyendo resultados de herramientas anteriores, y decide el siguiente movimiento. Esa es toda la diferencia con el uso de herramientas: sigues repitiendo el ciclo hasta que el modelo considera que terminó.

El cambio real está en quién tiene el control. En todos los capítulos anteriores, tu código decidía el flujo de control: tú elegías cuándo llamar al modelo, cuándo ejecutar una herramienta, qué venía después. Un agente le entrega esa decisión al modelo. El bucle sigue preguntando "¿qué debería pasar ahora?" y la predicción del modelo es la respuesta cada vez. Cambias control por flexibilidad, y ese intercambio es la fuente tanto del alcance como del riesgo.

Por debajo, no está pasando nada nuevo. Es la misma predicción sobre un contexto que crece, el mismo ida y vuelta de uso de herramientas repetido. El modelo no traza un plan y lo sigue. En cada turno predice el mejor siguiente paso a partir de lo que puede ver en ese momento, y luego el bucle vuelve a correr.

Cuando esto funciona, parece razonamiento hacia una meta. Cuando no funciona, el agente da vueltas sobre sí mismo o termina en un callejón sin salida, porque ninguna parte del sistema está sosteniendo el plan general.

JunoEl bucle del agente Un agente es el bucle de uso de herramientas repetido: envías la conversación y las herramientas, el modelo llama a una herramienta o da una respuesta final, tú ejecutas la herramienta y devuelves el resultado, y sigues así hasta que responde. En cada turno el modelo ve todos los resultados anteriores y elige el siguiente paso. La única idea nueva respecto al uso simple de herramientas es repetir el ciclo en lugar de manejar una sola llamada.

En uso de herramientas manejabas una sola llamada y devolvías el resultado. Un agente es ese ida y vuelta envuelto en un bucle, que corre hasta que el modelo decide que terminó. Ese bucle es el bucle del agente. Esta es la clave: dejas de escribir a mano la secuencia de pasos y permites que el modelo elija el siguiente en cada turno.

El ciclo tiene cuatro pasos:

  1. Envía la conversación más la lista de herramientas al modelo.
  2. El modelo responde con llamadas a herramientas o con una respuesta final en texto.
  3. Si pidió herramientas, ejecútalas, agrega cada resultado a la conversación y repite el ciclo.
  4. Si respondió, detente y devuelve el resultado.

El mecanismo que hace que esto funcione es que el modelo ve la conversación completa, cada vez más grande, en cada turno: tu solicitud original, cada llamada a herramienta que hizo y cada resultado que recibió. Ese contexto acumulado es la única memoria del agente. Cada predicción está condicionada por todo el historial hasta ese punto, y por eso puede encadenar pasos que dependen de resultados anteriores.

Un detalle que vale la pena mencionar desde ya: el paso 2 puede devolver varias llamadas a herramientas a la vez, no solo una. Cuando las llamadas no dependen unas de otras, como revisar el clima en tres ciudades, el modelo puede pedir las tres en un solo turno y tú las ejecutas juntas. Cuando una llamada necesita el resultado de una anterior, el modelo tiene que esperar ese resultado antes de poder pedir la siguiente, así que esas quedan repartidas en turnos separados. El bucle maneja ambos casos: ejecuta las llamadas que llegaron en ese turno, devuelve todos los resultados y vuelve a predecir.

No hay ningún plan global dentro de todo esto. El modelo predice el mejor siguiente paso a partir de lo que puede ver en ese momento, no a partir de un mapa de toda la tarea. Esa es la diferencia entre un agente y los pipelines fijos que has escrito antes, y por eso el mismo bucle que encadena pasos de investigación también puede terminar dando vueltas sin sentido.

JunoEl bucle del agente Un agente es el ida y vuelta de uso de herramientas metido en un bucle: envías la conversación más las herramientas, el modelo llama herramientas o responde, tú ejecutas las herramientas y devuelves los resultados, repites hasta que responde. La conversación que crece es la única memoria del agente, así que cada paso está condicionado por todos los resultados anteriores. Un turno puede devolver varias llamadas independientes a la vez, o una a la vez cuando cada una depende de la anterior. No hay ningún plan global en ninguna parte: cada paso es una nueva conjetura sobre el siguiente movimiento.

Un agente es el ida y vuelta de uso de herramientas puesto en un bucle y con el modelo al volante, el bucle del agente: el modelo elige la siguiente herramienta en cada turno, tú la ejecutas, devuelves el resultado, y sigues así hasta que emite una respuesta final en lugar de una llamada. El bucle tiene cuatro pasos y esa no es la parte interesante. La parte interesante es qué te da esta arquitectura y qué no.

El ciclo:

  1. Envía la conversación en curso más los esquemas de las herramientas.
  2. El modelo devuelve llamadas a herramientas o una respuesta final.
  3. Ejecuta las llamadas que haya, agrega los resultados, repite.
  4. Ante una respuesta final, devuélvela.

Un solo turno puede devolver múltiples llamadas a herramientas. El modelo emite llamadas en paralelo cuando las considera independientes (tres búsquedas sin dependencia de datos entre ellas), y llamadas en serie a través de varios turnos cuando una necesita primero el resultado de otra. No puedes forzar esto desde afuera: que el trabajo se paralelice o no es una decisión del modelo basada en la tarea que infirió, así que una tarea que crees paralela puede volver serializada y más lenta, y una que crees serial puede volver como un lote que debes estar listo para ejecutar en conjunto.

Aquí está el hecho estructural del que dependen todos los modos de falla. No hay un plan global. El modelo no sostiene un mapa de la tarea y lo ejecuta. En cada turno predice el siguiente paso a partir de la conversación actual, y esa conversación es todo el estado del sistema: tu prompt más cada llamada y resultado acumulado hasta ese momento.

Cada paso confía en el paso anterior, sin nada que verifique el conjunto. Por eso un agente que parece estar razonando hacia una meta en realidad está haciendo una secuencia de conjeturas localmente plausibles que, cuando funciona, terminan sumando.

La consecuencia que hay que internalizar desde ahora, porque la sección de salvaguardas se apoya en ella: como el estado es solo la transcripción que crece y cada paso está condicionado por ella, un resultado erróneo de una herramienta que ocurre temprano no se corrige, se construye sobre él. El error se propaga hacia adelante y se acumula, y ninguna parte del bucle está en posición de notarlo. La mayor parte del trabajo de confiabilidad en agentes consiste en lidiar con esa única propiedad.

JunoEl bucle del agente Un agente es el ida y vuelta de uso de herramientas en un bucle, con el modelo al mando: elige la siguiente herramienta, tú la ejecutas, devuelves el resultado, repites hasta que responde. Todo el estado es la transcripción que crece, y no hay ningún plan global en ninguna parte, solo una cadena de conjeturas sobre el siguiente paso, cada una condicionada por la anterior. Un turno puede devolver llamadas en paralelo cuando el modelo las considera independientes, o en serie cuando dependen unas de otras, y tú no controlas cuál. Quédate con esto: cada paso confía en el paso anterior, así que un resultado erróneo temprano se acumula hacia adelante sin que nada verifique el conjunto.

Un agente mínimo ​

Aquí está el bucle en código. Reutiliza las definiciones e implementaciones de herramientas de uso de herramientas y las envuelve en un bucle que corre hasta que el modelo deja de pedir herramientas.

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content  # no quiso ninguna herramienta: esta es la respuesta final

        # ejecuta cada herramienta solicitada y devuelve los resultados
        for call in calls:
            args = json.loads(call.function.arguments)
            result = tool_impls[call.function.name](args)
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "Detenido: el agente alcanzó su límite de pasos."  # red de seguridad

Léelo de arriba a abajo: llama al modelo, agrega su mensaje a la conversación, y si pidió herramientas, ejecútalas todas y agrega los resultados, luego vuelve a repetir. Cuando el modelo devuelve texto en lugar de una llamada a herramienta, esa es la respuesta final y la devuelves.

El valor max_steps establece un límite de pasos, la red de seguridad que evita que el bucle se descontrole, de lo cual trata la siguiente sección. La forma de este código corresponde al SDK de un proveedor; los nombres de los campos varían entre proveedores, pero el bucle es el mismo en todas partes.

JunoUn agente mínimo Un agente mínimo es un bucle alrededor de una llamada al modelo: ejecutas el modelo, ejecutas cualquier herramienta que pida, devuelves los resultados, repites. Cuando el modelo devuelve texto en lugar de una llamada a herramienta, ese texto es la respuesta final. El límite de pasos es una red de seguridad obligatoria, no algo extra que agregas después.

Aquí está el bucle en código, reutilizando las definiciones e implementaciones de herramientas de uso de herramientas. Corre hasta que el modelo deja de pedir herramientas o alcanza el límite de pasos.

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content  # respuesta final

        for call in calls:
            args = json.loads(call.function.arguments)
            try:
                result = tool_impls[call.function.name](args)
            except Exception as err:
                result = {"error": str(err)}  # muestra la falla, no dejes que reviente
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "Detenido: el agente alcanzó su límite de pasos."

La forma corresponde al SDK de un proveedor y los nombres de los campos varían, pero todos los bucles tienen estas partes: agregar el mensaje del modelo, decidir si pidió herramientas, ejecutar las solicitadas, devolver cada resultado como un mensaje tool asociado a su id de llamada.

El único cambio que vale la pena hacer respecto a la versión sin adornos es el try/except alrededor de la herramienta. Cuando una herramienta falla, no dejes que la excepción mate el bucle. Captúrala y devuelve el error al modelo como resultado de la herramienta. El modelo puede entonces leer "esa búsqueda falló" en su siguiente turno y adaptarse: reintentar con argumentos distintos, probar otra herramienta, o decirle al usuario que no pudo completar la tarea. Un fallo que revienta no le da al modelo ninguna oportunidad de recuperarse; este patrón de error-como-resultado lo mantiene dentro del bucle con información sobre la cual actuar.

Hay dos cosas que rastrear mientras esto corre. Primero, la conversación solo crece. Cada turno agrega el mensaje del modelo y cada resultado de herramienta, así que en el paso cinco el modelo está leyendo de nuevo todo lo de los pasos uno al cuatro. Esa es la memoria del agente y también su factura: cada paso reenvía todo el contexto acumulado, así que el costo en tokens por paso sube conforme avanza la tarea. Un agente de diez pasos no es diez llamadas baratas, es diez llamadas sobre una transcripción cada vez más grande.

Segundo, ese crecimiento es la razón por la que max_steps importa más allá de detener bucles infinitos. Elígelo según la tarea. Una pregunta sobre el clima necesita dos o tres pasos; una tarea de investigación puede necesitar diez. Fija el límite un poco por encima de lo que toma una ejecución normal, así una tarea legítimamente más larga puede terminar, pero una que se atasca igual se corta antes de que agote tu presupuesto.

JunoUn agente mínimo El bucle es: agregar el mensaje del modelo, decidir si pidió herramientas, ejecutarlas, devolver cada resultado como un mensaje tool. Envuelve la llamada a la herramienta en try/except y devuelve los errores en lugar de reventar, así el modelo puede reintentar o recuperarse. Ten en cuenta que la conversación solo crece: cada paso reenvía toda la transcripción, así que el costo en tokens por paso sube conforme avanza la tarea. Fija max_steps según la tarea, un poco por encima de una ejecución normal.

El bucle, reutilizando la capa de herramientas de uso de herramientas. La forma corresponde al SDK de un proveedor, los nombres de los campos varían, la estructura no.

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content

        for call in calls:
            args = json.loads(call.function.arguments)
            try:
                result = tool_impls[call.function.name](args)
            except Exception as err:
                result = {"error": str(err)}  # el modelo lee esto y puede adaptarse en el siguiente turno
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "Detenido: el agente alcanzó su límite de pasos."

El bucle sin adornos es correcto pero no está listo para producción, y la brecha entre ambos es de lo que trata esta sección. Tres propiedades de este código causan problemas en producción.

Muestra los errores, nunca dejes que revienten. El try/except devuelve una herramienta fallida al modelo como un resultado que puede leer. Eso está bien, pero entiende lo que estás haciendo: le estás entregando al modelo una cadena de error y confiando en que se recupere de manera sensata. Puede reintentar la misma llamada mala, o inventar un enfoque distinto, o disculparse y detenerse.

Devolver los errores mantiene al agente vivo; no hace que la recuperación sea confiable. Para cualquier cosa crítica, limita los reintentos por herramienta y trata la falla repetida como un estado terminal que tú manejas, no como un bucle que dejas que el modelo resuelva por intuición.

La transcripción solo crece, y eso genera dos costos que se acumulan. El costo en tokens por paso sube porque cada llamada reenvía todo el historial acumulado, así que una ejecución larga paga una factura que crece en cada turno, no una fija. Y cuanto más larga sea la transcripción, más está leyendo el modelo salidas de herramientas antiguas para decidir el siguiente movimiento, que es justo donde empieza a manifestarse el efecto de pérdida en el medio del capítulo sobre la ventana de contexto, donde un modelo presta menos atención a la información enterrada en medio de un contexto largo: las instrucciones iniciales que deberían restringir al agente quedan hundidas bajo los resultados acumulados y reciben menos atención. Los agentes largos no fallan de forma ruidosa, se desvían poco a poco.

max_steps es un presupuesto, no una protección contra errores. Existe porque el modelo decide cuándo detenerse y puede decidir mal: dar vueltas en un paso, rebotar entre dos herramientas, perseguir un callejón sin salida.

El número es un tope de costo real. En el peor caso, el gasto es aproximadamente max_steps multiplicado por el costo de una llamada con contexto completo cerca del final de la ejecución, así que un límite generoso en una tarea que consume mucho contexto es una factura generosa. Fíjalo a partir de la ejecución legítima más larga más un margen, activa una alarma cuando las ejecuciones lo alcancen de manera rutinaria (esa es una señal de que el agente está atascado, no de que el límite sea demasiado bajo), y resiste la tentación de subirlo solo para disimular un agente que no puede terminar.

JunoUn agente mínimo El bucle sin adornos es correcto pero no está listo para producción. Devuelve los errores de herramientas al modelo para que pueda adaptarse, pero limita los reintentos y trata la falla repetida como terminal, porque mostrar un error no hace que la recuperación sea confiable. La transcripción solo crece, así que el costo en tokens por paso sube y tus instrucciones iniciales quedan enterradas bajo resultados antiguos hasta que el agente se desvía. max_steps es un tope de costo, no una protección contra errores: dimensiónalo según la ejecución real más larga más un margen, y cuando las ejecuciones lo alcancen de manera constante, el agente está atascado, así que no lo subas por reflejo.

Detenerse y salvaguardas ​

Un bucle que deja que un modelo decida cuándo detenerse puede no lograr detenerse. Puede llamar herramientas para siempre, repetirse, o terminar en un callejón sin salida. Como cada paso es una llamada al modelo cobrada por tokens, un agente descontrolado gasta dinero y tiempo rápidamente.

Por eso las salvaguardas, los límites que pones alrededor del bucle, son parte del diseño, no un detalle que agregas al final:

  • Un límite de pasos. Limita el número de vueltas, tal como lo hace max_steps. Cuando se alcanza, detente y devuelve el resultado.
  • Valida las entradas de las herramientas. El modelo elige los argumentos, así que revísalos antes de ejecutar cualquier cosa con consecuencias reales.
  • Limita lo que las herramientas pueden hacer. Dale al agente el mínimo poder que necesita. Una herramienta que solo lee es más segura que una que borra.
  • Vigila el costo. Varias llamadas al modelo por tarea se multiplican rápido, así que rastrea los tokens y fija un presupuesto.

El hilo que une todo esto: el modelo está improvisando el camino, así que tú pones los límites que él no va a poner. Asume que el agente hará algo incorrecto al menos una vez, y haz que eso sea sobrevivible.

JunoDetenerse y salvaguardas Un agente decide su propio punto de detención, así que puede quedarse dando vueltas para siempre, y cada vuelta cuesta tokens. Siempre fija un límite de pasos, valida los argumentos que elige el modelo, y dale a las herramientas el mínimo poder que necesitan. Rastrea el costo, porque varias llamadas al modelo por tarea se suman rápido.

Un bucle donde el modelo decide cuándo detenerse puede no lograr detenerse, y como cada paso es una llamada al modelo cobrada por tokens, un agente atascado gasta presupuesto rápido. Las salvaguardas son parte del diseño. Las cuatro que hay que incorporar:

  • Un límite de pasos. Limita las vueltas con max_steps y devuelve el resultado de forma limpia cuando se alcance. Este es tu freno duro contra bucles descontrolados.
  • Valida las entradas de las herramientas. El modelo elige los argumentos, y puede elegir mal o ser manipulado para elegir mal. Revísalos antes de que corra cualquier herramienta con consecuencias reales: un borrado sin id, una transferencia con un monto negativo, una ruta fuera del directorio permitido.
  • Mínimo poder. Dale a cada herramienta la capacidad más estrecha que la tarea necesita. Solo lectura es mejor que lectura y escritura, una consulta acotada es mejor que acceso crudo a la base de datos, una lista fija de destinatarios es mejor que envío arbitrario.
  • Tope de costo. Rastrea los tokens de toda la ejecución, no por llamada, y detente cuando una ejecución supere un presupuesto.

El punto que une todo esto es que los argumentos de tus herramientas vienen del modelo, lo cual significa que vienen, indirectamente, de cualquier texto que el modelo haya leído. Si una herramienta trajo una página web y esa página contenía instrucciones, esas instrucciones ahora están en el contexto del modelo y pueden dirigir la siguiente llamada a una herramienta. Esto es inyección de prompt: texto no confiable en el contexto influyendo en lo que hace el agente. La defensa no está en el prompt. Está en validar cada entrada de herramienta y acotar el poder de cada herramienta para que incluso un argumento completamente secuestrado no pueda causar daño real.

JunoDetenerse y salvaguardas Cuatro salvaguardas, por diseño y no como detalle final: un freno duro con max_steps, validación de entradas en cada herramienta con consecuencias, mínimo poder en el alcance de las herramientas, y un presupuesto de tokens para toda la ejecución. La razón por la que la validación de entradas importa: los argumentos de las herramientas vienen del modelo, es decir, de cualquier texto que haya leído, así que una página traída con instrucciones es inyección de prompt que puede dirigir la siguiente llamada. Valida las entradas y acota el poder para que un argumento secuestrado tampoco pueda causar daño.

Un bucle donde el modelo decide cuándo detenerse puede no lograr detenerse, y cada paso es una llamada cobrada por tokens, así que el modo de falla es costoso por defecto. Las cuatro salvaguardas (límite de pasos, validación de entradas, mínimo poder, tope de costo) son lo mínimo indispensable. La parte que merece tu atención es por qué la validación de entradas es un control de seguridad, no una simple verificación de sensatez.

Los argumentos de las herramientas son salida del modelo, y la salida del modelo está condicionada por todo lo que hay en el contexto, incluyendo texto que el agente trajo desde afuera. En el momento en que un agente lee una página web, un documento, un correo, o el resultado de una herramienta que no controlas, hay texto no confiable en su contexto y ese texto puede llevar instrucciones. Eso es inyección de prompt: contenido adversarial en la entrada que dirige al modelo hacia acciones que no querías. En un prompt de un solo turno es una molestia. En un agente es un exploit activo, porque el siguiente movimiento del modelo es una llamada a una herramienta con efecto en el mundo real, y el texto inyectado puede influir en esa llamada.

Diséñalo asumiendo que es adversarial, porque lo es. Tres reglas se mantienen firmes:

  • Valida cada argumento de herramienta contra una lista de lo permitido, no de lo prohibido. Define cómo se ve un argumento válido (este formato de id, este conjunto de destinatarios, este directorio) y rechaza todo lo demás. No puedes enumerar cada entrada mala que un atacante pueda inventar; sí puedes enumerar las buenas.
  • Acota el poder de las herramientas para que una llamada totalmente secuestrada sea sobrevivible. Asume que el argumento está controlado por un atacante y pregúntate qué podría hacer entonces la herramienta. Si la respuesta real es "enviar correo a cualquiera" o "borrar cualquier fila", la herramienta es demasiado amplia sin importar cuán cuidadoso sea el prompt. El mínimo poder es el control que se mantiene cuando el modelo está comprometido, y el prompt no es ningún control en absoluto.
  • Pon a una persona en el circuito para las acciones irreversibles. Enviar dinero, borrar datos, escribir a clientes: condiciona esto a una confirmación. El agente propone, una persona o una verificación más estricta dispone.

La razón más profunda por la que nada de esto vive en el prompt: las instrucciones del prompt del sistema y las instrucciones inyectadas en el contenido traído desde afuera llegan como el mismo tipo de cosa, texto en el contexto, y el modelo no tiene ninguna forma confiable de darle más peso a una que a la otra. Así que no puedes lograr seguridad solo con el prompt. La frontera que se sostiene está afuera del modelo: entradas validadas y herramientas acotadas. Esto se conecta con el tratamiento más amplio en seguridad y límites.

JunoDetenerse y salvaguardas Las cuatro salvaguardas son lo mínimo indispensable; la que merece más reflexión es la validación de entradas, porque es un control de seguridad. Los argumentos de las herramientas son salida del modelo condicionada por todo lo que leyó, así que cualquier página o correo traído desde afuera puede llevar instrucciones inyectadas que dirijan la siguiente llamada, y en un agente esa llamada tiene efecto en el mundo real. Valida contra una lista de lo permitido, acota cada herramienta para que un argumento secuestrado siga siendo sobrevivible, y condiciona las acciones irreversibles a la aprobación de una persona. No puedes lograr seguridad solo con el prompt: las instrucciones inyectadas y las del sistema son el mismo tipo de texto para el modelo, así que la frontera tiene que vivir fuera de él.

Cuándo un workflow es mejor que un agente ​

Los agentes son emocionantes, lo cual hace tentador recurrir a uno cuando en realidad no lo necesitas. La regla simple: si ya conoces los pasos, no uses un agente. Escríbelos como código plano, un workflow, donde cada paso corre en un orden fijo.

Un workflow es más confiable, más económico, y mucho más fácil de depurar, porque tú controlas el camino en lugar de esperar que el modelo lo encuentre. Reserva los agentes para tareas abiertas donde los pasos dependen de lo que se va descubriendo en el camino.

Muchas funciones que parecen necesitar un agente en realidad funcionan mejor como una llamada de salida estructurada o una consulta de RAG armada a mano. Recurre a un agente solo cuando no puedas escribir los pasos de antemano.

JunoCuándo un workflow es mejor que un agente Si ya conoces los pasos, escríbelos directamente como un workflow en lugar de usar un agente: es más económico, más confiable, y más fácil de depurar. Reserva los agentes para tareas abiertas donde los pasos dependen de lo que se descubre en el camino. Muchas funciones "de agente" en realidad son una llamada de salida estructurada o de RAG armada a mano.

Los agentes son la herramienta que emociona, y por eso mismo se recurre a ellos cuando no corresponde. La regla de decisión se reduce a una pregunta: ¿puedes escribir los pasos de antemano? Si la respuesta es sí, quieres un workflow, los pasos como código plano en un orden fijo, no un agente.

Un workflow gana en todo aquello donde un agente tiene dificultades. Es más económico, porque haces una o dos llamadas al modelo en lugar de un bucle de ellas. Es más confiable, porque el camino es fijo en lugar de decidirse de nuevo en cada turno. Y es mucho más fácil de depurar, porque una falla ocurre en un paso conocido que puedes inspeccionar, no en algún punto de una cadena de movimientos elegidos por el modelo.

Aquí está la prueba en la práctica. "Resume este ticket de soporte, clasifica su urgencia y enrútalo a una cola" tiene pasos conocidos en un orden conocido, así que es un workflow: una llamada de salida estructurada para obtener el resumen, la categoría y la urgencia, y luego código plano para enrutar según el resultado. "Investiga por qué fallaron las últimas tres órdenes de este cliente" no tiene pasos conocidos, el camino depende de lo que revele cada búsqueda, así que ahí sí es un agente.

La trampa es que muchas funciones parecen abiertas y en realidad no lo son. Extraer campos de un documento, responder a partir de tu documentación, clasificar correo entrante: esto suena a trabajo de agente pero se reduce a una llamada de salida estructurada o una consulta de RAG con código alrededor. Por defecto ve al workflow y deja que una tarea se gane el derecho a usar un agente siendo impredecible de una forma que no puedes anticipar en código.

JunoCuándo un workflow es mejor que un agente La decisión se reduce a una pregunta: ¿puedes escribir los pasos de antemano? Si sí, construye un workflow, los pasos como código plano, porque es más económico, más confiable, y depurable en un punto conocido. "Resumir, clasificar y enrutar un ticket" es un workflow: una llamada de salida estructurada más código de enrutamiento. "Investigar por qué fallaron estas órdenes" es un agente, porque el camino depende de lo que encuentre cada paso. Ve al workflow por defecto y haz que la tarea se gane el derecho a usar un agente.

El agente es la herramienta que la gente quiere usar, y por eso se usa donde no corresponde. La regla de decisión es corta: si puedes escribir los pasos de antemano, escríbelos. Eso es un workflow, los pasos como código en un orden fijo, y gana a un agente en costo, confiabilidad y facilidad de depuración para cualquier tarea cuya forma conoces.

La razón se remonta directamente a la arquitectura. Un agente no tiene un plan global y acumula errores hacia adelante, así que su confiabilidad es el producto de que cada paso salga bien sin que nada verifique el conjunto. Un workflow que escribiste tiene un plan, por definición, y puedes inspeccionar, probar y validar cada paso por separado. Cuando algo se rompe en un workflow, se rompe en una línea de código. Cuando algo se rompe en un agente, se rompe en algún punto de una transcripción de movimientos elegidos por el modelo, y tienes que reconstruir qué estaba pensando a partir del rastro.

Ahora el caso más difícil, porque "¿conozco los pasos?" es la mitad sencilla. Un agente puede ser la herramienta equivocada incluso cuando la tarea es abierta, cuando el costo de un paso equivocado es demasiado alto para dejarlo en manos de algo que solo adivina el siguiente paso. Un agente que reserva viajes, mueve dinero o modifica datos de producción es abierto y también un lugar donde no quieres un bucle no planeado, susceptible a inyección y que acumula errores, sosteniendo los controles. El diseño correcto ahí suele ser híbrido: el modelo planifica o propone, pero un workflow fijo y controles humanos ejecutan, de manera que la parte impredecible nunca toca directamente la parte irreversible.

Así que la pregunta en realidad son dos preguntas. ¿Conoces los pasos, y qué cuesta un paso equivocado?

Los pasos conocidos van a un workflow. Los pasos desconocidos con acciones baratas y reversibles son donde un agente se gana su lugar. Los pasos desconocidos con acciones costosas e irreversibles necesitan un diseño acotado, no un bucle que corra libremente.

Un agente le queda bien al trabajo abierto con pasos baratos y reversibles, y poco más. Una proporción sorprendente de las funciones "de agente" en realidad son una llamada de salida estructurada o una consulta de RAG con código alrededor, y les conviene seguir siendo eso.

JunoCuándo un workflow es mejor que un agente Dos preguntas, no una: ¿conoces los pasos, y qué cuesta un paso equivocado? Los pasos conocidos van a un workflow, que gana a un agente en costo, confiabilidad y depuración porque tiene un plan y el agente nunca lo tiene. Los pasos desconocidos con acciones baratas y reversibles son donde un agente se gana su lugar. Los pasos desconocidos con acciones costosas e irreversibles necesitan un híbrido: el modelo propone, un workflow fijo y controles humanos ejecutan, de manera que el bucle que acumula errores nunca toca la parte que no puedes deshacer.

En la práctica ​

La función run_agent de arriba es todo el patrón. Dale una pregunta, un conjunto de herramientas y sus implementaciones, y repite el ciclo hasta terminar o hasta alcanzar el límite de pasos. Una tarea pequeña muestra al bucle demostrando su utilidad:

python
answer = run_agent(
    "¿Cómo está el clima en Lima y debería llevar sombrilla?",
    tools,        # incluye get_weather del capítulo de uso de herramientas
    tool_impls,   # {"get_weather": ...}
)
# El agente llama a get_weather, lee "nublado", y luego responde en un turno final:
# "Está nublado en Lima a 18 grados, así que llevar sombrilla es buena idea."

Una herramienta, un bucle, una respuesta. La misma estructura escala a varias herramientas y varios pasos sin cambiar de forma. Una vez que puedas construir cosas así de capaces, la siguiente pregunta es cómo sabes que en realidad funcionan, que es de lo que trata evals.

JunoEn la práctica El bucle de run_agent es todo el patrón: le das una pregunta, herramientas y sus implementaciones, y repite el ciclo hasta que el modelo deja de pedir herramientas o alcanza el límite de pasos. Una herramienta y un bucle escalan a muchas sin cambiar de forma. La siguiente pregunta es cómo sabes que en realidad funciona, que es evals.

La función run_agent es todo el patrón. Dale una pregunta, herramientas y sus implementaciones, y repite el ciclo hasta que el modelo deja de pedir cosas o alcanza el límite.

python
answer = run_agent(
    "¿Cómo está el clima en Lima y debería llevar sombrilla?",
    tools,        # incluye get_weather del capítulo de uso de herramientas
    tool_impls,   # {"get_weather": ...}
)
# El agente llama a get_weather, lee "nublado", y luego responde en un turno final.

Una herramienta, un bucle, una respuesta, y la misma forma escala a varias herramientas y varios pasos. Lo que no escala gratis es tu confianza en que funciona. Un workflow lo puedes probar paso por paso; un agente toma un camino distinto según la entrada, así que una ejecución que funcionó ayer te dice poco sobre la ejecución que falla hoy.

Por eso lo siguiente que hay que construir junto a un agente es una forma de medirlo: correrlo sobre un conjunto de tareas representativas y revisar los resultados, en lugar de confiar en una sola demostración exitosa. Convertir "funcionó cuando lo probé" en un número que puedas rastrear es exactamente de lo que trata evals.

JunoEn la práctica El bucle de run_agent es todo el patrón, y una herramienta y un bucle escalan a muchas sin cambiar de forma. El detalle es la confianza: un agente toma un camino distinto según la entrada, así que una buena demostración prueba poco sobre la siguiente ejecución. Construye una forma de medirlo sobre tareas representativas en lugar de confiar en un solo éxito, que es para lo que sirve evals.

La función run_agent es todo el patrón, y el ejemplo de abajo es lo mínimo posible: una herramienta, un bucle, una respuesta.

python
answer = run_agent(
    "¿Cómo está el clima en Lima y debería llevar sombrilla?",
    tools,        # incluye get_weather del capítulo de uso de herramientas
    tool_impls,   # {"get_weather": ...}
)
# get_weather devuelve "nublado", el modelo responde en un turno final.

La forma escala a muchas herramientas y muchos pasos sin cambiar, y ahí está la trampa, porque los modos de falla escalan junto con ella mientras el código se mantiene igual. Un agente depende del camino: entradas distintas producen secuencias distintas de pasos elegidos por el modelo, así que probar entrada por entrada te dice casi nada sobre la entrada que no has visto. La no determinación que viene del muestreo hace que incluso la misma entrada pueda tomar un camino distinto dos veces.

Así que lo que hay que construir junto a un agente es medición, y es un tipo de medición distinto al que necesita un workflow. No estás afirmando una única salida esperada; estás muestreando muchas tareas representativas y leyendo la distribución de resultados: con qué frecuencia termina dentro del presupuesto, con qué frecuencia llega a la respuesta correcta, dónde se queda dando vueltas, cuánto cuesta en los casos extremos. Esa es la versión con forma de agente de evals, y es la única manera de que las preocupaciones de confiabilidad, costo y seguridad de las secciones anteriores se conviertan en números que puedas defender en lugar de una demostración en la que tuviste suerte.

JunoEn la prácticarun_agent es todo el patrón y escala en forma mientras los modos de falla escalan con ella. Un agente depende del camino y el muestreo agrega no determinación, así que probar entrada por entrada te dice poco y una buena demostración prueba menos. Mídelo a la manera de un agente: muestrea muchas tareas representativas y lee la distribución, con qué frecuencia termina dentro del presupuesto, dónde se queda dando vueltas, cuánto cuestan los casos extremos. Para eso sirve evals, y así las preocupaciones de confiabilidad y costo de arriba se convierten en números que puedes defender.