Una de las formas más claras de entender LangGraph es bajar al terreno del código y observar qué aporta frente a una implementación clásica con llamadas encadenadas al modelo. El ejemplo que se muestra a continuación es deliberadamente sencillo, pero contiene casi todos los elementos que aparecen en sistemas reales: estado compartido, uso de herramientas, bucles de decisión y finalización controlada.
El objetivo del caso de uso es simple: permitir que un agente interprete una instrucción, decida qué operaciones necesita ejecutar, llame a las herramientas correspondientes y, cuando ya no haya más acciones pendientes, genere una respuesta final en lenguaje natural.
Definiendo el estado del agente
LangGraph gira alrededor de un concepto central: el estado. En este ejemplo, el estado se define como una estructura tipada (AgentState) que contiene una lista de mensajes. No es un detalle menor: todos los nodos del grafo leen y escriben sobre ese mismo estado.
class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], add_messages]
El uso de add_messages indica a LangGraph cómo debe combinar los mensajes nuevos con los existentes. Esto permite que el historial de la conversación vaya creciendo de forma controlada y que cada paso tenga acceso al contexto completo.
Herramientas: lógica explícita fuera del modelo
Las herramientas (tools) representan operaciones deterministas que el modelo puede invocar cuando lo considere necesario. En este caso son funciones aritméticas simples (add, subtract, multiply), pero el patrón es el mismo que se usaría para acceder a bases de datos, APIs externas o sistemas internos.
Cada herramienta:
- tiene una firma clara,
- recibe argumentos tipados,
- y devuelve un resultado directo.
Esto separa de forma limpia el razonamiento (qué hacer) de la ejecución (cómo se hace), algo fundamental para mantener sistemas complejos.
El nodo del agente: decidir y delegar
El nodo principal del grafo es el agente (our_agent). Su responsabilidad no es ejecutar cálculos, sino interpretar el estado actual y decidir el siguiente paso. En la práctica, esto se traduce en una llamada al modelo con el historial de mensajes y un system prompt que define su rol.
def model_call(state: AgentState) -> AgentState:
response = model.invoke([system_prompt] + state["messages"])
return {"messages": [response]}
El modelo puede devolver:
- una respuesta final en texto, o
- una o varias llamadas a herramientas (
tool_calls).
La clave es que no se asume de antemano cuál de las dos cosas ocurrirá.
Decidir si el flujo continúa o termina
Aquí es donde LangGraph empieza a diferenciarse claramente de una cadena tradicional. Tras cada ejecución del agente, se evalúa el estado para decidir si el grafo debe continuar o finalizar.
def shoud_continue(state: AgentState):
last_message = state["messages"][-1]
if not last_message.tool_calls:
return "end"
else:
return "continue"
Esta función actúa como un nodo de decisión: si el modelo no ha solicitado ninguna herramienta, el flujo termina; si las ha solicitado, se pasa al nodo encargado de ejecutarlas.
Este patrón es extremadamente común en agentes reales y suele acabar implementado con lógica poco clara cuando no se usa un enfoque basado en grafos.
El grafo como estructura explícita
Con todos los componentes definidos, el grafo se construye de forma declarativa:
- un nodo para el agente,
- un nodo para las herramientas,
- un punto de entrada,
- transiciones condicionales,
- y un bucle controlado entre agente y herramientas.
graph.add_conditional_edges(
"our_agent",
shoud_continue,
{
"continue": "tools",
"end": END
}
)
graph.add_edge("tools", "our_agent")
El resultado es un flujo muy claro:
- El agente analiza la petición.
- Si necesita herramientas, se ejecutan.
- El resultado vuelve al agente.
- El proceso se repite hasta que no hay más acciones pendientes.
Además, el propio grafo puede imprimirse o visualizarse, lo que facilita entender y depurar el comportamiento del sistema.
Qué ocurre durante la ejecución
En la ejecución mostrada, el comportamiento del sistema es coherente con la estructura del grafo:
- El agente identifica que debe sumar 40 y 12.
- Solicita la herramienta
add. - Con el resultado (52), solicita
multiply. - Una vez resueltas las operaciones, ya no hay más llamadas a herramientas.
- El agente genera una respuesta final que combina el resultado numérico con texto adicional.
Este ciclo de razonar → actuar → razonar ocurre de forma explícita y controlada, sin lógica implícita ni bucles opacos.
Conclusión
Este ejemplo ilustra bien el valor práctico de LangGraph. No aporta “inteligencia extra” al modelo, pero sí una estructura clara para organizar flujos agentivos que, de otro modo, acabarían siendo difíciles de seguir y mantener. Al hacer explícitos el estado, las decisiones y los ciclos, el comportamiento del sistema resulta más predecible, trazable y extensible.
A partir de aquí, escalar el diseño hacia casos más complejos —más herramientas, varios agentes, validadores intermedios o persistencia de estado— es una evolución natural, no un rediseño completo.
