Un agente es un bucle while: dónde se utilizan LangChain create_agent y LangGraph Fit.
Un agente de llamada a herramientas en veinte líneas, los cuatro problemas de producción que se presentan con bucles y cuándo pasar de LangChain create_agent a los gráficos de estado de LangGraph.
Fuentes: An Agent Is a While Loop
El uso de herramientas recibe mucha atención, pero lo que determina cuándo llamar a una herramienta, qué hacer con el resultado y cuándo detenerse es el bucle que rodea al modelo. La gente denomina a ese bucle orquestación, un término que hace que suene más importante de lo que es en realidad. La forma más sencilla de comprenderlo es observar primero todo el proceso completo y luego analizar por qué no es suficiente para su uso en entornos de producción.
Un agente completo en unas veinte líneas
Tomemos el intercambio de llamadas a herramientas, donde el modelo solicita una herramienta, su código la ejecuta y el resultado vuelve al modelo, y rodeemos todo esto con un bucle while. Primero se inicia la conversación:
messages = [system_prompt, user_question]
Luego, el bucle en sí:
while True:
reply = model(messages, tools=TOOLS) if not reply.tool_calls:
return reply.text # the model answered; done for call in reply.tool_calls:
result = TOOLS[call.name](**call.args) # your code runs it
messages.append(tool_result(call.id, result))
Ese es un agente real, no uno de dibujos animados. El modelo elige qué herramienta utilizar. Tu código la ejecuta y agrega el resultado. Esto se repite hasta que el modelo devuelve texto en lugar de una solicitud de herramienta.
Si te parece un poco decepcionante que sea tan pequeño, esa reacción es precisamente el objetivo. Todo lo que proporciona un framework es algo que añades una vez que este bucle llegue a la producción.
Una ejecución, paso a paso
Imagina un agente de triaje de soporte técnico al que le preguntan por qué las sincronizaciones nocturnas con los proveedores han fallado con el error ERR_4412 desde el lanzamiento de diciembre. Entra en posesión de una respuesta tras tres intentos, dentro de un único bucle sin framework alguno.
Turno 1. El modelo aún no responde. Emite una solicitud, search_runbooks("ERR_4412"), y el bucle la ejecuta. Regresan tres resultados, y el primero indica que el error se debe a un token de autenticación del proveedor vencido. Eso se agrega a los mensajes.
Turno 2. Después de leer eso, el modelo solicita get_release_notes("december"). Un documento indica que el intervalo de renovación del token se redujo de 24 horas a 12. Se vuelve a añadir al resultado.
Turno 3. Con ambos resultados en mano, el modelo responde en texto plano sin realizar ninguna solicitud de herramienta. Las sincronizaciones que se ejecutan durante la noche duran más de doce horas, por lo que el token expira en medio de una ejecución. Al no haber solicitud alguna para ejecutar, el bucle finaliza.
El modelo eligió las herramientas y ejecutó sus acciones. La lista de mensajes aumentó en dos resultados, y no ocurrió nada más.
Qué falla después de una semana de funcionamiento
Suele aparecer cuatro problemas en entornos de producción, generalmente en este orden. Ninguno afecta al modelo; todos se refieren al entorno de ejecución que lo rodea.
El reinicio. En la segunda vuelta se queda atascado en un sistema lento debido a un incidente; tras ocho minutos, el contenedor se recicla. Dado que messages solo existía en memoria, este desaparece y la ejecución comienza de nuevo desde el punto inicial. La solución es guardar la conversación después de cada vuelta y reanudar desde esa copia de seguridad.
La herramienta peligrosa. Otra noche, en la cuarta vuelta, el modelo concluye que la solución es rollback_release("dec-2025"). Dejar que un modelo haga eso solo a las 3 a.m. no es algo que nadie quiera. El bucle debe detenerse, consultar a una persona, esperar, posiblemente hasta la mañana, y luego continuar exactamente desde donde se detuvo. Un simple bucle while no puede esperar hasta la mañana.
El giro equivocado. En el paso 5 se elige una consulta de búsqueda inadecuada, y los pasos del 6 al 16 repiten esa búsqueda con ligeras modificaciones en la redacción, siendo cada una de ellas facturada. Mirar una lista de mensajes de dieciséis elementos no muestra dónde ocurrió el error. Lo que ayuda es establecer un límite en el número de pasos y registrar un rastro de cada uno de ellos para poder reproducirlo.
Qué dirección tomar. Los errores de autenticación requieren una secuencia de pasos distinta a la de los errores de datos, y cuando dos herramientas discrepan, el caso debe ser llevado a un humano. Un modelo es competente para elegir una herramienta, pero no debería improvisar el flujo de control de manera diferente en cada ejecución. Las ramificaciones deben ser anotadas para que se comporten de la misma forma en todas las ocasiones.
Mira de nuevo a los cuatro. Ninguno culpa a un modelo inteligente o torpe. Todos se deben al código circundante, es decir, a lo que persiste, cuándo se detiene, qué registra y quién elige la ruta. La orquestación es esa capa circundante, por lo que un bucle de veinte líneas puede estar perfectamente bien y aún así ser un punto por el que pasar.
Convierte los pasos en cajas
Dibuja nuevamente la misma ejecución con cada paso como una caja conectada por flechas: clasificar, buscar manuales de procedimientos, obtener notas de lanzamiento, proponer una solución, aprobar y luego aplicarla o responder. Al tener los pasos como cajas, aparecen tres nuevas capacidades.
- Cada caja termina guardando el estado en un almacenamiento duradero, de modo que después de un reinicio la ejecución continúa desde la última caja completada y no desde el principio.
- Cualquier caja puede pausar toda la ejecución y esperar a una persona el tiempo que sea necesario, con el estado guardado de forma segura.
La ramificación se encuentra en la casilla de clasificación, que incluye una ruta de autenticación, una ruta de datos y un mecanismo de escalada. Tú dibujaste esas tres flechas. El modelo sigue eligiendo herramientas dentro de una ruta, pero la ruta en sí es tuya.
El modelo no cambió. El bucle adquirió una estructura que se puede ver, guardar e interrumpir.
Qué es LangChain
LangChain es una biblioteca en Python, con su equivalente en JavaScript, que proporciona componentes listos para usar en aplicaciones de LLM, de modo que no sea necesario reescribir siempre la misma lógica. Hay tres tipos de componentes importantes.
Envoltorios de modelos. Una única interfaz para todos los proveedores. ChatAnthropic, ChatOpenAI y ChatGoogleGenerativeAI exponen todos la misma función .invoke(messages), por lo que cambiar de proveedor consiste únicamente en realizar una edición sencilla y no en reescribir el código de la solicitud.
Integraciones. Adaptadores para todo lo que rodea al modelo: almacenamientos vectoriales, cargadores de documentos, recuperadores de información, modelos de incrustación y varios cientos de herramientas externas. Aquí radica la mayor parte del ahorro de esfuerzo, ya que de lo contrario cada adaptador requeriría ser escrito y mantenido por usted.
Bucle de agente empaquetado. Desde la versión 1.0 en octubre de 2025, la función principal es create_agent, que se importa de esta manera:
from langchain.agents import create_agent
y se utiliza de esta manera:
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=[search_runbooks, get_release_notes],
system_prompt="You are the on-call triage assistant.",
)
result = agent.invoke({"messages": [("user", "Why is ERR_4412 failing?")]})
En efecto, el bucle mencionado anteriormente llega ya preescrito. También se admite middleware: pequeños complementos que se activan alrededor de una llamada a un modelo o a una herramienta. Los existentes permiten hacer una pausa para obtener la aprobación humana antes de que ejecute una herramienta, eliminar datos personales y resumir una conversación larga.
Lo que omite create_agent es el control del interior del bucle: no hay posibilidad de consultar el estado entre pasos, no existe pausa de un día entero, y si el proceso falla, todo se detiene con él.
Qué es LangGraph
Bajo create_agent se encuentra LangGraph, una biblioteca diferente del mismo creador. Mientras que LangChain proporciona un bucle ya listo, LangGraph ofrece las partes necesarias para construir el propio, siguiendo la estructura del grafo mostrado anteriormente. Tienes que definir tres elementos.
Estado. Un objeto tipado que se desplaza a través del flujo de ejecución. Para la triaje, contiene los mensajes recibidos hasta el momento, la clasificación del error, la solución propuesta y si ha sido aprobada.
Nodos. Funciones normales de Python que reciben el estado y devuelven actualizaciones. classify, search_runbooks, propose_fix y ask_human son simplemente funciones.
Aristas. El orden de ejecución. Las aristas simples son flechas fijas, mientras que las aristas condicionales son funciones que leen el estado y seleccionan el siguiente nodo, de modo que allí se expresa la separación entre autenticación y datos.
La importación:
from langgraph.graph import StateGraph
Y un gráfico creado a partir de esas piezas:
g = StateGraph(TriageState)
g.add_node("classify", classify)
g.add_node("search", search_runbooks)
g.add_node("propose", propose_fix)
g.add_node("approve", ask_human)
g.add_edge("classify", "search")
g.add_conditional_edges("search", route_by_error_type)
g.add_edge("propose", "approve")app = g.compile(checkpointer=PostgresSaver(...))
Una línea cerca del final es la clave: un checkpointer, que representa un lugar donde se puede guardar el estado y que se pasa al compilar el grafo. Gracias a él, el estado se escribe después de cada nodo. La posibilidad de reiniciar, usar interrupt() para esperar a una persona y rebobinar hasta un nodo para reproducir todo desde allí proviene de ese único argumento y no de código escrito a mano. Tu contribución son los recuadros y las flechas.
Así que el contraste es este: LangChain ofrece un bucle del cual no se puede ver el interior. LangGraph te pide que dibujes ese bucle, y a cambio puedes inspeccionarlo, guardarlo, detenerlo y reproducirlo. Las cuatro situaciones mencionadas anteriormente son los momentos en que no poder ver el interior deja de ser aceptable.
Una pila, dos puertas
Dado que create_agent está basado en un grafo de LangGraph, elegir entre LangChain o LangGraph no es una decisión relacionada con el framework. Se trata de decidir qué “puerta” utilizar, y ambas opciones se combinan. Un agente creado con create_agent es en sí mismo un grafo, lo que significa que puede colocarse como un nodo individual dentro de un StateGraph más grande. El grafo mayor se encarga de la clasificación, las aprobaciones y la persistencia, mientras que el agente interno se ocupa de las decisiones que debe tomar el modelo.
Utilice create_agent cuando necesite un agente funcional de inmediato y no le importe su estructura interna. Muchos agentes nunca requieren algo más que eso. Recurre a StateGraph cuando sea necesario examinar el estado durante la ejecución, esperar a una persona, recuperarse de un fallo o rebobinar, que son los mismos cuatro problemas mencionados anteriormente.
Los SDK de los proveedores Anthropic y OpenAI se encuentran al lado de esta pila en lugar de dentro de ella. Ejecutan el mismo bucle, vinculado a una familia de modelos, con la menor fricción si se utiliza un único proveedor. El precio a pagar es la portabilidad.
Consejos para un equipo
Escriba primero el bucle de veinte líneas, incluso si luego será descartado. Le tomará una hora, y después quedará claro qué está haciendo cada framework en su nombre, que es la única forma de depurarlo.
Cámbiese a LangGraph el día en que uno de esos cuatro problemas aparezca realmente, y no antes. Un chatbot que llama a tres herramientas y responde puede prescindir de un grafo. Un agente que debe sobrevivir a un reinicio, esperar aprobación o ser reproducido no puede hacerlo, y una ejecución duradera construida desde cero es un proyecto en sí mismo.
Los equipos suelen recurrir al gráfico desde el primer día para un problema que puede resolverse con un bucle simple, y luego pierden un cuarto del tiempo aprendiendo el framework, cuando ese tiempo debería destinarse al propio problema.